如何在新节点(Nokogiri,Ruby)中包装XML内容?

时间:2014-10-20 22:38:34

标签: ruby xml nokogiri

使用Nokogiri我想将节点<inserted_node>插入以下XML-snipplet

<foo>
   <bar>some text</bar>
</foo>
像那样

<foo>
   <inserted_node>
      <bar>some text</bar>
   </inserted_node>
</foo>.

如何通过Nokogiri实现这一目标?

2 个答案:

答案 0 :(得分:4)

Nokogiri有一种方便的方法叫wrap

doc.search("bar").wrap("<inserted_node>")
doc.to_html

 => <foo>
        <inserted_node><bar>some text</bar></inserted_node>
    </foo>

回答后续问题:

str = "<foo><bar1></bar1><bar2></bar2></foo>"
doc = Nokogiri::XML(str)
doc.search("bar1,bar2").map(&:parent).uniq.each do |node|
  # Create a new element to attach the children to
  inserted = doc.create_element("inserted")

  # Move the children into the new element
  inserted.children = node.children

  # Add the new element as a child of the parent node
  node << inserted
end

=> "<foo><inserted><bar1></bar1><bar2></bar2></inserted></foo>"

答案 1 :(得分:2)

我这样做:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<foo>
   <bar>some text</bar>
</foo>
EOT

children = doc.root.children
doc.root.children = '<inserted_node>'
doc.at('inserted_node').children = children
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <foo>
# >>   <inserted_node>
# >>    <bar>some text</bar>
# >> </inserted_node>
# >> </foo>

如果有更多内容,它仍然有效:

<foo>
   <bar>some text</bar>
   <baz>some more text</baz>
</foo>

再次运行:

doc = Nokogiri::XML(<<EOT)
<foo>
   <bar>some text</bar>
   <baz>some more text</baz>
</foo>
EOT

children = doc.root.children
doc.root.children = '<inserted_node>'
doc.at('inserted_node').children = children
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <foo>
# >>   <inserted_node>
# >>    <bar>some text</bar>
# >>    <baz>some more text</baz>
# >> </inserted_node>
# >> </foo>

如果你想在DOM中进一步做这件事:

require 'nokogiri'

doc = Nokogiri::XML(<<EOT)
<foo>
   <sub_foo>
     <bar>some text</bar>
     <baz>some more text</baz>
   </sub_foo>
</foo>
EOT

NODE_TO_INSERT = 'inserted_node'

graft_node = doc.at('sub_foo')
children = graft_node.children
graft_node.children = "<#{ NODE_TO_INSERT }>"
doc.at(NODE_TO_INSERT).children = children
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <foo>
# >>    <sub_foo><inserted_node>
# >>      <bar>some text</bar>
# >>      <baz>some more text</baz>
# >>    </inserted_node></sub_foo>
# >> </foo>

这个想法是,您指出通过获取该节点来修改文档的位置。我使用doc.at('sub_foo'),因为只有一个。如果您有许多要操作的地方,则可以search,然后迭代生成的NodeSet。一旦你知道了你要继续工作的节点,抓住它的子节点并在变量中记住它们,在嫁接点下更改子节点,然后在该节点下重新插入旧节点。

一旦你理解了这一点,就可以轻松地修改XML和HTML。