2014-06-12 72 views
0

我无法正确编辑XML文件。我想删除某些元素,然后添加新元素。漂亮的打印文件与REXML

<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中的问题。

几乎同样的问题,可以在著作“编程的Ruby和Pragmatic Programmers'指南”中可以看出726页

+3

对于它的价值,我得到了一个完全不同的输出,在Ruby 1.8.6(和2.1)上运行您的代码。你可以用粘贴的代码重现问题吗? –

+0

我认为这里的问题是'xmldoc.write(data,0)',它从输出中删除缩进。如果你摆脱了0,那么你会得到更像问题中的例子。 – Max

回答

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 "

坦率地说,REXML并不是一个设计精良的库。对于一个人来说,显然不能决定如何处理空白。你尝试过Nokogiri吗?