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?
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.