Nexpose XML结果解析器中的Ruby / Nokogiri嵌套循环失败

时间:2012-10-18 12:51:23

标签: ruby xml nokogiri

我正在尝试编写一个ruby脚本来进行Nexpose Simple XML结果导出,解析它,并将所需的结果写成更漂亮的格式以便于查看。我正在使用Nokogiri来解析XML。我的问题是我有一个嵌套循环,为每个设备迭代每个服务部分,并从每个服务部分中提取名称,端口和协议属性。这将最终打印回文件文件或csv文件。但是,我的嵌套循环似乎只从第一个服务部分拉出这三个属性并重复打印它们。

示例输入(这些设备块中不止一个):

<device address="10.x.x.1" id="20xx">
<fingerprint certainty="0.85">
<description>Microsoft Windows</description>
<vendor>Microsoft</vendor>
<family>Windows</family>
<product>Windows</product>
<version/>
<device-class>General</device-class>
<architecture/>
</fingerprint>
<vulnerabilities>
</vulnerabilities>
<services>
<service name="NTP" port="123" protocol="udp">
<vulnerabilities>
</vulnerabilities>
</service>
<service name="HTTP" port="8080" protocol="tcp">
<fingerprint certainty="0.75">
<description>Apache</description>
</device>

<device address="10.x.x.2" id="20xx">
<fingerprint certainty="0.85">
<description>Microsoft Windows</description>
<vendor>Microsoft</vendor>
<family>Windows</family>
<product>Windows</product>
<version/>
<device-class>General</device-class>
<architecture/>
</fingerprint>
<vulnerabilities>
</vulnerabilities>
<services>
<service name="DNS" port="53" protocol="udp">
<vulnerabilities>
</vulnerabilities>
</service>
<service name="HTTP" port="80" protocol="tcp">
<fingerprint certainty="0.75">
<description>Apache</description>
</device>

Ruby代码:

#! /usr/bin/env ruby

require 'rubygems'
require 'nokogiri'

doc = Nokogiri::XML(open('report.xml').read)
device = doc.xpath('//device')

device.each do |d|
 service = d.xpath('//service')
 puts d.attr('address')

 service.each do |s|
   name = s.attr('name')
   port = s.attr('port')
   protocol = s.attr('protocol')

   puts port
   puts protocol
   puts name
 end
end

期望输出:

10.x.x.1
123
udp
NTP
8080
tcp
HTTP

10.x.x.2
53
udp
DNS
80
tcp
HTTP

实际输出:

123
NTP
udp
123
NTP
udp

因此,代码应显示每个设备的每个服务的服务端口,名称和协议列表。但是,当前代码似乎只是反复打印第一个服务(即123,NTP和udp)的集合。

我在循环逻辑中遗漏了什么?或者你看到循环有什么问题?任何帮助这项工作将有所帮助。感谢。

1 个答案:

答案 0 :(得分:0)

请注意,XPath构造//表示在文档中找到 where 元素。您不希望在内循环中执行此操作,因为您已经为您的设备执行了此操作。

<强>更新

基于新的输入文档,这是提取所需信息的一种方法。我冒昧地使用CSV,获得了一个很好的Excel就绪输出文件。请注意,有一个解析循环。代码:

require 'nokogiri'
require 'csv'

doc = Nokogiri::XML(open('report.xml').read)

CSV.open("devices.csv", "wb") do |csv|
  csv << ["Device", "Service", "Port", "Protocol"]
  doc.search('//service').each do |s|
    device = s.xpath('ancestor::device[1]/@address')
    name = s.attr('name')
    port = s.attr('port')
    protocol = s.attr('protocol')
    csv << [device, name, port, protocol]
  end
end

以下是devices.csv的内容:

Device,Service,Port,Protocol
10.x.x.1,NTP,123,udp
10.x.x.1,HTTP,8080,tcp
10.x.x.2,DNS,53,udp
10.x.x.2,HTTP,80,tcp