如何向XML添加新节点

Mr.*_*. L 7 ruby xml nokogiri

我有一个简单的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>
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用以下代码插入新节点:

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
Run Code Online (Sandbox Code Playgroud)

但是,此代码仅在最后一个<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>
Run Code Online (Sandbox Code Playgroud)

为什么?

Ken*_*oom 13

区分Node(树中特定位置的特定结构化XML数据)和作为数据结构的"节点模板"将是有帮助的.

Nokogiri(和大多数其他XML库)只允许您指定Nodes,而不是节点模板.因此,当您创建时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
Run Code Online (Sandbox Code Playgroud)

  • 或者,你可能想简单地使用[`节点#dup`(http://nokogiri.rubyforge.org/nokogiri/Nokogiri/XML/Node.html#M000469)在新的位置插入之前克隆的节点. (2认同)