Search code examples
rubyxmlxml-simple

Filter Simple-XML Output in ruby


I'm absolutely new to ruby and I'm trying to parse an XML structure and filter it for some attributes. The XML looks like this:

<systeminfo>
<machines>
<machine name="localhost">
<repository worker="localhost:8060" status="OK"/>
<dataengine worker="localhost:27042" status="OK"/>
<serverwebapplication worker="localhost:8000" status="OK"/>
<serverwebapplication worker="localhost:8001" status="OK"/>
<vizqlserver worker="localhost:9100" status="OK"/>
<vizqlserver worker="localhost:9101" status="OK"/>
<dataserver worker="localhost:9700" status="OK"/>
<dataserver worker="localhost:9701" status="OK"/>
<backgrounder worker="localhost:8250" status="OK"/>
<webserver worker="localhost:80" status="OK"/>
</machine>
</machines>
<service status="OK"/>
</systeminfo>

I want to check if the status attribute is OK. So far I have written this code:

#!/usr/bin/ruby -w

require 'rubygems'
require 'net/http'
require 'xmlsimple'

url = URI.parse("URL to XML")
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}

sysinfodoc = XmlSimple.xml_in(res.body)


sysinfodoc["machines"][0]["machine"][0].each do |status|
p status[1][0]
p status[1][1]
end

Output:

{"worker"=>"localhost:8060", "status"=>"OK"}
nil
{"worker"=>"localhost:27042", "status"=>"OK"}
nil
{"worker"=>"localhost:9100", "status"=>"OK"}
{"worker"=>"localhost:9101", "status"=>"OK"}
{"worker"=>"localhost:8000", "status"=>"OK"}
{"worker"=>"localhost:8001", "status"=>"OK"}
{"worker"=>"localhost:8250", "status"=>"OK"}
nil
{"worker"=>"localhost:9700", "status"=>"OK"}
{"worker"=>"localhost:9701", "status"=>"OK"}
{"worker"=>"localhost:80", "status"=>"OK"}
nil
108
111

UPDATE The Output should be something like:

OK
OK
OK
OK
OK
OK
OK
OK
OK
OK

This script is supposed to be used with nagios. So rather than outputting the results I want to check if one of the status attributes conatins something which is not "OK" later. UPDATE

How do I get rid of the nils and the fixnums? Why are there fixnums anyway?

How can I filter this so I get just the status for every machine child? Or is this the wrong approach alltogether?


Solution

  • How about using Nokogiri and XPath for this?

    require 'nokogiri'
    @doc = Nokogiri::XML(File.open("example.xml"))
    @doc.xpath("//machine/*/@status").each { |x| puts x }
    

    And the result will be

    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    OK
    => 0