Python で XML 属性値のリストを取得する
-
01-07-2019 - |
質問
Python の子要素から属性値のリストを取得する必要があります。
例を挙げて説明するのが最も簡単です。
次のような XML があるとします。
<elements>
<parent name="CategoryA">
<child value="a1"/>
<child value="a2"/>
<child value="a3"/>
</parent>
<parent name="CategoryB">
<child value="b1"/>
<child value="b2"/>
<child value="b3"/>
</parent>
</elements>
次のようなことができるようにしたいです:
>>> getValues("CategoryA")
['a1', 'a2', 'a3']
>>> getValues("CategoryB")
['b1', 'b2', 'b3']
XPath の仕事のように見えますが、あらゆる推奨事項を歓迎します。また、お気に入りの Python XML ライブラリについてもお聞きしたいと思います。
解決
私は Python にあまり詳しくありませんが、libxml2 を使用した XPath ソリューションを次に示します。
import libxml2
DOC = """<elements>
<parent name="CategoryA">
<child value="a1"/>
<child value="a2"/>
<child value="a3"/>
</parent>
<parent name="CategoryB">
<child value="b1"/>
<child value="b2"/>
<child value="b3"/>
</parent>
</elements>"""
doc = libxml2.parseDoc(DOC)
def getValues(cat):
return [attr.content for attr in doc.xpathEval("/elements/parent[@name='%s']/child/@value" % (cat))]
print getValues("CategoryA")
結果としては…
['a1', 'a2', 'a3']
他のヒント
エレメントツリー 1.3 (残念ながら、Python に含まれている 1.2 ではありません) XPathをサポート このような:
import elementtree.ElementTree as xml
def getValues(tree, category):
parent = tree.find(".//parent[@name='%s']" % category)
return [child.get('value') for child in parent]
そうすれば、次のことができます
>>> tree = xml.parse('data.xml')
>>> getValues(tree, 'CategoryA')
['a1', 'a2', 'a3']
>>> getValues(tree, 'CategoryB')
['b1', 'b2', 'b3']
lxml.etree
(ElementTree インターフェースも提供します) も同様に機能します。
stdlib の minidom や pxdom などの標準 W3 DOM を使用します。
def getValues(category):
for parent in document.getElementsByTagName('parent'):
if parent.getAttribute('name')==category:
return [
el.getAttribute('value')
for el in parent.getElementsByTagName('child')
]
raise ValueError('parent not found')
私がファンであることを認めなければなりません xmltramp 使いやすさのため。
上記にアクセスすると次のようになります。
import xmltramp
values = xmltramp.parse('''...''')
def getValues( values, category ):
cat = [ parent for parent in values['parent':] if parent(name) == category ]
cat_values = [ child(value) for child in parent['child':] for parent in cat ]
return cat_values
getValues( values, "CategoryA" )
getValues( values, "CategoryB" )
これを行うことができます 美しいスープ
>>> from BeautifulSoup import BeautifulStoneSoup
>>> soup = BeautifulStoneSoup(xml)
>>> def getValues(name):
. . . return [child['value'] for child in soup.find('parent', attrs={'name': name}).findAll('child')]
HTML/XML を使用する作業を行っている場合は、BeautifulSoup を参照することをお勧めします。これは DOM ツリーに似ていますが、より多くの機能が含まれています。
私の好みのPython XMLライブラリは次のとおりです。 lxml 、libxml2をラップします。
Xpath がここに行く方法だと思われるので、これを次のように書きます。
from lxml import etree
def getValues(xml, category):
return [x.attrib['value'] for x in
xml.findall('/parent[@name="%s"]/*' % category)]
xml = etree.parse(open('filename.xml'))
>>> print getValues(xml, 'CategoryA')
['a1', 'a2', 'a3']
>>> print getValues(xml, 'CategoryB')
['b1', 'b2', 'b3]
Python 3.x では、属性のリストをフェッチするのは、メンバーを使用する簡単なタスクです。 items()
を使用して、 ElementTree
, 、以下のスニペットは、属性のリストを取得する方法を示しています。この例では名前空間が考慮されていないことに注意してください。名前空間が存在する場合は考慮する必要があります。
import xml.etree.ElementTree as ET
flName = 'test.xml'
tree = ET.parse(flName)
root = tree.getroot()
for element in root.findall('<child-node-of-root>'):
attrList = element.items()
print(len(attrList), " : [", attrList, "]" )
参照:
Element.items()
要素の属性を (名前、値) ペアのシーケンスとして返します。
属性は任意の順序で返されます。