我有以下代码可以使用:
import xml.etree.ElementTree as etree
def get_path(self):
parent = ''
path = self.tag
sibs = self.parent.findall(self.tag)
if len(sibs) > 1:
path = path + '[%s]'%(sibs.index(self)+1)
current_node = self
while True:
parent = current_node.parent
if not parent:
break
ptag = parent.tag
path = ptag + '/' + path
current_node = parent
return path
etree._Element.get_path = get_path
etree._Element.parent = None
class XmlDoc(object):
def __init__(self):
self.root = etree.Element('root')
self.doc = etree.ElementTree(self.root)
def SubElement(self, parent, tag):
new_node = etree.SubElement(parent, tag)
new_node.parent = parent
return new_node
doc = XmlDoc()
a1 = doc.SubElement(doc.root, 'a')
a2 = doc.SubElement(doc.root, 'a')
b = doc.SubElement(a2, 'b')
print etree.tostring(doc.root), '\n'
print 'element:'.ljust(15), a1
print 'path:'.ljust(15), a1.get_path()
print 'parent:'.ljust(15), a1.parent, '\n'
print 'element:'.ljust(15), a2
print 'path:'.ljust(15), a2.get_path()
print 'parent:'.ljust(15), a2.parent, '\n'
print 'element:'.ljust(15), b
print 'path:'.ljust(15), b.get_path()
print 'parent:'.ljust(15), b.parent
这导致此输出:
<root><a /><a><b /></a></root>
element: <Element a at 87e3d6c>
path: root/a[1]
parent: <Element root at 87e3cec>
element: <Element a at 87e3fac>
path: root/a[2]
parent: <Element root at 87e3cec>
element: <Element b at 87e758c>
path: root/a/b
parent: <Element a at 87e3fac>
现在这与原始代码有很大的不同,但我不允许分享。
这些函数效率不是太低,但是当我从cElementTree切换到ElementTree时会有一个显着的性能下降,但是根据我的实验,似乎猴子修补cElementTree是不可能的,所以我不得不切换。
我需要知道的是,是否有一种方法可以将方法添加到cElementTree,或者是否有更有效的方法来实现这一点,这样我就可以恢复一些性能。
只是为了让你知道我正在考虑实现选择的静态类型并使用cython进行编译,但出于某些原因我真的不想这样做。
谢谢你看看。
编辑:对于错误使用术语后期绑定感到抱歉。有时我的词汇会留下一些需要的东西。我的意思是“猴子补丁。” 编辑:@Corley Brigman,盖伊:非常感谢您解决问题,但是(我应该在原帖中说明)我在使用lxml之前完成了这个项目,这是一个很棒的图书馆这使得编码变得轻而易举,但由于新的要求(这需要作为一个名为Splunk的产品的插件实现),它将我与Splunk附带的python 2.7解释器联系起来,并消除了添加第三方库的可能性,但django除外答案 0 :(得分:1)
如果您需要父母,请使用lxml - 它在内部跟踪父母,并且在幕后仍然是C,所以它非常快。
然而......请注意跟踪父母存在权衡,因为给定节点只能有一个父节点。这通常不是问题,但是,如果您执行以下操作,您将在cElementTree与lxml中获得不同的结果:
p = Element('x')
q = Element('y')
r = SubElement(p, 'z')
q.append(r)
cElementTree:
dump(p)
<x><z /></x>
dump(q)
<y><z /></y>
LXML:
dump(p)
<x/>
dump(q)
<y>
<z/>
</y>
由于父母被跟踪,显然一个节点只能有一个父节点。如您所见,元素r
被复制到cElementTree中的两个树,并且在lxml中重新设置/移动。
可能只有少数用例需要考虑,但需要注意的事项。
答案 1 :(得分:0)
你可以使用xpath,例如:
import lxml.html
def get_path():
for e in doc.xpath("//b//*"):
print e
应该工作,虽然没有测试......