首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用libxml-ruby解析命名空间XML

使用libxml-ruby解析命名空间XML
EN

Stack Overflow用户
提问于 2009-11-04 01:11:07
回答 2查看 2.4K关注 0票数 2

我尝试使用libxml-ruby解析以下格式的XML (来自欧洲中央银行的数据提要):

代码语言:javascript
复制
<?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>

我将按如下方式加载文档:

代码语言:javascript
复制
require 'rubygems'
require 'xml/libxml'
doc = XML::Document.file('eurofxref-hist.xml')

但是我正在努力想出正确的名称空间配置来允许对数据进行XPATH查询。

我可以使用以下代码提取所有Cube节点:

代码语言:javascript
复制
doc.find("//*[local-name()='Cube']")

但是,鉴于父节点和子节点都称为Cube,这实际上并不能帮助我只遍历父节点。也许我可以修改这个XPATH,使其只查找那些带有time参数的节点?

我的目标是能够提取所有具有time属性的Cube节点(即<Cube time="2009-11-03">),这样我就可以提取日期并遍历Cube子节点中的汇率。

有人能帮上忙吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-04 01:29:12

这两种方法都可以工作:

代码语言:javascript
复制
/gesmes:Envelope/Cube/Cube - direct path from root
//Cube[@time] - all cube nodes (at any level) with a time attribute

好了,这是经过测试的,并且工作正常。

代码语言:javascript
复制
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)
票数 3
EN

Stack Overflow用户

发布于 2009-11-04 06:15:02

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

代码语言:javascript
复制
xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"

定义前缀后,可以很容易地引用前缀名称空间的名称。使用原始问题中的XML,此XPATH如下:

代码语言:javascript
复制
/gesmes:Envelope/gesmes:subject

将返回“参考利率”。

因为Cube节点没有前缀,所以我们首先需要为全局名称空间定义一个名称空间前缀。这就是我是如何做到的:

代码语言:javascript
复制
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节点就很简单了:

代码语言:javascript
复制
context.find("//euro:Cube[@time]").each {|node| .... }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1668789

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档