2015-05-16 4 views
0

Я пытаюсь создать небольшой аддон для ElementTree и Element в Питона xml.etree.ElementTree, который позволил бы нотации, как:Наследовать или издеваться над python etree.ElementTree.Element возможно?

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.fromstring, ET.ElementTree.find и т. д. всегда будут возвращать внутренние объекты Element и ElementTree.

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' 

Является ли это выполнимо без копирования модуля etree питона, а затем добавить __getattr__?

Похожие: How to inherit ElementTree.Element class in python?

ответ

0

Переопределение класса не представляется возможным из-за import of the Element and XMLParser's C implementation:

# 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.

Раствор должен был бы скопировать модуль питона 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') 
Смежные вопросы