我正在尝试使用libxml-ruby以下列格式解析XML(来自欧洲中央银行数据Feed):
<?xml version="1.0" encoding="UTF-8"?>
<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="2009-11-03">
<Cube currency="USD" rate="1.4658"/>
<Cube currency="JPY" rate="132.25"/>
<Cube currency="BGN" rate="1.9558"/>
</Cube>
</Cube>
</gesmes:Envelope>
我正在按如下方式加载文档:
require 'rubygems'
require 'xml/libxml'
doc = XML::Document.file('eurofxref-hist.xml')
但我正在努力想出正确的命名空间配置以允许对数据进行XPATH查询。
我可以使用以下代码提取所有Cube
个节点:
doc.find("//*[local-name()='Cube']")
但鉴于父节点和子节点都被称为Cube
,这实际上无法帮助我迭代父节点。也许我可以修改此XPATH以仅查找具有time
参数的节点?
我的目标是能够提取具有Cube
属性(即time
)的所有<Cube time="2009-11-03">
个节点,以便我可以提取日期并迭代汇率孩子Cube
个节点。
有人可以帮忙吗?
答案 0 :(得分:3)
其中任何一个都可以使用:
/gesmes:Envelope/Cube/Cube - direct path from root
//Cube[@time] - all cube nodes (at any level) with a time attribute
好的,这是经过测试和运作的
arrNS = ["xmlns:http://www.ecb.int/vocabulary/2002-08-01/eurofxref", "gesmes:http://www.gesmes.org/xml/2002-08-01"]
doc.find("//xmlns:Cube[@time]", arrNS)
答案 1 :(得分:0)
所以我想出来了。根节点定义了两个名称空间,一个带有前缀,一个没有:
xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"
定义前缀后,您可以非常轻松地引用前缀命名空间名称。使用原始问题中的XML,这个XPATH:
/gesmes:Envelope/gesmes:subject
将返回“参考率”。
由于Cube
节点没有前缀,我们首先需要为全局命名空间定义命名空间前缀。这就是我实现这个目标的方式:
doc = XML::Document.file('eurofxref-hist-test.xml')
context = XML::XPath::Context.new(doc)
context.register_namespace('euro', 'http://www.ecb.int/vocabulary/2002-08-01/eurofxref')
一旦定义了这个,找到带有时间属性的Cube节点是微不足道的:
context.find("//euro:Cube[@time]").each {|node| .... }