0

I have the following XML file:

<Response Version="X">
  <Status StatusCode = "OK">
  <Internal>
    <SP>
      <URL>SP_url_1</URL>
    </SP>
    <SP>
      <URL>SP_url_2</URL>
    </SP>
  </Internal>
<Response>

I want to get all the URL elements' text in an array.

I implemented the following:

...perform an HTTP GET request...

response_xml = REXML::Document.new(response.body).root
if response_xml.nil? or response_xml.name != 'Response'
  raise ParseError, "Invalid service discovery response!"
end    
status_code  = response_xml.elements['Status'].attribute('StatusCode').value
if status_code == 'OK'
  urls = response_xml.elements.each('//URL') { |u| u }
end
urls

Regarding this line response_xml.elements.each('//URL') { |u| u }, can you recommend a cleaner way to get all URL elements in an array? Maybe there is a wiser way to do via REXML methods, but cannot see it right now.

Any other REXML or general code recommendations are welcome.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Emil Petkov
  • 375
  • 1
  • 4
  • 14

2 Answers2

1

To get text node with XPath, you can use text():

urls = response_xml.elements.each('//URL/text()') { |u| u }
yasu
  • 1,374
  • 8
  • 16
1

I greatly prefer using Nokogiri for my XML parser:

require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<Response Version="X">
  <Status StatusCode = "OK">
  <Internal>
    <SP>
      <URL>SP_url_1</URL>
    </SP>
    <SP>
      <URL>SP_url_2</URL>
    </SP>
  </Internal>
<Response>
EOT

if (doc.at('Status')['StatusCode'] == 'OK')
  urls = doc.search('URL').map(&:text)
  # => ["SP_url_1", "SP_url_2"]
end

Or:

urls = doc.search('URL').map(&:text) if (doc.at('Status')['StatusCode'] == 'OK')
the Tin Man
  • 158,662
  • 42
  • 215
  • 303