Domanda

Ho bisogno di ottenere un elenco di valori di attributo da bambino elementi in Python.

Il modo più semplice per spiegare con un esempio.

Dato un po ' di XML come questo:

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

Voglio essere in grado di fare qualcosa di simile:

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

Sembra un lavoro per XPath, ma sono aperto a tutte le raccomandazioni.Mi piacerebbe anche sentire il tuo preferito Python e le librerie XML.

È stato utile?

Soluzione

Io non sono davvero un esperto in Python, ma qui è un XPath soluzione utilizzando 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")

Con il risultato...

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

Altri suggerimenti

ElementTree 1.3 (purtroppo non è il 1.2 che è incluso con Python) supporta XPath come questa:

import elementtree.ElementTree as xml

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

Quindi si può fare

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

lxml.etree (che fornisce anche la ElementTree interfaccia) anche funzionano allo stesso modo.

Utilizzando uno standard W3 DOM come stdlib del minidom, o 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')

Devo ammettere che non sono un fan di xmltramp a causa della sua facilità di utilizzo.

L'accesso di cui sopra diventa:

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

Si può fare questo con Coherence

>>> from BeautifulSoup import BeautifulStoneSoup
>>> soup = BeautifulStoneSoup(xml)
>>> def getValues(name):
. . .      return [child['value'] for child in soup.find('parent', attrs={'name': name}).findAll('child')]

Se stai facendo il lavoro con HTML/XML ti consiglierei di dare un'occhiata a Coherence.È simile a un albero DOM, ma contiene più funzionalità.

Il mio preferito python libreria xml è lxml che avvolge libxml2.
Xpath sembra il modo di andare qui, quindi mi piacerebbe scrivere questo come qualcosa di simile a:

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, il recupero di un elenco di attributi è un compito semplice di usare il membro items()

Utilizzando il ElementTree, sotto snippet mostra un modo per ottenere l'elenco di attributi.Si noti che questo esempio non considera gli spazi dei nomi, che, se presenti, dovranno essere valutate.

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

RIFERIMENTO:

Elemento.gli articoli()
Restituisce l'elemento attributi come una sequenza di (nome, valore) coppie.
Gli attributi vengono restituiti in un ordine arbitrario.

Python manuale

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top