使用Python解析(可能是非标准的)XML

时间:2014-08-07 09:54:00

标签: python xml parsing

我刚刚开始深入研究Python和XML,我遇到了解析(可能)非标准XML的问题(如果我错了,请纠正我)。

我想通过先前根据其Attribute的值识别Element来解析Element的值。

更多细节: 我有两个元素'Name',我想解析具有属性language == 'en-US'的元素的值。

在我的XML文件中,<'Name' language == 'en-US'>始终显示在<'Name' language == 'es-ES'>之后,我无法获得前者的值(例如B),我只能得到后者(例如A)。

XML文件:

<Eways>
    <Products>
        <Operator>
            <Name language="es-ES">A</Name>
            <Name language="en-US">B</Name>
        </Operator>
    </Products>
</Eways>

Python脚本:

import xml.etree.ElementTree as ET

tree = ET.parse('test.xml')
root = tree.getroot()

for prod in root.findall('Products'):

    for op in prod.findall('Operator'):
        print op.find('Name').text ### <- Testing, here I would expect to print both A and B, but only A is printed.

        for names in op.iter(tag='Name'):   ### Here I iterate over Element 'Name' trying to get the values anyways.
            l_name = names.get('language')

            if l_name == 'en-US':                     ### My objective is to print out the value of Element 'Name' where Attribute language == en-US.
                print 'OK en-US', names.find('Name')  ### I can not get the values (neither A nor B)
            else:
                print 'KO en-US', names.find('Name')

2 个答案:

答案 0 :(得分:4)

element.find()方法只找到第一个匹配元素。如果您希望找到两个元素,则必须使用element.findall()

你不需要在这里做很多循环;只需使用XPath expression

for nametag in tree.findall('./Products/Operator/Name[@language]'):
    print nametag.attrib['language'], nametag.text

XPath查询在这里非常具体;仅找到Name元素内languageOperator属性的Products个元素。

此处的.text属性为您提供了内容。

演示:

>>> from xml.etree import ElementTree as ET
>>> tree = ET.fromstring('''\
... <Eways>
...     <Products>
...         <Operator>
...             <Name language="es-ES">A</Name>
...             <Name language="en-US">B</Name>
...         </Operator>
...     </Products>
... </Eways>
... ''')
>>> for nametag in tree.findall('./Products/Operator/Name[@language]'):
...     print nametag.attrib['language'], nametag.text
... 
es-ES A
en-US B

如果您只想要<Name language="en-US">标签,请调整XPath查询:

for nametag in tree.findall("./Products/Operator/Name[@language='en-US']"):
    print nametag.attrib['language'], nametag.text

[@language='en-US']部分将搜索范围限制为具有特定属性值的那些标记。

答案 1 :(得分:1)

Name元素本身不包含其他元素,因此find会提供None。相反,您只需要元素的text

>>> for p in tree.findall("Products"):
    for op in p.findall("Operator"):
        for n in op.findall("Name"):
            print n.get('language'), n.text


es-ES A
en-US B