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

发布于 2024-08-09 08:25:35 字数 1244 浏览 10 评论 0原文

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

<?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 节点(即 ),这样我就可以提取日期并迭代子 Cube 节点中的汇率。

有人可以帮忙吗?

I'm attempting to parse XML in the following format (from the European Central Bank data feed) using libxml-ruby:

<?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>

I'm loading the document as follows:

require 'rubygems'
require 'xml/libxml'
doc = XML::Document.file('eurofxref-hist.xml')

But I'm struggling to come up with the correct namespace configuration to allow XPATH queries on the data.

I can extract all the Cube nodes using the following code:

doc.find("//*[local-name()='Cube']")

But given that both the parent node and child nodes are both called Cube this really doesn't help me iterate over just the parent nodes. Perhaps I could modify this XPATH to only find those nodes with a time parameter?

My aim is to be able to extract all the Cube nodes which have a time attribute (i.e. <Cube time="2009-11-03">) so I can then extract the date and iterate over the exchange rates in the child Cube nodes.

Can anyone help?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

゛时过境迁 2024-08-16 08:25:35

其中任何一个都可以工作:

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

either of these will work:

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

Ok, this is tested and working

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)
野生奥特曼 2024-08-16 08:25:35

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

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| .... }

So I figured this out. The root node defines two namespaces, one with a prefix, one without:

xmlns:gesmes="http://www.gesmes.org/xml/2002-08-01
xmlns="http://www.ecb.int/vocabulary/2002-08-01/eurofxref"

When a prefix is defined, you can quite easily reference the prefix namespaced names. Using the XML from the original question, this XPATH:

/gesmes:Envelope/gesmes:subject

Will return "Reference rates".

Because the Cube nodes are not prefixed, we first need to define a namespace prefix for the global namespace. This is how I achieved this:

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

Once this is defined, finding the Cube nodes with time attributes is trivial:

context.find("//euro:Cube[@time]").each {|node| .... }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文