Анализ на XML в python при запазване на връзка към позиция в оригиналния файл

Трябва да извлека определени данни от XML файлове, но също така да знам позицията, където е бил разположен извлеченият елемент в оригиналния XML файл - като отместване на знака от началото на файла или номер на ред + позиция в този ред.

Често използваните XML библиотеки на python изглежда не предоставят такава функционалност.

Има подобен въпрос Получаване на информация за позиция при анализиране на 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 входът, да се добавят атрибут(и) на "позиция", отнасящ се до оригиналната позиция на потока, да се анализира XML с обикновена библиотека и да се използва този атрибут(и) по-късно за потребителска информация...

Кажете ни как го направихте!

person Oct    schedule 03.08.2016