lxml XPath中不需要的命名空间声明

Mar*_*cin 6 python xpath lxml

我想选择特定element(subelement)的第一个子节点,但是这个子节点名称空间与父节点名称空间不同.而且,这个孩子可以是任何命名空间.

xml = '''<root xmlns="default_ns">
    <subelement>
        <!-- here we can have an element of any namespace  -->
        <some_prefix:a xmlns:some_prefix="some_namespace">
            <some_prefix:b/>
        </some_prefix:a>
    </subelement>
</root>'''
root = etree.fromstring(xml)
evaluator = etree.XPathEvaluator(root, namespaces={'def':'default_ns'})
child = evaluator.evaluate('//def:subelement/child::*')[0]
a_string = etree.tostring(child)
print a_string
Run Code Online (Sandbox Code Playgroud)

这给出了:

<some_prefix:a xmlns:some_prefix="some_namespace" xmlns="default_ns">
    <some_prefix:b/>
</some_prefix:a>
Run Code Online (Sandbox Code Playgroud)

但我想得到的是没有来自父母的名称空间声明的孩子xmlns="default_ns":

<some_prefix:a xmlns:some_prefix="some_namespace">
    <some_prefix:b/>
</some_prefix:a>
Run Code Online (Sandbox Code Playgroud)

Mar*_*cin 0

Dimitre完整地解释了命名空间为何被继承以及如何使用 XSLT 摆脱它。

我已使用副本中的深度复制来删除不需要的名称空间。

这是我使用Python的最终解决方案:

from lxml import etree
from copy import deepcopy

xml = '''<root xmlns="default_ns">
    <subelement>
        <!-- here we can have an element of any namespace  -->
        <some_prefix:a xmlns:some_prefix="some_namespace">
            <some_prefix:b/>
        </some_prefix:a>
    </subelement>
</root>'''
root = etree.fromstring(xml)
evaluator = etree.XPathEvaluator(root, namespaces={'def':'default_ns'})
child = evaluator.evaluate('//def:subelement/child::*')[0]
child = deepcopy(child)
a_string = etree.tostring(child)
print a_string
Run Code Online (Sandbox Code Playgroud)