【问题标题】:Filter Simple-XML Output in ruby在 ruby​​ 中过滤 Simple-XML 输出
【发布时间】:2015-02-13 09:29:56
【问题描述】:

我对 ruby​​ 完全陌生,我正在尝试解析 XML 结构和 过滤一些属性。 XML 如下所示:

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

我想检查状态属性是否正常。到目前为止我已经写了 这段代码:

#!/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

输出:

{"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

更新 输出应该是这样的:

OK
OK
OK
OK
OK
OK
OK
OK
OK
OK

该脚本应该与 nagios 一起使用。因此,我不想输出结果,而是想检查其中一个状态属性是否包含稍后不是“OK”的东西。 更新

如何摆脱 nils 和 fixnums?为什么还是有fixnums?

如何过滤这个,以便我只获得每个机器子节点的状态? 或者这完全是错误的方法?

【问题讨论】:

  • 您能否展示(而不是试图解释)您期望的输出究竟是什么?
  • 我希望输出为 OK OK OK OK OK OK OK OK OK OK 因为我想检查是否存在不正常的状态。这应该与 nagios 一起使用。
  • 请编辑您的问题以包含此信息 - 并确保您的输入 XML 具有代表性,如果我理解正确,应该存在“不正常”的机器实例.
  • 我已经更新了我的问题。 XML 是正确的,因为它是由应监控的服务器软件创建的,并且 status 的值根据服务状态而变化。目前所有服务都已启动并运行。
  • 恐怕你不明白我的意思。我要求您展示一个测试用例,其中包括您需要考虑的所有真实案例。

标签: ruby xml xml-simple


【解决方案1】:

为此使用Nokogiri and XPath 怎么样?

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

结果会是

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

【讨论】:

  • 谢谢,这很好用。真的很感激!
【解决方案2】:

免责声明:按照 Mathias 的建议使用 nokogiri 和 XPath 更加优雅和容易。


一旦您遇到了意外的输出,请尝试打印出状态局部变量本身:

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

你会看到输出是:

#⇒ ["name", "localhost"]
#⇒ ["repository", [{"worker"=>"localhost:8060", "status"=>"OK"}]]
#⇒ ["dataengine", [{"worker"=>"localhost:27042", "status"=>"OK"}]]
#⇒ ...

也就是说,要实现你想要的,你应该:

▶ sysinfodoc["machines"][0]["machine"][0].values.each do |status|
▷   next unless Array === status
▷   p status.last['status']
▷ end  
# "OK"
# "OK"
# "OK"
# ...

检查status 是数组是必要的,因为存在

# ["name", "localhost"]

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 2013-12-26
    • 1970-01-01
    • 2015-11-26
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    • 2021-07-02
    相关资源
    最近更新 更多