Итак, я разбираю некоторые XML файлы, используя Python 3.2.1 cElementTree, и во время разбора я заметил, что в некоторых тегах отсутствует информация об атрибутах. Мне было интересно, есть ли простой способ получить номера строк этих элементов в XML файле.
Есть ли способ получить номер строки из элемента ElementTree
Ответ 1
Глядя на документы, я не вижу возможности сделать это с помощью cElementTree.
Однако мне повезло с lxml версией XML-реализации.
Предполагалось, что это будет почти замена, используя libxml2. А элементы имеют атрибут sourceline
. (Помимо получения множества других функций XML).
Единственное предостережение в том, что я использовал его только в python 2.x - не знаю, как это работает, если оно работает под 3.x, но может стоить того.
Приложение: со своей главной страницы они говорят:
Инструментарий lxml XML - это связка Pythonic для библиотек C libxml2 и libxslt. Он уникален тем, что сочетает скорость и XML полнота этих библиотек с простотой родной Python API, в основном совместимый, но превосходящий хорошо известный API ElementTree. Последняя версия работает со всеми версиями CPython от 2,3 до 3,2. См. Введение для получения дополнительной информации о фон и цели проекта lxml. Некоторые распространенные вопросы ответил в FAQ.
Итак, похоже, что python 3.x в порядке.
Ответ 2
Мне понадобилось время, чтобы понять, как это сделать, используя 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())
Ответ 3
Я сделал это в 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.
Ответ 4
Один (хакерский) способ сделать это - вставить фиктивный атрибут, содержащий номер строки в каждый элемент, перед разбором. Вот как я это сделал с мини-министром:
строка отчета/столбца происхождения python XML node
Это может быть тривиально настроено на cElementTree (или на самом деле любой другой синтаксический анализатор python XML).