我有一个简单的XML文件items.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>
为什么?
答案 0 :(得分:13)
区分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
答案 1 :(得分:2)
我从这开始:
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>
很容易在此基础上插入不同的价格值。