Как сохранить комментарии при разборе XML с помощью Python / ElementTree - PullRequest
11 голосов
/ 18 декабря 2010

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

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

Мне удалось создать скрипт Python, который принимает 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 Ответ

17 голосов
/ 06 декабря 2014

Я знаю, что это уже старо, но я наткнулся на этот ответ выше о том, как сохранить комментарии. опубликованная инструкция Фредерика о том, как поместить комментарии в дерево, по-прежнему работает с текущими версиями 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 (хотя вряд ли в этот момент после всех этих лет) сломают это.

...