Pergunta

Eu preciso para obter uma lista de valores de atributos de elementos filhos em Python.

É mais fácil explicar com um exemplo.

Dado algum XML como este:

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

Eu quero ser capaz de fazer algo como:

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

Parece um trabalho para XPath mas estou aberto a todas as recomendações. Eu também gostaria de ouvir sobre suas bibliotecas favoritas Python XML.

Foi útil?

Solução

Eu não sou realmente um veterano em Python, mas aqui está uma solução XPath usando 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")

Com o resultado ...

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

Outras dicas

ElementTree 1,3 (infelizmente não 1,2 que é o incluído com o Python) suporta XPath assim:

import elementtree.ElementTree as xml

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

Em seguida, você pode fazer

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

lxml.etree (que também fornece a interface ElementTree) também funcionará da mesma forma.

Usando um padrão W3 DOM como minidom do 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')

Devo admitir que eu sou um fã de xmltramp devido à sua facilidade de uso .

Acessando o acima torna-se:

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

Você pode fazer isso com 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')]

Se você está fazendo o trabalho com HTML / XML eu recomendo que você dê uma olhada BeautifulSoup. É semelhante à árvore DOM, mas contém mais funcionalidade.

A minha biblioteca python xml preferido é lxml , que envolve libxml2.
Xpath não parece o caminho a percorrer aqui, então eu ia escrever isso como algo como:

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]

Em Python 3.x, buscando uma lista de atributos é uma tarefa simples de usar o items() membro

Usando o ElementTree, abaixo trecho de código mostra uma maneira de obter a lista de atributos. Observe que este exemplo não considera namespaces, que se presente, terá de ser contabilizado.

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

REFERÊNCIA:

Element.items ()
Retorna os atributos do elemento como uma sequência de (nome, valor) pares.
Os atributos são retornados em uma ordem arbitrária.

Python manual do

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top