如何使用包含不同标记的Ruby解析大型XML文件?

时间:2013-07-02 20:37:42

标签: ruby xml nokogiri sax

我有几个大的XML文件,如下所示:

<Listings>
  <Listing>
    <Location>
      <StreetAddress>123 Main St</StreetAddress>
      <UnitNumber>2F</UnitNumber>
      <City>Anytown</City>
      <State>NY</State>
      <Zip>10000</Zip>
    </Location>
  </Listing>
  <!-- a bajillion more Listing nodes -->
</Listings>

不同风格之间的主要区别在于,一个节点有一个<Listing>节点,另一个节点叫<property/>。子元素的嵌套也各不相同。

解析一系列大型XML文件的好方法是什么,每个文件包含相似的条目但标签名称不同?我认为维护标签名称的映射表是有意义的,但是如何使用Ruby有效地迭代这些?

我想抓住<Listing>元素,解析出他们的子元素,如StreetAddress等,然后将它们写在别的地方。每个文件包含数千个列表,其中一些是100 + MB。

2 个答案:

答案 0 :(得分:2)

Nokogiri将接受多个表达,例如:

doc.search('Listing', 'property').each do |item|
  puts item.at('StreetAddress', 'othernameforaddress').text
end

文件大小问题可能是一个更大的问题。如果你没有足够的内存,你可能会看到SAX

答案 1 :(得分:0)

我会选择Nokogiri或REXML和XPath:

//*[self::Listing or self::property]

所以使用Nokogiri的代码将是这样的:

require "nokogiri"

doc = Nokogiri.XML <<-XML
  <Listings>
    <Listing>
      <Location>
        <StreetAddress>123 Main St</StreetAddress>
        <UnitNumber>2F</UnitNumber>
        <City>Anytown</City>
        <State>NY</State>
        <Zip>10000</Zip>
      </Location>
    </Listing>
    <property>
      <Location>
        <StreetAddress>321 Main St</StreetAddress>
        <UnitNumber>2F</UnitNumber>
        <City>Anytown</City>
        <State>NY</State>
        <Zip>10000</Zip>
      </Location>
    </property>
  </Listings>
XML

doc.xpath("//*[self::Location or self::property]").map do |node|
  node.xpath("./*[self::StreetAddress or self::AlternativeStreetAddress]").text
end

# => ["123 Main St", "321 Main St"]