如何将新节点添加到XML
我有一个简单的XML文件,items.xml:如何将新节点添加到XML
<?xml version="1.0" encoding="UTF-8" ?>
<items>
<item>
<name>mouse</name>
<manufacturer>Logicteh</manufacturer>
</item>
<item>
<name>keyboard</name>
<manufacturer>Logitech - Inc.</manufacturer>
</item>
<item>
<name>webcam</name>
<manufacturer>Logistech</manufacturer>
</item>
</items>
我试图插入下面的代码一个新的节点:
require 'rubygems'
require 'nokogiri'
f = File.open('items.xml')
@items = Nokogiri::XML(f)
f.close
price = Nokogiri::XML::Node.new "price", @items
price.content = "10"
@items.xpath('//items/item/manufacturer').each do |node|
node.add_next_sibling(price)
end
file = File.open("items_fixed.xml",'w')
file.puts @items.to_xml
file.close
然而此代码后,才最后<manufacturer>
节点,items_fixed.xml增加了一个新的节点:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<name>mouse</name>
<manufacturer>Logitech</manufacturer>
</item>
<item>
<name>keyboard</name>
<manufacturer>Logitech</manufacturer>
</item>
<item>
<name>webcam</name>
<manufacturer>Logitech</manufacturer><price>10</price>
</item>
</items>
为什么?
区分Node
(树中特定位置的特定结构化XML数据)和作为数据结构的“节点模板”将会有帮助。
Nokogiri(和大多数其他XML库)只允许指定Node
,而不是节点模板。所以当你创建price = Nokogiri::XML::Node.new "price", @items
时,你有一个特定的数据属于某个特定的地方,但尚未定义这个地方。
当您将其添加到第一个<item>
时,您已定义它的位置。当你将它添加到第二个<item>
时,你将它从它的位置拔下并放到一个新的地方。此时Node
只出现在第二个<item>
中。当您为每个项目添加相同的Node
时,这种情况会继续,直到您到达最后的<item>
,这是节点停留的地方。
Nokogiri没有任何方式指定节点模板。你需要做的是:
@items.xpath('//items/item/manufacturer').each do |node|
price = Nokogiri::XML::Node.new "price", @items
price.content = "10"
node.add_next_sibling(price)
end
我看到您在调试器中解释的确切行为,但无法理解它。谢谢你的解释和你的回答! – 2011-03-15 18:26:07
或者,您可能只需使用['Node#dup'](http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Node.html#M000469)在将节点插入新位置之前克隆节点。 – Phrogz 2011-03-21 19:40:57
很好的解释..自从去年3-4天以来,我遇到了同样的问题。现在我发现它为什么会发生。感谢OP和你。 – 2015-02-03 08:48:25
我这个启动:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>
<name>mouse</name>
<manufacturer>Logitech</manufacturer>
</item>
<item>
<name>keyboard</name>
<manufacturer>Logitech - Inc.</manufacturer>
</item>
</items>
EOT
doc.search('manufacturer').each { |n| n.after('<price>10</price>') }
导致:
puts doc.to_xml
# >> <?xml version="1.0" encoding="UTF-8"?>
# >> <items>
# >> <item>
# >> <name>mouse</name>
# >> <manufacturer>Logitech</manufacturer><price>10</price>
# >> </item>
# >> <item>
# >> <name>keyboard</name>
# >> <manufacturer>Logitech - Inc.</manufacturer><price>10</price>
# >> </item>
# >> </items>
可以很容易地建立在此插入不同的值价格。
你让它太难了。 Nokogiri可以轻松地使用字符串添加节点,然后将其解析为新节点。请参阅下面的答案。 – 2016-08-19 21:19:15