使用sax解析在Ruby中解析复杂的xml

时间:2015-08-26 15:41:42

标签: ruby xml parsing

我一直在搜索和搜索有关如何执行此操作的几天,但我似乎无法理解sax解析,这将有助于我完成我想要完成的任务。我理解基本级别的sax解析,但我不能理解如何使用它来提取我需要提取的数据。

我目前正在使用:

  • xml数据
  • 红宝石
  • saxerator gem(我没有卖掉它,它是迄今为止我发现的最简单的,我能够清楚地理解)

这是xml结构的一个示例:

<result created="2015-08-26T09:42:35-05:00" host="testdata" status="
  <items>
    <client>
      <clientid>00001</clientid>
      <name>
        <![CDATA[ ABC Company ]]>
      </name>
      <site>
        <siteid>222222</siteid>
        <name>
          <![CDATA[ 123 Blvd ]]>
        </name>
        <workstations/>
        <servers>
          <server>
            <id>333333</id>
            <name>
              <![CDATA[ 123BLVD-SRV ]]>
            </name>
            <failed_checks>
              <check>
                <checkid>4444444</checkid>
                <check_type>0001</check_type>
                <description>
                  <![CDATA[Critical Events Check - Application log]]>
                </description>
                <dsc_247>2</dsc_247>
                <date>2015-08-26</date>
                <time>06:03:44</time>
                <consecutive_fails>2</consecutive_fails>
                <startdate>2015-08-25</startdate>
                <starttime>10:43:51</starttime>
                <formatted_output>
                  <![CDATA[Event log issues[CLIENT:]]>
                </formatted_output>
                <checkstatus>
                  <![CDATA[ Status ]]>
                </checkstatus>
              </check>
            </failed_checks>
          </server>
        </servers>
      </site>
    </client>

我尝试提取的是一系列客户端。每个客户端都有一个名称,一个clientid,一组工作站(及其属性),以及一组服务器(及其属性)。像这样:

clients_array = [
  {
    :name => 'ABC Company', 
    :clientid => '00001', 
    :workstations => [
      {
        :name => 'hostname', 
        :id => '00002', 
        :failed_checks => [
          {
            :description => 'description', :cause => 'cause'
          }
        ]
      }, 
      {
        :name => 'hostname2',
        :id => '00003',
        ...
      }
    ]
  },
  {
    :name => 'Second Company',
    :clientid => '...',
    ...
  }
] 

我遇到的问题是我可以很容易地提取客户端节点的信息,但是很难提取每个客户端节点的工作站和服务器信息。

旁注:我只会使用DOM解析,这在过去我已经取得了巨大的成功,但我使用的XML太大而且已经崩溃了服务器。

这是我到目前为止所做的工作。我一直卡在站点/工作站/服务器节点上,因为有时会有一个站点(哈希元素),有时会有多个站点(数组元素)。工作站和服务器也是如此。

由于这是sax解析,我不明白如何将工作站和服务器指向每个客户端。我不需要网站数据,只需要每个客户的工作站和服务器:

require 'saxerator'

def parse_sax    

  clients_array = []

  parser = Saxerator.parser(File.new("data.xml"))

  parser.for_tag(:client).each do |client|

    # Create a hash to store 'this' client's data in
    client_hash = Hash.new

    # Grab some data
    client_hash[:name] = client['name']
    client_hash[:clientid] = client['clientid']

    # Here's where the workstation/server code would go
    parser.for_tag(:site).each do |site|
      # This just goes through and finds ALL sites
    end
  clients_array << client_hash
end

当我考虑分别解析客户端,工作站和服务器时,我以为我已经弄明白了:

parser.for_tag(:client).each do |client|
  ...
end

parser.for_tag(:workstation).each do |ws|
  ...
end

parser.for_tag(:server).each do |srv|
  ...
end

但后来我最终得到了一堆独立的客户端,工作站和服务器对象,无法将设备与各自的客户端联系起来。

我很有可能掌握萨克斯语解析,以至于我只是缺少一些可以实现我想要的微不足道的东西,但我似乎无法找到解决方案。

我非常乐意在需要的地方提供说明,并且非常感谢任何帮助。

0 个答案:

没有答案