1

我正在尝试为ElementTreeElement在 python中创建一个小插件,xml.etree.ElementTree这将允许如下符号:

root = ET.fromstring('<root><a><b attr1="2"/></a></root>')
element1 = root.a
element2 = root.a.b
attr = root.a.b.attr

我试过这个:

import xml.etree.ElementTree as _ET

def __getattr__(self, key):
    return self.find('./' + key)

class ElementTree(_ET.ElementTree):
    __getattr__ = __getattr__


class Element(_ET.Element):
    __getattr__ = __getattr__

但这不起作用,因为,ET.parse等将始终返回内部和对象。ET.fromstringET.ElementTree.findElementElementTree

Monkeypatching 类也不起作用:

>>> xml.etree.ElementTree.Element.__getattr__ = lambda x: x
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-bacb0a64c2e5> in <module>()
----> 1 xml.etree.ElementTree.Element.__getattr__ = lambda x: x

TypeError: can't set attributes of built-in/extension type 'xml.etree.ElementTree.Element'

这在不复制 python etree 模块然后添加的情况下可行__getattr__吗?

相关:如何在 python 中继承 ElementTree.Element 类?

4

2 回答 2

2

由于导入了 Element 和 XMLParser 的 C 实现,因此无法覆盖该类:

# Import the C accelerators
try:
    # Element is going to be shadowed by the C implementation. We need to keep
    # the Python version of it accessible for some "creative" by external code
    # (see tests)
    _Element_Py = Element

    # Element, SubElement, ParseError, TreeBuilder, XMLParser
    from _elementtree import *
except ImportError:
    pass

该模块_elementtree位于Modules/_elementtree.c中。

一个解决方案是复制 python etree 模块,并将导入更改为:

_Element_Py = Element

我对此做了一个简单的实现:https ://github.com/arve0/objectifiedetree

像这样使用:

from objectifiedetree import *

tree = ET.parse('/path/to/file.xml')
# dot notation :-)
el = tree.xpath.to.your.element

# use normal etree attributes
print(el.attrib)

# access name crashes
attrib_el = el.find('./attrib')
于 2015-05-18T10:07:33.073 回答
1

我有一个类似的问题,我无意中找到了一个快速的解决方法:
我导入xmlschema了 Python 3.7 之前的版本,并且在ET.Element使用setattr.

编辑:由于这很有趣,我已经进一步研究了它。这是猴子补丁 ElementTree的方法。

于 2019-02-25T10:46:21.323 回答