1

Тема: XML strange separation

Отже, парсимо xml файлик на 1 гб.
Структура проста, рядки:

<ITEM>
      <STATE>якийсь текст</STATE>
      <FL>ПІБ</FL>
      <ADDRESS>91007, Дніпропетровська обл., місто Дніпро, ВУЛИЦЯ Джв, будинок 55</ADDRESS>
      <REC>98.22 і довгий текст до 255 символів</REC>
   </ITEM>

Використовую python3, lxml.
Оскільки файл агромний, то щоб не вантажити в пам'ять, використовується Event Driven Parsing, через імплементацію інтерфейсу target. https://lxml.de/tutorial.html#event-driven-parsing

Виглядає це так:

class ParserTarget:
     events = []
     close_count = 0

     def start(self, tag, attrib):
         self.events.append(("start", tag, attrib))

     def close(self):
         # when closing attr fired
         events, self.events = self.events, []
         self.close_count += 1
         return events

    def data(self, data):
         # when some data exists, like: data=='якийсь тексту'
         pass

ну і парсер читає по трішки файл, і потім викликає відповідний метод.

Проблема в тому, що парсер викликає метод data() по кілька разів. Напр, якщо є дані:

якийсь текст

парсер викличе:

data('якийсь текст')

Але, якщо:

100 якийсь текст

парсер викличе:

data('100 ')
data('якийсь текст')

І те саме з лапками. Дивна поведінка, документації про це жодної не знайшов, лише:

Called for character data and expanded character references and entities. May be called more than once for each character data section. The text string may be either an 8-bit string containing ASCII data, or a Unicode string

звідси: http://effbot.org/elementtree/elementtree-xmlparser.htm посилання з доки

Що таке character data section? Як це розуміти?

Можливо хтось парсив, знає, допоможе?

2

Re: XML strange separation

Раптом в когось виникне схожа проблема.

Вирішив, написавши свій TargetManager (хз, як це в них називається правильно)

    START = 'start'
    END = 'end'
    context = etree.iterparse(filepath, events=(START, END, ))

    for event, elem in context:
        if event == START:
            # print(elem.tag)
            target.start(elem.tag)
        if event == END:
            target.data(elem.text)
            target.end(elem.tag)