Есть ли способ получить номер строки из ElementTree Element - PullRequest
16 голосов
/ 05 августа 2011

Итак, я анализирую некоторые XML-файлы, используя cElementTree в Python 3.2.1, и во время синтаксического анализа я заметил, что в некоторых тегах отсутствует информация об атрибутах. Мне было интересно, есть ли какой-нибудь простой способ получить номера строк этих элементов в XML-файле.

Ответы [ 4 ]

14 голосов
/ 05 августа 2011

Глядя на документы, я не вижу способа сделать это с помощью cElementTree.

Однако мне повезло с lxml версией реализации XML. Предполагается, что замена будет почти каплей с использованием libxml2. И элементы имеют атрибут sourceline. (Также как и множество других функций XML).

Единственное предостережение в том, что я использовал его только в python 2.x - не уверен, как / если он работает под 3.x - но, возможно, стоит взглянуть.

Приложение: с их первой страницы они говорят:

Инструментарий lxml XML представляет собой Pythonic-привязку для библиотек C libxml2 и libxslt. Он уникален тем, что сочетает в себе скорость и XML полнота этих библиотек с простотой нативный Python API, в основном совместимый, но превосходящий хорошо известный ElementTree API. Последний выпуск работает со всеми версиями CPython от 2,3 до 3,2. Смотрите введение для получения дополнительной информации о Предпосылки и цели проекта lxml. Некоторые общие вопросы ответил в FAQ.

Похоже, что Python 3.x в порядке.

9 голосов
/ 05 апреля 2016

Мне потребовалось некоторое время, чтобы понять, как это сделать с помощью Python 3.x (здесь используется 3.3.2), поэтому я решил подвести итог:

# Force python XML parser not faster C accelerators
# because we can't hook the C implementation
sys.modules['_elementtree'] = None
import xml.etree.ElementTree as ET

class LineNumberingParser(ET.XMLParser):
    def _start_list(self, *args, **kwargs):
        # Here we assume the default XML parser which is expat
        # and copy its element position attributes into output Elements
        element = super(self.__class__, self)._start_list(*args, **kwargs)
        element._start_line_number = self.parser.CurrentLineNumber
        element._start_column_number = self.parser.CurrentColumnNumber
        element._start_byte_index = self.parser.CurrentByteIndex
        return element

    def _end(self, *args, **kwargs):
        element = super(self.__class__, self)._end(*args, **kwargs)
        element._end_line_number = self.parser.CurrentLineNumber
        element._end_column_number = self.parser.CurrentColumnNumber
        element._end_byte_index = self.parser.CurrentByteIndex
        return element

tree = ET.parse(filename, parser=LineNumberingParser())
2 голосов
/ 05 августа 2011

Я сделал это в elementtree, создав подкласс ElementTree.XMLTreeBuilder.Затем, где у меня есть доступ к self._parser (Expat), он имеет свойства _parser.CurrentLineNumber и _parser.CurrentColumnNumber.

http://docs.python.org/py3k/library/pyexpat.html?highlight=xml.parser#xmlparser-objects содержит подробную информацию об этих атрибутах

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

Если вашXML-файл включает в себя дополнительные XML-файлы. Вы должны сделать некоторые вещи, которые я не помню и не были хорошо документированы для отслеживания текущего XML-файла.

0 голосов
/ 22 декабря 2014

Один (хакерский) способ сделать это - вставить атрибут-пустышку, содержащий номер строки в каждый элемент, перед синтаксическим анализом.Вот как я это сделал с minidom:

строка отчета Python / столбец происхождения узла XML

Это можно легко настроить на cElementTree (или фактически любой другой питон)Парсер XML).

...