按绝对路径访问XML节点

时间:2017-11-28 13:55:34

标签: python xml

我正在使用Python 2.7解析xml文件 我正在使用xml.etree.ElementTree模块,在OSX 10.10上工作 该文件非常大,我希望能够以合理有效的方式访问特定节点。如果我知道节点的绝对路径,我可以通过不断使用.find()来访问它,但肯定有一种更简单的方法。

例如,如果xml是

import xml.etree.ElementTree as ET
tree = ET.parse('file.xml')
root = tree.getroot()

<A>
    <C>
    unwanted text
    </C>
    <B> 
        <C>
        wanted text
        </C>
    </B>
</A>

我可以使用root.find("A").find("B").find("C").text访问“通缉文字”,但这显然很尴尬。

有更好的方法吗?

非常感谢

2 个答案:

答案 0 :(得分:0)

您可以使用findall和xpath表达式,例如:

import xml.etree.ElementTree as ET
xml = """
<A>
    <C>
    unwanted text
    </C>
    <B> 
        <C>
        wanted text
        </C>
    </B>
    <B> 
        <C>
        wanted text 2
        </C>
    </B>
</A>
"""

tree = ET.ElementTree(ET.fromstring(xml))
c_nodes = tree.getroot().findall("B/C")

for c in c_nodes:
    print(c.text)

这将返回A和B的所有C元素子节点,并且应该非常快。

您可以在此处查看所有受支持的XPath操作:https://docs.python.org/2/library/xml.etree.elementtree.html

答案 1 :(得分:0)

对于非常大的xml文件,您可能会使用iterparse,以避免将整个文件读入内存。

此处,默认情况下,iterparse会监视每个元素的关闭。在for循环中,当代码注意到'C'元素时,它输出'text'内容。

from xml.etree import ElementTree

for ev, el in ElementTree.iterparse('ludog.xml'):
    if el.tag=='C':
        print (el.text)

编辑以回复评论。

我已将xml扩展到此,以演示后面代码中的原理。

<more>
    <D>
        <C>
            other text
        </C>
    </D>
    <A>
        <B> 
            <C>
            text
            </C>
        </B>
    </A>
</more>
可以使用

iterparse来指示xml元素的开头和结尾。在这里,我使用它来跟踪iterparse当前是在“A”元素还是“B”元素中解析,或两者都是。当它在两者内部并且遇到'C'元素时,代码会发出'C'元素的'text'。

>>> from xml.etree import ElementTree
>>> inside_A = False
>>> inside_B = False
>>> for ev, el in ElementTree.iterparse('ludog.xml', events=('start', 'end')):
...     if el.tag=='A':
...         inside_A = ev=='start'
...     if el.tag=='B':
...         inside_B = ev=='start'
...     if el.tag=='C' and ev=='end' and inside_A and inside_B:
...         print(el.text)
... 

            text

>>>