Obtenir la liste des valeurs d'attributs XML en Python
-
01-07-2019 - |
Question
Je dois obtenir une liste de valeurs d'attributs à partir d'éléments enfants en Python.
Il est plus facile d'expliquer avec un exemple.
Étant donné que XML ressemble à ceci:
<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>
Je veux pouvoir faire quelque chose comme:
>>> getValues("CategoryA")
['a1', 'a2', 'a3']
>>> getValues("CategoryB")
['b1', 'b2', 'b3']
Cela ressemble à un travail pour XPath mais je suis ouvert à toutes les recommandations. J'aimerais également entendre parler de vos bibliothèques XML préférées Python.
La solution
Je ne suis pas vraiment un habitué de Python, mais voici une solution XPath utilisant libxml2.
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")
Avec résultat ...
['a1', 'a2', 'a3']
Autres conseils
ElementTree 1.3 (malheureusement, ce n'est pas la version 1.2 fournie avec Python). prend en charge XPath comme suit:
import elementtree.ElementTree as xml
def getValues(tree, category):
parent = tree.find(".//parent[@name='%s']" % category)
return [child.get('value') for child in parent]
Ensuite, vous pouvez faire
>>> tree = xml.parse('data.xml')
>>> getValues(tree, 'CategoryA')
['a1', 'a2', 'a3']
>>> getValues(tree, 'CategoryB')
['b1', 'b2', 'b3']
lxml.etree
(qui fournit également l'interface ElementTree) fonctionnera également de la même manière.
Utilisation d'un DOM W3 standard tel que le minidom de stdlib ou pxdom:
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')
Je dois admettre que je suis un fan de xmltramp en raison de sa facilité d'utilisation. .
Accéder à ce qui précède devient:
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" )
Vous pouvez le faire avec BeautifulSoup
>>> from BeautifulSoup import BeautifulStoneSoup
>>> soup = BeautifulStoneSoup(xml)
>>> def getValues(name):
. . . return [child['value'] for child in soup.find('parent', attrs={'name': name}).findAll('child')]
Si vous travaillez avec HTML / XML, je vous recommande de jeter un coup d'œil à BeautifulSoup. Il est similaire à l’arborescence DOM mais contient plus de fonctionnalités.
Ma bibliothèque xml python préférée est lxml , qui enveloppe libxml2.
Xpath semble être la voie à suivre ici, alors j’écrirais ceci comme quelque chose comme:
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]
Dans Python 3.x, l'extraction d'une liste d'attributs est une tâche simple consistant à utiliser le membre items ()
En utilisant ElementTree
, l'extrait ci-dessous montre un moyen d'obtenir la liste des attributs.
Notez que cet exemple ne prend pas en compte les espaces de noms, qui, le cas échéant, devront être pris en compte.
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, "]" )
REFERENCE:
Element.items ()
Renvoie les attributs d'élément sous forme d'une séquence de paires (nom, valeur).
Les attributs sont renvoyés dans un ordre arbitraire.