我正在使用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
访问“通缉文字”,但这显然很尴尬。
有更好的方法吗?
非常感谢
答案 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
>>>