2

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これは実際には親ノードだけを反復処理するのに役立ちません。timeおそらく、この XPATH を変更して、パラメーターを持つノードのみを見つけることができますか?

私の目的は、属性 (つまり)Cubeを持つすべてのノードを抽出できるようにすることです。これにより、日付を抽出し、子ノードの為替レートを反復処理できます。time<Cube time="2009-11-03">Cube

誰でも助けることができますか?

4

2 に答える 2

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)
于 2009-11-03T17:29:12.170 に答える
0

だから私はこれを理解しました。ルート ノードは 2 つの名前空間を定義します。1 つはプレフィックス付き、もう 1 つはプレフィックスなしです。

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| .... }
于 2009-11-03T22:15:01.713 に答える