Разбор XML в python при сохранении ссылки на позицию в исходном файле

Мне нужно извлечь определенные данные из файлов XML, но также знать позицию, в которой извлеченный элемент находился в исходном файле XML - как смещение символа от начала файла или номер строки + позиция в этой строке.

Обычно используемые библиотеки Python XML, похоже, не предоставляют такой функциональности.

Существует аналогичный вопрос Получение информации о позиции при разборе HTML в Python это было решено путем написания специальной оболочки вокруг html5lib; но эта библиотека мне не подойдет, так как конкретные данные не являются HTML.

Существуют ли какие-либо анализаторы XML, которые хранят информацию о позиции элемента, или для этого мне нужно выполнить собственный анализ?


person Peteris    schedule 03.08.2016    source источник
comment
lxml имеет sourceline, но это дает вам только номер строки   -  person gsnedders    schedule 03.08.2016


Ответы (2)


Эти функции есть у парсера Expat. Вот быстрый и грязный пример:

from xml.parsers.expat import ParserCreate, ExpatError, errors

p = ParserCreate()

def start_element(name, attrs):
    print(f"Start element at line {p.CurrentLineNumber}, col. {p.CurrentColumnNumber}, byte {p.CurrentByteIndex}: {name}")
def end_element(name):
    print(f"End element at line {p.CurrentLineNumber}, col. {p.CurrentColumnNumber}, byte {p.CurrentByteIndex}:", name)
def char_data(data):
    print(f"Character data at line {p.CurrentLineNumber}, col. {p.CurrentColumnNumber}, byte {p.CurrentByteIndex}:", repr(data))
def parse_xml(xml: str):
    try:
        p.StartElementHandler = start_element
        p.EndElementHandler = end_element
        p.CharacterDataHandler = char_data
        p.Parse(xml)
    except ExpatError as err:
        print("Error:", errors.messages[err.code])

parse_xml("<root>abc <tag>ghi</tag>\n def</root>")

и вот вывод этого кода:

Start element at line 1, col. 0, byte 0: root
Character data at line 1, col. 6, byte 6: 'abc '
Start element at line 1, col. 10, byte 10: tag
Character data at line 1, col. 15, byte 15: 'ghi'
End element at line 1, col. 18, byte 18: tag
Character data at line 1, col. 24, byte 24: '\n'
Character data at line 2, col. 0, byte 25: ' def'
End element at line 2, col. 4, byte 29: root

Как видите, он может печатать номер строки, номер столбца и позицию байта каждого элемента XML.

person JustAC0der    schedule 09.01.2021

Я не думаю, что такие вещи существуют. Большинство синтаксических анализаторов сначала выполняют синтаксический анализ (преобразуют текстовый поток в токены, а затем анализируют его в дереве). К тому времени они обычно хорошо знают, где находятся в исходном потоке (это требуется для вывода ошибок парсинга). Однако после того, как дерево объектов построено, эта информация становится малопригодной и более недоступной в результирующих объектах.

Хорошим и уродливым хаком (одновременно!) будет токенизация ввода XML, добавление атрибута (ов) «position», ссылающегося на исходную позицию потока, анализ XML с помощью обычной библиотеки и использование этого атрибута (ов) позже для информации пользователя...

Дайте нам знать, как вы это сделали!

person Oct    schedule 03.08.2016