lxml XPath 从下一条记录中吞噬一个元素
lxml XPath gobbles an element from the next record
我正在使用 lxml 通过 XPath
从每条记录中获取 name
s。出于某种原因 XPath
总是首先从下一条记录中获取 name
,尽管我一次只提供一条记录。此外,它还会在加载下一条记录时再次获取相同的名称。我究竟做错了什么?
示例:解析以下 sample.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<records>
<REC>
<name>Alpha</name>
<name>Beta</name>
<name>Gamma</name>
</REC>
<REC>
<name>Delta</name>
</REC>
</records>
代码:
#!/usr/bin/env python3
from lxml import etree
class Nam:
XPATH = '/records/REC/name'
def __init__(self):
self.xp = etree.XPath(self.XPATH)
def getvals(self, doc):
for no, el in enumerate(self.xp(doc)):
print("{} val: {} ".format(no, el.text))
print()
def main():
nam = Nam()
context = etree.iterparse("sample.xml", events=('end',), tag='REC')
for event, elem in context:
print("Element: {}".format( etree.tostring(elem).decode()))
nam.getvals(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
if __name__ == '__main__':
main()
输出:
Element: <REC>
<name>Alpha</name>
<name>Beta</name>
<name>Gamma</name> </REC>
0 val: Alpha
1 val: Beta
2 val: Gamma
3 val: Delta
Element: <REC>
<name>Delta</name> </REC>
0 val: Delta
感谢您的帮助。
当 iterparse
发出一个事件时,并不意味着它只解析了当前元素的输入,它实际上可能已经解析了超出该点的 while you iterate over it it parses the input file in chunks of a fixed size。
然而,这意味着无法保证已经解析了多少输入 xml,因此对于开始事件,您不应尝试访问元素内容(除了其属性),如可能尚未解析,您不应尝试在开始或结束事件中访问以下任何兄弟。
在这种情况下,您的示例 xml 非常短,因此它被解析为一个块。您的 xpath 表达式是有根的,所以它总是 return 文档的所有匹配元素,而不考虑给定的元素。
鉴于您只处理 REC
标签,您的 xpath 表达式可能应该是 ./name
。
我正在使用 lxml 通过 XPath
从每条记录中获取 name
s。出于某种原因 XPath
总是首先从下一条记录中获取 name
,尽管我一次只提供一条记录。此外,它还会在加载下一条记录时再次获取相同的名称。我究竟做错了什么?
示例:解析以下 sample.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<records>
<REC>
<name>Alpha</name>
<name>Beta</name>
<name>Gamma</name>
</REC>
<REC>
<name>Delta</name>
</REC>
</records>
代码:
#!/usr/bin/env python3
from lxml import etree
class Nam:
XPATH = '/records/REC/name'
def __init__(self):
self.xp = etree.XPath(self.XPATH)
def getvals(self, doc):
for no, el in enumerate(self.xp(doc)):
print("{} val: {} ".format(no, el.text))
print()
def main():
nam = Nam()
context = etree.iterparse("sample.xml", events=('end',), tag='REC')
for event, elem in context:
print("Element: {}".format( etree.tostring(elem).decode()))
nam.getvals(elem)
elem.clear()
while elem.getprevious() is not None:
del elem.getparent()[0]
if __name__ == '__main__':
main()
输出:
Element: <REC>
<name>Alpha</name>
<name>Beta</name>
<name>Gamma</name> </REC>
0 val: Alpha
1 val: Beta
2 val: Gamma
3 val: Delta
Element: <REC>
<name>Delta</name> </REC>
0 val: Delta
感谢您的帮助。
当 iterparse
发出一个事件时,并不意味着它只解析了当前元素的输入,它实际上可能已经解析了超出该点的 while you iterate over it it parses the input file in chunks of a fixed size。
然而,这意味着无法保证已经解析了多少输入 xml,因此对于开始事件,您不应尝试访问元素内容(除了其属性),如可能尚未解析,您不应尝试在开始或结束事件中访问以下任何兄弟。
在这种情况下,您的示例 xml 非常短,因此它被解析为一个块。您的 xpath 表达式是有根的,所以它总是 return 文档的所有匹配元素,而不考虑给定的元素。
鉴于您只处理 REC
标签,您的 xpath 表达式可能应该是 ./name
。