在Python中使用自定义元素类解析XML

3 投票
6 回答
4111 浏览
提问于 2025-04-16 13:12

我想用Python的xml.etree.ElementTree模块来解析一个xml文档。不过,我希望解析出来的树形结构中的所有元素都能有我自己定义的一些类方法。这就意味着我需要创建一个自己的元素类,但我在告诉解析器使用我自己的元素类时遇到了问题,它总是使用内置的类。

举个例子,假设我想让树中的节点有一个叫做custommethod()的新方法。为此,我需要创建一个元素子类:

class MyElement(xml.etree.ElementTree._Element):

    def custommethod():
        . . . 

现在,当我使用

tree = xml.etree.ElementTree.parse(source)

来解析树时,我希望树中的所有元素都有custommethod()这个方法。所以,

tree.getroot.custommethod() 

应该不会出错。

但我不知道怎么告诉解析器使用我的元素类——这真的可能吗?在Python的文档中有一些关于如何传递自定义解析器给.parse()的提示,但没有很多详细信息。

6 个回答

1

Python3 中,对 Element 类进行猴子补丁(也就是动态修改类的行为)时,效果不太好。我觉得可能有三个原因:

  1. 内置类的 __class____dict 等属性被重写是无效的。
  2. ElementTree 使用 C 语言来处理一些复杂的操作。
  3. 用于解析的类之间关系复杂,像是一张交错的网。

解决办法: 自己创建一个解析函数吧!

import xml.etree.ElementTree
def parse(source):
    """Parse wrapper to build a tree with the extended Node class"""
    treebuilder = xml.etree.ElementTree.TreeBuilder(element_factory=MyElement)
    parser = xml.etree.ElementTree.XMLParser(target=treebuilder)
    tree = xml.etree.ElementTree.parse(source, parser)
    return tree

上面的例子中,使用了你的 MyElement 类来替代树中每个对象的 ElementTree.Element

1

《Dive Into Python》这本书对这个主题讲得很详细。这一章可以在网上找到。在页面底部有一些关于如何创建自定义XML解析器的步骤。我不确定这些内容是否能满足你的需求,但也许这是一个不错的起点。

3

一个自定义的XML解析器是xml.etree.ElementTree.XMLParser的一个子类,它定义了四个函数:

  1. start(self, tag, attrs):当找到一个开始标签时会被调用。
  2. end(self, tag):当找到一个结束标签时会被调用。
  3. data(self, data):当找到数据时会被调用。
  4. close(self):在解析结束时会被调用。

你需要自己管理其他所有事情,比如节点实例是怎么创建的、每个标签的深度等等。注意,data(self, data)这个方法没有标签参数。

撰写回答