Как хранить комментарии при разборе XML с помощью Python/ElementTree

В настоящее время используется Python 2.4.3 и не разрешается обновлять

Я хочу изменить значения данного атрибута в одном или нескольких тегах вместе с комментариями XML в обновленном файле.

Мне удалось создать Python script, который принимает XML файл в качестве аргумента, и для каждого указанного тега изменяется атрибут, как показано ниже

def update(file, state):
    global Etree
    try:
        from elementtree import ElementTree
        print '*** using ElementTree'
    except ImportError, e:
        print '***'
        print '*** Error: Must install either ElementTree or lxml.'
        print '***'
        raise ImportError, 'must install either ElementTree or lxml'
    #end try

    doc = Etree.parse(file)
    root = doc.getroot()

    for element in root.findall('.//StateManageable'):
        element.attrib['initialState'] = state
    #end for
    doc.write(file)
#end def

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

Подозреваем, что синтаксический анализ только извлекает XML-структуру, но я думал, что XML-комментарии содержат часть структуры. Я также понимаю, что "удобочитаемое" форматирование моего оригинального документа давно прошло, но я понял, что это ожидаемое поведение, нужно форматировать впоследствии с помощью xmllint --format или XSL.

Ответ 1

Я знаю, что это уже сейчас, но я наткнулся на этот ответ выше о том, как сохранить комментарии. Frederik опубликованные инструкции о том, как помещать комментарии в дерево, по-прежнему работает с текущими версиями ElementTree, но делает больше, чем это необходимо для моего использования, по крайней мере. Он обертывает XML в элемент, что нежелательно для меня. Мне также не нужны инструкции по обработке, но только комментарии. Итак, я урезал класс, который он предоставил на сайте, чтобы это:

import xml.etree.ElementTree as ET

class PCParser(ET.XMLTreeBuilder):

   def __init__(self):
       ET.XMLTreeBuilder.__init__(self)
       # assumes ElementTree 1.2.X
       self._parser.CommentHandler = self.handle_comment

   def handle_comment(self, data):
       self._target.start(ET.Comment, {})
       self._target.data(data)
       self._target.end(ET.Comment)

Чтобы использовать это, создайте экземпляр этого объекта как "парсер", а затем передайте его как параметр ElementTree.parse() следующим образом:

parser = PCParser()
self.tree = ET.parse(self.templateOut, parser=parser)

Я не беру на себя никакой ответственности за код или за недокументированное использование ElementTree, но он работает для меня в сохранении только комментариев, не затрагивая исходную структуру документа. И обратите внимание, что любое будущее изменение ElementTree (кажется маловероятным в этот момент после всех этих лет, хотя) нарушит это.