2016-03-02 4 views
0

Я использую lxml для получения name с каждой записи через XPath. По какой-то причине XPath всегда выбирает первый name со следующей записи, несмотря на то, что я подаю только одну запись за раз. Кроме того, он снова получает одно и то же имя при загрузке следующей записи. Что я делаю не так?lxml XPath поглощает элемент из следующей записи

Пример: разобрать следующий 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 

Благодарим за помощь.

ответ

1

Когда iterparse генерирует событие, которое не означает, что она имеет только проанализирован ввод до текущего элемента, он может на самом деле уже разобран за эту точку, как это while you iterate over itparses the input file in chunks из fixed size.

Это, однако, не гарантирует, сколько из входного xml уже было проанализировано, поэтому для события запуска вы не должны пытаться получить доступ к содержимому элементов (иначе, чем его атрибут), как в, возможно, не были проанализированы но вы не должны пытаться получить доступ к любому из следующих братьев и сестер в начале или в конце событий.

В этом случае ваш образец xml очень короткий, поэтому он анализируется как один кусок. Ваше выражение xpath внедрено, поэтому оно всегда будет возвращать все соответствующие элементы документа независимо от данного элемента.

Учитывая, что вы используете только теги REC, ваше выражение xpath должно быть, вероятно, ./name.

Смежные вопросы