在Rails 3中使用Nokogiri读取XML文件



我在试图遍历XML文件的一部分时遇到问题。我正在使用Nokogiri和Rails3。

我正在阅读这个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对象。然而,当我试图在第一个循环中提升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命名空间引起的。

在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!方法:

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

这样做的结果与前两个示例不太一样,因为名称空间信息已被删除,但它将为您提供所需的节点。

相关内容

  • 没有找到相关文章

最新更新