0

我有以下有效的代码:

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,Guy:非常感谢您的回答确实解决了这个问题,但是(我应该在原始帖子中说明这一点)我在使用 lxml 之前完成了这个项目,这是一个很棒的库,可以进行编码轻而易举,但由于新的要求(这需要作为名为 Splunk 的产品的插件来实现),这将我与 Splunk 附带的 python 2.7 解释器联系在一起,并消除了添加第三方库的可能性,但 django 除外。

4

2 回答 2

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中重新设置/移动。

可能只有少数用例对此很重要,但要记住一些事情。

于 2013-11-22T14:52:57.390 回答
0

您可以只使用 xpath,例如:

import lxml.html

def get_path():
    for e in doc.xpath("//b//*"):
        print e

应该可以,虽然没有测试...

于 2013-11-22T14:58:01.990 回答