我无法正确编辑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页。
答案 0 :(得分:1)
我认为这里的问题是XML文本节点。 REXML实际上没有忽略空格,所以在你的元素之间你有文本节点导致输出看起来很奇怪。
例如,如果你在循环中查看parent.texts
,你会看到
["\n\t\t", "\n\t\t", "\n\t\t", "\n\t"]
这是您的元素之间的缩进。当您拨打delete_element
时,REXML不会触及周围的文本节点,这会导致空行出现在输出中。当您调用add_element
时,REXML会在最后一个文本节点之后插入元素,即在结束</option>
之前,这就是为什么您的新元素出现在错误的缩进级别。
我看到两个解决方案:
xmldoc.write(data, 4)
。但是,这也会在每个元素的文本节点上添加空格,即"bar"
变为"\n bar\n "
。坦率地说,REXML不是一个设计得很好的库。显然,它无法决定如何处理空白。你试过Nokogiri吗?