Frage

Ich brauche eine Liste von Attributwerten von untergeordneten Elementen in Python zu erhalten.

Es ist am einfachsten mit einem Beispiel zu erklären.

einige XML wie folgt gegeben:

<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>

Ich möchte in der Lage sein zu tun, so etwas wie:

>>> getValues("CategoryA")
['a1', 'a2', 'a3']
>>> getValues("CategoryB")
['b1', 'b2', 'b3']

Es sieht aus wie ein Job für XPath, aber ich bin auf alle Empfehlungen offen. Ich würde auch gerne über Ihre Lieblings-Python XML-Bibliotheken hören.

War es hilfreich?

Lösung

Ich bin nicht wirklich ein alter Hase in Python, aber hier ist eine XPath-Lösung mit 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")

Mit Ergebnis ...

['a1', 'a2', 'a3']

Andere Tipps

ElementTree 1.3 (leider nicht die 1,2 ist die mit Python enthalten) unterstützt XPath wie folgt aus:

import elementtree.ElementTree as xml

def getValues(tree, category):
    parent = tree.find(".//parent[@name='%s']" % category)
    return [child.get('value') for child in parent]

Dann können Sie tun

>>> tree = xml.parse('data.xml')
>>> getValues(tree, 'CategoryA')
['a1', 'a2', 'a3']
>>> getValues(tree, 'CategoryB')
['b1', 'b2', 'b3']

lxml.etree (die auch die ElementTree Schnittstelle zur Verfügung stellt) wird auch in der gleichen Art und Weise arbeiten.

einen Standard-W3 DOM wie die stdlib des minidom oder 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')

Ich muss zugeben, ich bin ein Fan von xmltramp aufgrund seiner Benutzerfreundlichkeit .

Zugriff auf die oben wird:

  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" )

Sie können dies mit 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')]

Wenn Sie tun Arbeit mit HTML / XML würde ich empfehlen Ihnen einen Blick auf BeautifulSoup zu nehmen. Es ist ähnlich wie die DOM-Struktur enthält aber mehr Funktionalität.

Meine bevorzugte Python XML-Bibliothek ist lxml , die libxml2 einwickelt.
Xpath scheint den Weg hierher zu gehen, so würde ich dies als etwas schreiben wie:

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]

In Python 3.x, eine Liste der Attribute zu holen ist eine einfache Aufgabe, das Mitglied items() der mit

Mit dem ElementTree unter Schnipsel eine Art und Weise zeigt die Liste der Attribute zu erhalten. Beachten, dass dieses Beispiel nicht berücksichtigt Namespaces, die falls vorhanden, werden muß, berücksichtigt.

    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, "]" )

Referenz:

  

Element.items ()
      Gibt das Element-Attribute als eine Folge von (Name, Wert) -Paare.
      Die Attribute werden in beliebiger Reihenfolge zurückgegeben.

Python Handbuch

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top