64

Element Treeを使用してPythonでXMLを解析する方法の基本的な良い例を見つけるのに苦労しています。私が見つけた限りでは、これは XML の解析に使用する最も簡単なライブラリのようです。以下は、私が使用している XML のサンプルです。

<timeSeriesResponse>
    <queryInfo>
        <locationParam>01474500</locationParam>
        <variableParam>99988</variableParam>
        <timeParam>
            <beginDateTime>2009-09-24T15:15:55.271</beginDateTime>
            <endDateTime>2009-11-23T15:15:55.271</endDateTime>
        </timeParam>
     </queryInfo>
     <timeSeries name="NWIS Time Series Instantaneous Values">
         <values count="2876">
            <value dateTime="2009-09-24T15:30:00.000-04:00" qualifiers="P">550</value>
            <value dateTime="2009-09-24T16:00:00.000-04:00" qualifiers="P">419</value>
            <value dateTime="2009-09-24T16:30:00.000-04:00" qualifiers="P">370</value>
            .....
         </values>
     </timeSeries>
</timeSeriesResponse>

ハードコーディングされた方法を使用して、必要なことを行うことができます。しかし、コードをもう少し動的にする必要があります。うまくいったのは次のとおりです。

tree = ET.parse(sample.xml)
doc = tree.getroot()

timeseries =  doc[1]
values = timeseries[2]

print child.attrib['dateTime'], child.text
#prints 2009-09-24T15:30:00.000-04:00, 550

ここに私が試したことがいくつかありますが、どれも機能せず、timeSeries (または私が試したもの) が見つからないと報告しています:

tree = ET.parse(sample.xml)
tree.find('timeSeries')

tree = ET.parse(sample.xml)
doc = tree.getroot()
doc.find('timeSeries')

基本的に、xml ファイルをロードし、timeSeries タグを検索し、value タグを反復処理して、dateTime とタグ自体の値を返します。上記の例で行っているすべてのことですが、興味のある xml のセクションをハードコーディングしていません。


すべての助けをありがとう。以下の両方の提案を使用すると、私が提供したサンプル ファイルでは機能しましたが、完全なファイルでは機能しませんでした。Ed Carrel の方法を使用したときに実際のファイルから取得したエラーは次のとおりです。

 (<type 'exceptions.AttributeError'>, AttributeError("'NoneType' object has no attribute 'attrib'",), <traceback object at 0x011EFB70>)

実際のファイルには気に入らないものがあると考えたので、機能するまで徐々に削除しました。変更した行は次のとおりです。

originally: <timeSeriesResponse xsi:schemaLocation="a URL I removed" xmlns="a URL I removed" xmlns:xsi="a URL I removed">
 changed to: <timeSeriesResponse>

 originally:  <sourceInfo xsi:type="SiteInfoType">
 changed to: <sourceInfo>

 originally: <geogLocation xsi:type="LatLonPointType" srs="EPSG:4326">
 changed to: <geogLocation>

「xsi:...」を持つ属性を削除すると、問題が修正されました。「xsi:...」は有効な XML ではありませんか? これらをプログラムで削除するのは難しいでしょう。提案された回避策はありますか?

完全な XML ファイルは次のとおりです: http://www.sendspace.com/file/lofcpt


最初にこの質問をしたとき、私は XML の名前空間について知りませんでした。何が起こっているかがわかったので、名前空間宣言である「xsi」属性を削除する必要はありません。それらを xpath 検索に含めるだけです。lxml の名前空間の詳細については、このページを参照してください。

4

2 に答える 2

46

だから私は今私のボックスにElementTree 1.2.6を持っていて、あなたが投稿したXMLチャンクに対して次のコードを実行しました:

import elementtree.ElementTree as ET

tree = ET.parse("test.xml")
doc = tree.getroot()
thingy = doc.find('timeSeries')

print thingy.attrib

そして、次のものが返されました:

{'name': 'NWIS Time Series Instantaneous Values'}

数値インデックスを使用する必要なく、timeSeries 要素を見つけたようです。

ここで役立つのは、「うまくいかない」と言うときに何を意味するかを知ることです。同じ入力が与えられた場合に機能するため、ElementTree が明らかな方法で壊れている可能性は低いです。エラーメッセージ、バックトレース、または私たちがあなたを助けるために提供できるもので質問を更新してください.

于 2009-11-23T22:42:34.963 に答える
22

あなたの質問を正しく理解している場合:

for elem in doc.findall('timeSeries/values/value'):
    print elem.get('dateTime'), elem.text

または、必要に応じて(およびの出現が1つしかない場合timeSeries/values

values = doc.find('timeSeries/values')
for value in values:
    print value.get('dateTime'), elem.text

このfindall()メソッドは、一致するすべての要素のリストを返しfind()ますが、最初に一致する要素のみを返します。最初の例は見つかったすべての要素をループし、2 番目の例は要素の子要素をループしますが、valuesこの場合は同じ結果になります。

しかし、見つからないという問題がどこから来るのかわかりませんtimeSeries。たぶんあなたはgetroot()電話を忘れましたか?/timeSeriesResponse/timeSeries/values(パス式をたとえばorに変更すると、要素ツリー自体からも作業できるため、実際には必要ないことに注意してください//timeSeries/values

于 2009-11-23T23:27:32.083 に答える