2017-03-26 10 views
2

XMLファイルを解析するためにPythonとelementTreeを使用しています。これらのファイルは、私が読んだものから使いやすいツールの一部として示されています。私は経由でソートしようとしている解析されたXMLファイルから子とネストされた子要素の値をペアにする

XMLドキュメントは、この形式は次のとおりです。

<data> 
<property name="AText"> 
    <property value="BText"> 
    <property name="Id" value="DEVICE"/> #Pairing this value... 
    <property name="CText" value="text"> 
    <property name="Value" value="This is a device."/> #...with this value is 
                 #proving problematic 
    </property> 
    </property> 
    <property value="BText"> 
    <property name="Id" value="BRICK"/> 
    <property name="CText" value="text"> 
    <property name="Value" value="This is a brick."/> 
    </property> 
    </property> 
    </property> 
</data> 

私は何をすることができましたことは簡単な部分ですが、私は子供にドリルダウンすることができました要素に興味があり、テキスト情報を取得します。しかし、一度その情報を整理しようとすると、上記の子供の値をペアにする方法がわからないので、私は突っ込んでしまいます。

これは、任意にペアにしても意味をなさないため重要です。 Id要素の値のテキストは、文字どおりValue要素の値のIDです。

今のところ、私のコードはされています:

import xml.etree.ElementTree as ET 

tree = ET.parse('sample2.exml') 
root = tree.getroot() 

shrt = 0 
txt = 0 
save = {"ID:" : shrt, "Desc.:" : txt} 

for y in root.findall("./Property//*[@name='Id']"): 
    shrt = y.get('value') 
    save["ID:"] = shrt 

for x in root.findall(".//*[@name='CText']/Property"): 
    txt = x.get('value') 
    save["Desc.:"] = txt 

print(save) 

これは、すぐにあなたがより多くのペアを取得して破壊します。私はリストを試しましたが、これはソリューションの検索で廃止されなかったコードの中でも最も早く(そして最もクリーンな)ものでした。

私の主な目的は、単にこれらの要素のXMLを解析してから、適切なペアで整理することです。後の目的は、おそらくこれらのペアリングを保持してテーブルに書き込むことです。

答えて

1

アトリビュートをペアにする鍵は、同時にアトリビュートを処理することです。このビットのコードは、プロパティノードを探してループし、サブツリーのその部分を使用して、必要な要素の検索を続けます。

コード:

import xml.etree.ElementTree as ET 

tree = ET.parse(xml_data) 
root = tree.getroot() 

results = [] 
for prop in root.findall(".//property/[@value='BText']"): 
    results.append((
     prop.find(".//property/[@name='Id']").get('value'), 
     prop.find(".//property/[@name='Value']").get('value'), 
    )) 

print(results) 

試験データ:

from io import StringIO 

xml_data = StringIO(u""" 
    <data> 
     <property name="AText"> 
     <property value="BText"> 
      <property name="Id" value="DEVICE"/> 
      <property name="CText" value="text"/> 
      <property name="Value" value="This is a device."/> 
     </property> 
     <property value="BText"> 
      <property name="Id" value="BRICK"/> 
      <property name="CText" value="text"/> 
      <property name="Value" value="This is a brick."/> 
     </property> 
     </property> 
    </data> 
""") 

結果:

[('DEVICE', 'This is a device.'), ('BRICK', 'This is a brick.')] 

Pythonが楽しいです:

フォローアップとして、あなたがnamedtupleに精通していない場合、非常に滑らかです。それらはタプルであり、名前付き属性を使用してアクセスすることもできます。ここでは、名前付きタプルを使用した上からのループを示します。

ボーナスコード:

from collections import namedtuple 
ItemDesc = namedtuple('ItemDesc', 'shrt txt') 

results = [] 
for prop in root.findall(".//property/[@value='BText']"): 
    results.append(ItemDesc(
     shrt=prop.find(".//property/[@name='Id']").get('value'), 
     txt=prop.find(".//property/[@name='Value']").get('value'), 
    )) 

for item in results: 
    print("shrt={}, txt={}".format(item.shrt, item.txt)) 

ボーナス結果:

shrt=DEVICE, txt=This is a device. 
shrt=BRICK, txt=This is a brick. 
+0

これは私が探していたものに非常に近いです。私は上記のXMLの書式設定で軽微な誤りを犯しました。 CText行は独自の閉じた要素(すなわち、 ' ')であり、示されているように、値はその子です。 見落として申し訳ありません! –

+1

明確化:これはうまくいきました。問題は、サンプルコードの各行を実際のファイルの特性に合わせて適切に調整しなかったことです。 –

関連する問題