Я пытаюсь найти способ добавить номер строки из исходного текста 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-тега. Есть идеи?





Итак, я понял это. Если вы загружаете XML-данные в lxml etree из строкового списка строк XML-файла, а затем используете синтаксический анализатор каналов, вы можете получить атрибут sourceline элемента lxml etree, чтобы получить строку 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() Пока в конце каждой строки есть новая строка, я думаю, что все в порядке.
Если вы используете Python 2.x, вы должны пометить свой вопрос соответствующим образом.