解析XML命名空间的libxml使用,红宝石

问题描述:

我试图使用的libxml-红宝石按以下格式解析XML(来自欧洲央行的数据饲料):解析XML命名空间的libxml使用,红宝石

<?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参数的节点?

我的目标是能够提取所有有time属性(即<Cube time="2009-11-03">)的Cube节点这样的话我可以提取日期和迭代在孩子Cube节点的汇率。

任何人都可以帮忙吗?

任何一项都将工作:

/gesmes:Envelope/Cube/Cube - direct path from root 
//Cube[@time] - all cube nodes (at any level) with a time attribute 

OK,这是测试和工作

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) 
+0

这些都不实际工作,他们返回没有节点。我最初自己尝试了第一个,但无济于事。有趣的是,如果我删除所有命名空间并使用'test'的根标签,那么'/ test/Cube/Cube'确实按预期工作。有任何想法吗? – Olly

+1

见上面运行的代码编辑。接过试错的相当数量得到 – Zack

+0

啊哈!谢谢你。我真的想出了一个我刚刚发布的解决方案,但是您的解决方案为我节省了一段代码:) – Olly

所以我想通了这一点。根节点定义了两个命名空间,一个用一个前缀,一个没有:

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') 

一旦被定义,寻找魔方节点随着时间的属性很简单:

context.find("//euro:Cube[@time]").each {|node| .... } 
+0

t = XML :: XPath :: Context.new(doc)不需要参数... – mArtinko5MB