Добавление номера строки в элемент lxml - PullRequest
0 голосов
/ 07 марта 2019

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

       line_num = element.xml_line_num

Я знаю, что в элементах дерева lxml есть свойство sourceline, но это ненадежно.Это не всегда правильно.С базовым ElementTree, предоставленным по умолчанию в python 2.7, у парсера по умолчанию был метод GetInputContext (), который я мог использовать, просматривая строки в исходном XML-тексте и сравнивая его с текстом, полученным из этого метода входного контекста.Я быстро обнаружил, что CurrentLineNumber из парсера по умолчанию ненадежен.Пришлось прибегнуть к сравнению исходных строк XML.

Во всяком случае, я просто недостаточно хорош в моем понимании подклассов частей модулей и налаживания работы.Зрелые и широко используемые модули Python, как правило, очень тщательны и обширны в использовании столь многих аспектов Python, и когда вы начинаете понимать, что имеете дело с реализациями c-кода базовых базовых классов, это вызывает путаницу.Таким образом, некоторая помощь, и, возможно, некоторый пример кода, будет очень признателен.Заранее спасибо!

Позвольте мне добавить некоторые разъяснения.Я хотел бы иметь код, который выглядит следующим образом:

from lxml import etree as ET


xml_tree = ET.fromstringlist(xml_file_lines)

for xml_element in xml_tree.iter():

    line_num = xml_element.xml_line_num

'xml_file_lines' представляет собой список строк файла XML, считанных из файла.Некоторые из которых являются пустыми строками.Что я могу сказать о строках XML в обрабатываемых мной файлах, так это о том, что непробельные строки и строки, не являющиеся комментариями, отображаются как открывающие, закрывающие, самозакрывающиеся или открывающие / закрывающие элементы.То есть так:

<tag>text</tag>
<tag1 />
<tag2 id = "yum" />
<tag2 id = "delicious" name = "tasty">text</tag>
<tag3>
     <tag4>hungry</tag4>
<tag3>

В этих файлах XML никогда не будет более одного открывающего или закрывающего тега XML в одной строке.Есть идеи?

1 Ответ

0 голосов
/ 26 марта 2019

Хорошо, я понял это. Если вы загружаете данные XML в файл lxml etree из списка строк строк файла XML, то с помощью анализатора каналов вы можете получить атрибут sourceline элемента etx lxml, чтобы получить строку файла XML, из которой происходит каждый элемент XML. Код ниже демонстрирует, что я сделал:

from lxml import etree as ET

class LineNumberingParser(ET.XMLParser):

      def __init__(self, *args, **kwargs):

          super(self.__class__, self).__init__(*args, **kwargs)

      def feed(self, data):

           line = data.strip() + "\n"
           super(self.__class__, self).feed(line)     

Тогда все, что вам нужно сделать, это указать lxml использовать ваш анализатор строк:

from lxml import etree as ET

class LineNumberingParser(ET.XMLParser):

      def __init__(self, *args, **kwargs):

          super(self.__class__, self).__init__(*args, **kwargs)

      def feed(self, data):

           line = data.strip() + "\n"
           super(self.__class__, self).feed(line)     

with open(file.xml, "rU") as FILE:
     xml_file_lines = FILE.readlines()

xml_tree = ET.fromstringlist(xml_file_lines, parser=LineNumberingParser()) 

for xml_element in xml_tree.iter():
    print "XML tag " + xml_element.tag + " found on file line " + str(xml_element.sourceline) + "\n" 

Может даже не потребоваться создавать подкласс lxml XMLParser. Все, что может понадобиться, - это прочитать строки файла XML в виде списка строк и использовать etree.fromstringlist (). Пока в конце каждой строки есть новая строка, я думаю, что это все хорошо.

...