Creating XML Nodes with Nokogiri

I am having problems creating nodes and adding them to an XML file:

<mainnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
</mainnode>

      

I want to be able to add to a file like so:

<mainnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
</mainnode>

      

I am having problems getting the concept of adding nodes using Nokogiri.

This is my current code:

def openXML
    f = File.open("file.xml")
    doc = Nokogiri::XML(f)
end

def parseXML
    mainnode.name = 'mainnode'
    f = openXML
    temp = Nokogiri::XML::Node.new "secnode", f
    mainnode.add_next_sibling(temp)

end

      

What concepts am I missing?

I need to be able to add instance variables to <data1>

and <data2>

, but I found the Nokogiri tutorial not very helpful in this area and didn't skip it by just adding <secnode>

node as a child <mainnode>

.

Any help is appreciated.

+3


source to share


2 answers


Adding nodes to Nokigiri is much easier than you think, but your question is not very clear.

If you want to duplicate an existing node:

require 'nokogiri'

xml = <<EOT
<mainnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
</mainnode>
EOT

doc = Nokogiri::XML(xml)

secnode = doc.at('secnode')
doc.root.add_child secnode.dup
puts doc.to_xml

      

Which, when launched, results in:

<?xml version="1.0"?>
<mainnode>
    <secnode>
         <data1/>
         <data2/>
    </secnode>
<secnode>
         <data1/>
         <data2/>
    </secnode></mainnode>

      

Funky alignment is the result of adding intermediate text nodes used for indentation. The resulting XML is valid.

If you add another set of nodes, it's still easy:

requires "nokogiri"



xml = <<EOT
<mainnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
</mainnode>
EOT

node_to_add = <<EOT
<secnode>
  <data3 />
  <data4 />
</secnode>
EOT

doc = Nokogiri::XML(xml)

doc.root.add_child node_to_add
puts doc.to_xml

      

What are the outputs:

<?xml version="1.0"?>
<mainnode>
    <secnode>
         <data1/>
         <data2/>
    </secnode>
<secnode>
  <data3/>
  <data4/>
</secnode>
</mainnode>

      

You can use this as a template:

require 'nokogiri'

xml = <<EOT
<mainnode>
    <secnode>
         <data1></data2>
         <data2></data2>
    </secnode>
</mainnode>
EOT

v1 = 'foo'
v2 = 'bar'
node_to_add = <<EOT
<secnode>
  <data3>#{ v1 }</data3>
  <data4>#{ v2 }</data4>
</secnode>
EOT

doc = Nokogiri::XML(xml)

doc.root.add_child node_to_add
puts doc.to_xml

      

What looks like:

<?xml version="1.0"?>
<mainnode>
    <secnode>
         <data1/>
         <data2/>
    </secnode>
<secnode>
  <data3>foo</data3>
  <data4>bar</data4>
</secnode>
</mainnode>

      

Nokogiri makes it easy to create nodes that are added using XML or HTML string representations, which are then converted on the fly.

+5


source


require 'nokogiri'

def parse_xml_file(file_name)
  f = File.read(file_name)
  Nokogiri::XML(f) # do not need variable here; it the return value of the method
end

def add_element(doc, node_name)
  new_element = Nokogiri::XML::Node.new(node_name, doc)
  new_element.content = "anything"
  doc.root.add_child(new_element)
end

doc = parse_xml_file("sample.xml")
add_element(doc, 'secnode')

puts doc.to_s

      

Your line mainnode.name = 'mainnode'

does nothing and throws an error; you haven't selected anything from the XML document yet.

You should read about XML DOM traversal and node selection. Try this primer: https://blog.engineyard.com/2010/getting-started-with-nokogiri



You say you are reading the Nokogiri docs, but I'll come back and re-read that too: http://www.nokogiri.org/tutorials/searching_a_xml_html_document.html

Finally, play with nokogiri by parsing the document in IRB and seeing what you can do with it. This is a good way to explore and feel the nookogiri.

+4


source







All Articles