子类化ElementTree解析器以保留注释



尝试使用ElementTree解析xml文件;由于默认情况下解析器不保留注释,因此使用了http://bugs.python.org/issue8277:

import xml.etree.ElementTree as etree
class CommentedTreeBuilder(etree.TreeBuilder):
    """A TreeBuilder subclass that retains comments."""
    def comment(self, data):
        self.start(etree.Comment, {})
        self.data(data)
        self.end(etree.Comment)
parser = etree.XMLParser(target = CommentedTreeBuilder())

以上内容见文件.py。使用进行测试

class TestDocument(unittest.TestCase):
    def setUp(self):
        filename = os.path.join(sys.path[0], "data", "facilities.xml")
        self.doc = etree.parse(filename, parser = documents.parser)
    def testClass(self):
        print("Class is {0}.".format(self.doc.__class__.__name__))
        #commented out tests.
if __name__ == '__main__':
    unittest.main()

此barfs带有:

Traceback (most recent call last):
File "/home/goncalo/documents/games/ja2/modding/mods/xml-overhaul/src/scripts/../tests/test_documents.py", line 24, in setUp
    self.doc = etree.parse(filename, parser = documents.parser)
File "/usr/lib/python3.3/xml/etree/ElementTree.py", line 1242, in parse
    tree.parse(source, parser)
File "/usr/lib/python3.3/xml/etree/ElementTree.py", line 1726, in parse
    parser.feed(data)
IndexError: pop from empty stack

我做错了什么?顺便说一下,文件中的xml是有效的(由独立程序检查),并且是utf-8编码的。

备注:

  • 使用Python 3.3。在Kubuntu 13.04中,以防万一它是相关的。我确保使用"python3"(而不仅仅是"python")来运行测试脚本

edit:这是使用的示例xml文件;它很小(让我们看看我是否能正确格式化):

<?xml version="1.0" encoding="utf-8"?>
<!-- changes to facilities.xml by G. Rodrigues: ar overhaul.-->
<SECTORFACILITIES>
    <!-- Drassen -->
    <!-- Small airport -->
    <FACILITY>
        <SectorGrid>B13</SectorGrid>
        <FacilityType>4</FacilityType>
        <ubHidden>0</ubHidden>
    </FACILITY>
</SECTORFACILITIES>

您添加的示例XML在2.7中对我有效,但在3.3中使用了您描述的堆栈跟踪。

问题似乎出在第一个注释上——在XML声明之后,在第一个元素之前。它不是2.7中树的一部分(但没有引发异常),并导致3.3中的异常。

请参阅Python问题#17901:在包含上述修复程序的Python 3.4中,pop from empty stack没有出现,而是引发了ParseError: multiple elements on top level

这是有道理的:如果你想在树中保留注释,就需要将它们作为节点。XML只允许在文档的顶层有一个节点,因此在第一个"真实"元素之前不能有注释(如果强制解析器保留commments)。

不幸的是,我认为这是您唯一的选择:从XML文件中删除根文档节点之外的注释——要么在原始文件中,要么在解析之前剥离它们。

最新更新