Reputation: 14736
There are some posts about this topic, but I wasn't able to figure out how to solve my problem.
I have two XML files:
<Products>
<Product>
<some>
<value></value>
</some>
</Product>
<Product>
<more>
<data></data>
</more>
</Product>
</Products>
And:
<Products>
<Product>
<some_other>
<value></value>
</some_other>
</Product>
</Products>
I want to generate an XML document that looks like this:
<Products>
<Product>
<some>
<value></value>
</some>
</Product>
<Product>
<more>
<data></data>
</more>
</Product>
<Product>
<some_other>
<value></value>
</some_other>
</Product>
</Products>
Every node <Product>
should be merged into <Products>
.
I tried to create a new document using:
doc = Nokogiri::XML("<Products></Products>")
nodes = files.map { |xml| Nokogiri::XML(xml).xpath("//Product") }
set = Nokogiri::XML::NodeSet.new(doc, nodes)
but this throws an error: ArgumentError: node must be a Nokogiri::XML::Node or Nokogiri::XML::Namespace
.
I think I don't understand NodeSet
, but I can't figure out how to merge these two XML files.
Upvotes: 3
Views: 3158
Reputation: 160581
Your sample code won't generate what you want because you're throwing away your some
and more
nodes when you do:
doc = Nokogiri::XML("<Products></Products>")
Instead of creating an empty DOM, you need to piggyback on the original and simply append the new nodes to it:
require 'nokogiri'
xml1 = '<Products>
<Product>
<some>
<value></value>
</some>
</Product>
<Product>
<more>
<data></data>
</more>
</Product>
</Products>
'
xml2 = '<Products>
<Product>
<some_other>
<value></value>
</some_other>
</Product>
</Products>
'
doc = Nokogiri::XML(xml1)
Find the new Product
nodes to be added:
new_products = Nokogiri::XML(xml2).search('Product')
Append them to the original document as added children of Products
:
doc.at('Products').add_child(new_products)
This results in the DOM in doc
looking like:
puts doc.to_xml
# >> <?xml version="1.0"?>
# >> <Products>
# >> <Product>
# >> <some>
# >> <value/>
# >> </some>
# >> </Product>
# >> <Product>
# >> <more>
# >> <data/>
# >> </more>
# >> </Product>
# >> <Product>
# >> <some_other>
# >> <value/>
# >> </some_other>
# >> </Product></Products>
Upvotes: 6