lxml XPath 从下一条记录中吞噬一个元素

lxml XPath gobbles an element from the next record

我正在使用 lxml 通过 XPath 从每条记录中获取 names。出于某种原因 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