0

I come from C background but working on some stuff related to XML in Ruby, so, please bear with me if my question is naive.

I have one XML document. I am parsing it using libxml:

<test>
 <ready>
  <ex_success>true</ex_success>
 </ready>
 <ath>
  <name>abc</name>
  <pass>123</pass>
  <ex_success>true</ex_success>
 </ath>
</test>

In this document, I am able to read the ex_success element. However, I am not able to delete it from my original file.

Here is my little piece of code:

require 'xml'
test_file = @file_name
parser = XML::Parser.file(test_file)
document = parser.parse

document.root.each_element {|element|

  # Write each element name in the file
  puts 'element.name'

  if val = element.find_first('ex_success')   
    puts val.content   # prints true
    val.remove!    # THIS line does not remove the element from my original file

  else
    puts 'Not found'
  end

What am I doing wrong and what is the right way to delete it?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303

1 Answers1

2

I'd recommend not using libxml. While it's part of Ruby, it's not the defacto standard for XML parsing for Ruby. Nokogiri is.

Here's how I'd do it using Nokogiri:

require 'nokogiri'

doc = Nokogiri::XML::DocumentFragment.parse(<<EOT)
<test>
 <ready>
  <ex_success>true</ex_success>
 </ready>
 <ath>
  <name>abc</name>
  <pass>123</pass>
  <ex_success>true</ex_success>
 </ath>
</test>
EOT

ex_success = doc.at('ex_success')
ex_success_value = ex_success.text # !> assigned but unused variable - ex_success_value
ex_success.remove

puts doc.to_xml
# >> <test>
# >>  <ready>
# >>   
# >>  </ready>
# >>  <ath>
# >>   <name>abc</name>
# >>   <pass>123</pass>
# >>   <ex_success>true</ex_success>
# >>  </ath>
# >> </test>

If you don't want the blank line left by the empty text node, use this:

ex_success = doc.at('ex_success')
ex_success_value = ex_success.text # => "true"
ex_success.parent.children.remove

puts doc.to_xml
# >> <test>
# >>  <ready/>
# >>  <ath>
# >>   <name>abc</name>
# >>   <pass>123</pass>
# >>   <ex_success>true</ex_success>
# >>  </ath>
# >> </test>

I used Nokogiri::XML::DocumentFragment.parse, which accepts an XML snippet as-is. It's more common to use Nokogiri::XML(<<EOT), which will add the XML decl if it's not there.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • Yeah true, I've searched a lot on using libxml; however looks like Nokogiri is the way to go. Appreciate your response ! – Harry_Potter Aug 08 '14 at 00:54
  • 1
    I ran into all sorts of problems using other XML parsers, including completely blowing up scripts with one that used to be the defacto standard. I wrote a big RSS aggregator that was handling thousands of feeds using Nokogiri to parse RDF, RSS and Atom, and Nokogiri performed wonderfully. It's only gotten better since then. There's a lot of Q/A here so scan through the [tag:nokogiri] tagged questions to see what you can do with it. – the Tin Man Aug 08 '14 at 18:52