在Python中使用ElementTree更改命名空间前缀

18 投票
2 回答
10594 浏览
提问于 2025-04-15 13:28

默认情况下,当你调用 ElementTree.parse(someXMLfile) 时,Python 的 ElementTree 库会在每个解析的节点前面加上它的命名空间 URI,使用的是 Clark 的表示法:

    {http://example.org/namespace/spec}mynode

这让后面在代码中通过名字访问特定节点变得非常麻烦。

我看过关于 ElementTree 和命名空间的文档,似乎 iterparse() 函数应该可以让我改变解析器加命名空间前缀的方式,但我就是无法让它改变前缀。看起来这可能是在 ns-start 事件触发之前就发生在后台了,像这个例子一样:

for event, elem in iterparse(source):
    if event == "start-ns":
        namespaces.append(elem)
    elif event == "end-ns":
        namespaces.pop()
    else:
        ...

我该如何改变前缀的行为,并且在函数结束时应该返回什么合适的东西呢?

2 个回答

2

xml.etree.ElementTree这个库似乎没有fixtag这个功能,至少在它的说明文档里没有提到。不过我查看了一些关于fixtag的源代码,你可以这样做:

import xml.etree.ElementTree as ET

for event, elem in ET.iterparse(inFile, events=("start", "end")):
    namespace, looktag = string.split(elem.tag[1:], "}", 1)

你有一个叫looktag的字符串,它是用来查找的。命名空间则保存在namespace里。

6

其实你不一定要用 iterparse。你可以用下面这个脚本:

from cStringIO import StringIO
import xml.etree.ElementTree as ET

NS_MAP = {
    'http://www.red-dove.com/ns/abc' : 'rdc',
    'http://www.adobe.com/2006/mxml' : 'mx',
    'http://www.red-dove.com/ns/def' : 'oth',
}

DATA = '''<?xml version="1.0" encoding="utf-8"?>
<rdc:container xmlns:mx="http://www.adobe.com/2006/mxml"
                 xmlns:rdc="http://www.red-dove.com/ns/abc"
                 xmlns:oth="http://www.red-dove.com/ns/def">
  <mx:Style>
    <oth:style1/>
  </mx:Style>
  <mx:Style>
    <oth:style2/>
  </mx:Style>
  <mx:Style>
    <oth:style3/>
  </mx:Style>
</rdc:container>'''

tree = ET.parse(StringIO(DATA))
some_node = tree.getroot().getchildren()[1]
print ET.fixtag(some_node.tag, NS_MAP)
some_node = some_node.getchildren()[0]
print ET.fixtag(some_node.tag, NS_MAP)

这个脚本会生成

('mx:Style', None)
('oth:style2', None)

这段代码展示了你如何获取解析树中每个节点的完整标签名称。你可以根据自己的需求来调整这个代码。

撰写回答