代码之家  ›  专栏  ›  技术社区  ›  Olly

使用libxml-ruby解析名称空间的XML

  •  2
  • Olly  · 技术社区  · 16 年前

    我正在尝试使用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']")
    

    但是如果父节点和子节点都被调用 立方体 time

    具有 时间 <Cube time="2009-11-03"> )然后我可以提取日期,并在子对象中迭代汇率 立方体 节点。

    有人能帮忙吗?

    2 回复  |  直到 16 年前
        1
  •  3
  •   Zack    16 年前

    这两种方法中的任何一种都会起作用:

    /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)
    
        2
  •  0
  •   Olly    16 年前

    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| .... }
    
    推荐文章