问题 如何在使用Python / ElementTree解析XML时保留注释


目前使用的是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注释的事实,但它们早已不复存在,这很糟糕。

怀疑parse只检索XML结构,但我认为XML-comments是结构的一部分。我也意识到我的原始文档的“人类可读”格式早已不复存在,但我已经意识到预期的行为,需要在之后使用格式化 xmllint --format 或XSL。


4094
2017-12-17 21:07


起源

2.4?我的同情。
你打赌,我很难开始创建我的第一个脚本来实现这一点 所有 我发现的好东西是2.7 :-) - rhellem


答案:


我知道现在已经老了,但我偶然发现了上面关于如何保留评论的答案。弗雷德里克 发表的指示 关于如何将注释放入树中仍然可以使用当前版本的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的任何未来更改(尽管这些年后似乎不太可能)将打破这一点。


16
2017-12-06 15:46



我在用着 lxml 为此,并试图让它工作。我正在进口 from lxml import etree as et。我想我可以替换 self._parser 同 et 但无法弄清楚要用什么代替 self._target。你能帮我吗? - eoinzy