在Python中获取XML属性值列表

15

我需要在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库。

7个回答

7

我并不是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")

With result...

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

接受此答案,因为这是我最终使用的。这是一个简单的一行代码,我不需要安装任何额外的模块。也可以查看其他答案 - 那里有一些好东西。 - roomaroo
python test.py 回溯(Traceback)(最近的调用最先被显示): 文件“test.py”,第1行,在<module>中: 导入libxml2 导入错误:没有名为libxml2的模块 - Sreeni Puthiyillam
@SR 查询:您可能需要使用libxml2来使用此libxml2示例。 - Jesse Millikan

7

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接口)可以以相同的方式工作。


4

你可以使用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树,但包含更多功能。

4

使用标准的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')

4

我推荐使用lxml作为我的首选Python XML库,它包装了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]

4
在Python 3.x中,获取属性列表很简单,只需使用成员items()。使用ElementTree,以下代码段展示了获取属性列表的方法。请注意,此示例不考虑命名空间,如果存在命名空间,则需要加以考虑。
    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, "]" )

参考资料:

Element.items()
返回元素属性作为 (名称, 值) 对的序列。
属性以任意顺序返回。

Python 手册


2

我必须承认我是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" )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接