使用Python,当兄弟元素的标签是我要查找的字符串时,如何获取XML元素的文本?

时间:2014-02-27 22:45:06

标签: python xml xml-parsing parent-child elementtree

我希望这是一个简单的问题。我将尽力明确我要完成的任务。下面只是我的XML文件的一小部分。我想要做的是看看元素结构是否存在。如果是,则代码继续。然后我尝试查看所有元素,如果子元素(test)为False,那么我想得到id元素的文本。如果元素在元素之前,我将使用以下代码。我想确保无论订单ID是在(在之前还是之后)列出的,我都会获得属于相应父级的相应子ID。目前我正在使用元素树。

<data>
<cs>
    <c>
        <id>1</id>
        <test>True</test>
        <test2>False</test2>
        <test3>False</test3>
        <test4>True</test4>
    </c>
    <c>
        <test>False</test>
        <test2>False</test2>
        <test3>False</test3>
        <id>2</id>
        <test4>True</test4>
    </c>
</cs>

elementTree = self.param2
isCS = elementTree.find('./cs')
getCS = elementTree.findall('./cs')
CIDs = []

if isCS is None:
    raise Exception("Unable to find the 'cs' element structure under <data>. Failed to build a list of CID's.")
else:
    # Build the list of CID's.
    for cs in getCS:
        for c in cs:
            for child in c.getchildren():
                if str(child.tag).lower() == 'id':
                    myid = child.text
                elif str(child.tag).lower() == 'test' and str(child.text).lower() == 'false':
                    CIDs.append(myid)

    print CIDs

我得到的内容(取决于列出元素的顺序)是以下输出:

1

当我真的期待以下内容时:

2

我只需要知道如何根据我在文本中找到的内容对子元素进行特定测试并获取数据。

2 个答案:

答案 0 :(得分:1)

未经测试。

# Build the list of CID's.
for cs in getCS:
    for c in cs:
        myid = None
        mytest = None
        for child in c.getchildren():
            if str(child.tag).lower() == 'id':
                myid = child.text
            elif str(child.tag).lower() == 'test' and str(child.text).lower() == 'false':
                mytest = True
        if myid and mytest:
            CIDs.append(myid)

print CIDs

可能可以通过不同的方式完成 - 使用find()元素上的某个特殊功能或findall()c


编辑:

lxml示例(仅作为示例,因此不是“防弹”)

import lxml.etree

xml = '''<data>
<cs>
    <c>
        <id>1</id>
        <test>True</test>
        <test2>False</test2>
        <test3>False</test3>
        <test4>True</test4>
    </c>
    <c>
        <test>False</test>
        <test2>False</test2>
        <test3>False</test3>
        <id>2</id>
        <test4>True</test4>
    </c>
</cs>
</data>'''

tree = lxml.etree.fromstring(xml)

all_c = tree.findall('./cs/c')

#print all_c

results = []

for c in all_c:
    #print c

    myid = c.find('id').text
    mytest = (c.find('test').text.lower() == 'false')

    print myid, mytest

    if myid and mytest: 
        results.append(myid)

print "results:", results   

答案 1 :(得分:1)

这是一种方法:

cids = []
for c_node in tree.findall('.//cs/c'):
    test_node = c_node.find('test')
    if test_node is not None and test_node.text == 'False':
        id_node = c_node.find('id')
        cids.append(id_node.text)

print cids

讨论

  • for循环中,我找到 cs
  • 下的所有 c 节点
  • 接下来,我检查了“test”节点是否存在并且 False
  • 最后,我将 id 附加到列表