获取Python中XML属性值的列表

时间:2020-03-05 18:59:57  来源:igfitidea点击:

我需要从Python的子元素中获取属性值的列表。

举个例子最容易解释。

给定一些这样的XML:

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

我希望能够执行以下操作:

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

它看起来像XPath的工作,但我愿意接受所有建议。我也想听听我们最喜欢的Python XML库。

解决方案

回答

我必须承认我很喜欢xmltramp,因为它易于使用。

访问以上内容将成为:

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

回答

我们可以使用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')]

如果我们正在使用HTML / XML进行工作,我建议我们看一看BeautifulSoup。它类似于DOM树,但包含更多功能。

回答

我对Python并不是真正的老手,但是这是一个使用libxml2的XPath解决方案。

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

结果...

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

回答

使用标准W3 DOM,例如stdlib的minidom或者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')

回答

ElementTree 1.3(不幸的是不是Python附带的1.2)支持XPath,如下所示:

import elementtree.ElementTree as xml

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

那你可以做

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

lxml.etree(也提供ElementTree接口)也将以相同的方式工作。

回答

我首选的python xml库是lxml,它包装了libxml2.
Xpath似乎是解决问题的方法,因此我将其编写为:

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]