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.

Était-ce utile?

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.

Manuel de Python

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top