【问题标题】:Reading an XML file with Nokogiri in Rails 3在 Rails 3 中使用 Nokogiri 读取 XML 文件
【发布时间】:2013-02-10 16:51:19
【问题描述】:

我在尝试循环访问部分 XML 文件时遇到问题。我正在使用带有 Rails3 的 Nokogiri。

我正在阅读这个 XML 提要 - http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml

这是我的代码:

def save_rates

    # get the XML data form ECB URL
    file_handle = open('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml')

    # get document xml string and create Nokogiri object
    doc = Nokogiri::XML(file_handle)

    # foreach date...
    doc.xpath("//Cube/Cube").each do |cube|

        raise cube.inspect # isn't being executed

        # foreach currency...
        cube.xpath("./Cube").each do |curr|
            # create DB entry
            Exchange.create(:currency=>curr.currency, :rate=>curr.rate, :record_date => cube.time)

        end
    end

end

当我检查 doc 时,我可以看到 Nokogiri 对象。但是,当我尝试在第一个 .each 循环中提高 cube.inspect 时,它并没有触发。所以这让我相信我的道路是错误的://Cube/Cube

从我在 Nokogiri 教程中看到的其他示例中,路径与此类似。我的路径是错的还是我在这里做错了什么?

我是 ruby​​ n00b,所以请放轻松!

更新

这是 XML 的格式

<gesmes:Envelope xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01" xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref">
    <gesmes:subject>Reference rates</gesmes:subject>
    <gesmes:Sender>
    <gesmes:name>European Central Bank</gesmes:name>
    </gesmes:Sender>
    <Cube>
        <Cube time="2013-02-25">
            <Cube currency="USD" rate="1.3304"/>
            <Cube currency="JPY" rate="125"/>
            <Cube currency="BGN" rate="1.9558"/>
            <Cube currency="CZK" rate="25.52"/>
            <Cube currency="DKK" rate="7.4614"/>
            <Cube currency="GBP" rate="0.8789"/>
            ...
        </Cube>
        <Cube>
        <Cube time="2013-02-24">
            <Cube currency="USD" rate="1.3304"/>
            <Cube currency="JPY" rate="125"/>
            <Cube currency="BGN" rate="1.9558"/>
            <Cube currency="CZK" rate="25.52"/>
            <Cube currency="DKK" rate="7.4614"/>
            <Cube currency="GBP" rate="0.8789"/>
            ...
        </Cube>
    </Cube>
</gesmes:Envelope>

【问题讨论】:

  • 请包含您尝试读取的 XML 的 sn-p。将 URL 放入您的代码中是可以的,但是如果/当该链接中断您的问题时,对于搜索相同问题的其他人来说,这将没有多大意义或价值。
  • 我已经包含了xml结构

标签: ruby xml ruby-on-rails-3 xml-parsing nokogiri


【解决方案1】:

这里的问题是由于XML namespaces

在 XML 的根属性中有属性xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref",它指定了默认命名空间。 Cube 元素在这个命名空间中,如果你只使用 Cube 而不指定命名空间,你将不会得到匹配。

要在 Nokogiri 中指定命名空间,您可以执行以下操作:

doc.xpath("//ecb:Cube/ecb:Cube", 'ecb' => "http://www.ecb.int/vocabulary/2002-08-01/eurofxref")

这里我们为命名空间指定了前缀ecb,并在 XPath 表达式中使用了前缀。

在这种情况下,命名空间是在根节点上声明的默认命名空间,Nokogiri 将为我们在xmlns 前缀上声明它,所以我们可以使用更简单的:

doc.xpath("//xmlns:Cube/xmlns:Cube")

这将导致与第一个相同的结果。

如果您对命名空间不感兴趣,一个更简单的可能性是使用remove_namespaces! method

doc.remove_namespaces!
doc.xpath("//Cube/Cube")

由于名称空间信息已被删除,因此结果与前两个示例不太一样,但它会为您提供您期望的节点。

【讨论】:

  • 非常感谢@matt。很好的解释。我使用了 doc.remove_namespaces!效果很好。
  • 谢谢,remove_namespaces 也帮助了我,完全相同的问题 :] 问候
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2016-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-12
相关资源
最近更新 更多