使用REXML进行漂亮打印

时间:2014-06-12 09:15:23

标签: ruby xml rexml

我无法正确编辑XML文件。我想删除某些元素,然后添加新元素。

<project>
    <option>
        <name>foo</name>
        <state>0</state>
    </option>
    <option>
        <name>bar</name>
        <state>foo/apple</state>
        <state>foo/orange</state>
    </option>
</project>

我想删除state的苹果和橙子,并插入葡萄,柠檬和酸橙。我试过这段代码:

#!/usr/bin/ruby -w
require 'fileutils'
require 'rexml/document'
require 'find'
include REXML

path = 'C:\Users\GustavWi\Documents\Gustav\help.xml'
xmlfile = File.new(path)
xmldoc = Document.new(xmlfile)
str_new_elements =["grape","lemon","lime"]
xmldoc.elements.each("project/option") do |parent| 
    if parent.elements['name'].text == 'bar'
        parent.elements.each do |element|
        str = element.text.split('/')
            if str[0] == 'foo'
            parent.delete_element(element)
            end
        end
        str_new_elements.each do |dir|
            state = Element.new("state")
            state.text = dir
            parent.add_element(state)
        end
    end
end

File.open(path,"w") do |data|
        xmldoc.write(data)
end

问题是输出是:

<project>
    <option>
        <name>foo</name>
        <state>0</state>
    </option>
    <option>
        <name>bar</name>


    <state>grape</state><state>lemon</state><state>lime</state></option>
</project>

问题是新元素的空行和缺少的缩进。

我正在使用Ruby 1.8.6,这可能是一个问题,但我没有看到任何有关这是1.8.6中的问题的信息。

在书中可以看到几乎相同的问题&#34;编程Ruby实用程序员&#39;向导及#34;请参阅第726页。

1 个答案:

答案 0 :(得分:1)

我认为这里的问题是XML文本节点。 REXML实际上没有忽略空格,所以在你的元素之间你有文本节点导致输出看起来很奇怪。

例如,如果你在循环中查看parent.texts,你会看到

["\n\t\t", "\n\t\t", "\n\t\t", "\n\t"]

这是您的元素之间的缩进。当您拨打delete_element时,REXML不会触及周围的文本节点,这会导致空行出现在输出中。当您调用add_element时,REXML会在最后一个文本节点之后插入元素,即在结束</option>之前,这就是为什么您的新元素出现在错误的缩进级别。

我看到两个解决方案:

  1. 在输出之前用文本节点围绕猴子,以确保缩进很好。这看起来很难用REXML做,因为它很难让文本节点不受影响。
  2. 如果您不关心空格,请让REXML为您缩进:xmldoc.write(data, 4)。但是,这也会在每个元素的文本节点上添加空格,即"bar"变为"\n bar\n "
  3. 坦率地说,REXML不是一个设计得很好的库。显然,它无法决定如何处理空白。你试过Nokogiri吗?