Можно ли прервать синтаксический анализ большого xml-файла в середине с помощью целевого интерфейса lxml? - PullRequest
1 голос
/ 04 ноября 2011

Я получаю информацию из большого XML-файла и использую для этого Python с целевым интерфейсом синтаксического анализа .Я хотел бы возможность установить предел, после которого анализ останавливается.Вот некоторый код:

Целевой код анализатора:

class TitleTarget(object):
    def __init__(self,  limit=None):
        self.limit = limit
        self.counter = 0

    def start(self, tag, attrib):
        if self.limit and self.counter > self.limit:
            #### BREAK HERE ####
            return False
        #doProcessing(attrib)
        self.counter = self.counter + 1

    def end(self, tag):
        pass

    def data(self, data):
        pass

def close(self):
    pass

Код, инициирующий синтаксический анализ:

parser = etree.XMLParser(target = TitleTarget(limit)) 
etree.parse(file, parser)  

Я знаю, что обработка переходит к «BREAK HERE»-линии, но я не нашел никакого способа остановить анализ.Я попытался вернуть True, False, [], and raising Error, похоже, никто не работает.Он всегда обрабатывается, пока файл не заканчивается.

Есть ли способ остановить обработку бу, используя этот метод.

1 Ответ

1 голос
/ 04 ноября 2011

Вместо использования etree.parse(file, parser) вы можете перебирать строки в file и вызывать parser.feed в каждой строке. Это дает вам контроль над тем, когда выйти из цикла.

Теперь вы можете просто установить self.done=True в цели и проверить на target.done в цикле подачи:


import lxml.etree as ET
class HaltingTarget(object):
    def __init__(self, limit=None):
        self.done=False
        self.limit=limit
        self.counter=0
        self.result=[]
    def start(self, tag, attrib):
        if self.limit and self.counter>self.limit:
            self.done=True
            return
        if attrib:
            self.result.append(attrib)
        self.counter+=1
    def end(self, tag):
        pass
    def data(self, data):
        pass
    def comment(self, text):
        pass
    def close(self):
        return
def halt_parser():
    content='''\
        <node1>
          <Title a1="x1"> My Title </Title>
          <node2 a1="x2"> ... </node2>
          <node2 a1="x1"> ... </node2>
        </node1>
        '''
    target=HaltingTarget()
    parser=ET.XMLParser(target=target)
    for line in content.splitlines():
        parser.feed(line.strip())
        if target.done: break
    # We can't call parser.close() since the XML we've fed it is probably 
    # incomplete. We don't plan to use `parser` anymore, so delete it.
    del parser
    print(target.result)
    # [{'a1': u'x1'}, {'a1': u'x2'}, {'a1': u'x1'}]
...