2017-07-16 78 views
0

我想使用Nokogiri压缩现有的XML。我有以下的演示代码:使用nokogiri的紧凑的现有XML

#!/usr/bin/env ruby 
require 'nokogiri' 

doc = Nokogiri.XML <<-XML.strip 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
XML 

doc.write_xml_to($stdout, indent: 0) 

我期望看到

<?xml version="1.0" encoding="UTF-8"?> 
<root><foo><bar>test</bar></foo></root> 

而是我看到

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 

我已经试过

doc.write_to($stdout, indent: 0, save_with: Nokogiri::XML::Node::SaveOptions::AS_XML) 

但没有按”不管工作。

如何删除可忽略的空格?

+0

https://stackoverflow.com/questions/8406251/nokogiri-to-xml-without-carriage-returns可能帮帮我。如果你有很多级别的数据,我会建议sub,但它不可行。唯一能想到的是使用正则表达式,但是如果你在XML属性或值中有很长的字符串,那么这可能也不起作用。 – whodini9

+1

@ whodini9我没有使用构建器,因为我的最终目标是压缩现有的XML文件。此外,根据Nokogiri的官方文档和源代码,'Node#write_xml_to'只需使用'save_with:DEFAULT_XML'选项调用'Node#write_to'。顺便说一句,'AS_XML'是'DEFAULT_XML'的别名。 –

回答

0

好的,我回答我自己的问题。

Nokogiri不删除空白,因为Nokogiri不知道白色空格是否可以忽略(没有DTD,没有模式),所以它将所有只有空白的文本保留为文本节点。在将XML文档写入IO设备之前,我应手动删除它们。

#!/usr/bin/env ruby 
require 'bundler' 
Bundler.require :default 

doc = Nokogiri.XML <<-XML.strip 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
XML 

# remove ignorable white spaces 
doc.xpath('//text()').each do |node| 
    node.content = '' if node.text =~ /\A\s+\z/m 
end 

doc.write_xml_to($stdout, indent: 0) 

这是我的一大进步,但我还没有达到我的目标,因为我工作的XML文件具有内嵌自闭的标签,还有那些之间的空白,只有文本节点不应压缩的标签。我试图找出一种方法来处理这个角落案例。

0

你可以告诉引入nokogiri忽略空文本节点,然后输出无压痕:

require 'nokogiri' 

xml = <<EOT 
<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <foo> 
    <bar>test</bar> 
    </foo> 
</root> 
EOT 

doc = Nokogiri::XML(xml) { |opts| 
    opts.noblanks 
    opts.strict.noblanks 
} 
doc.to_xml(:indent_text => '', :indent => 0) 
# => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + 
# "<root>\n" + 
# "<foo>\n" + 
# "<bar>test</bar>\n" + 
# "</foo>\n" + 
# "</root>\n"