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



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

<foo>
   <bar>some text</bar>
</foo>

就像

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

野村怎么能做到这一点?

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>"

我会这样做:

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。

最新更新