如何用Python修改XML属性命名空间?lxml冗余命名空间去除
解决lxml ElementMaker生成XML的冗余命名空间声明问题
问题场景
使用Python的lxml库通过ElementMaker生成XML元素时,根元素被自动添加了冗余的命名空间声明。原实现代码如下:
from lxml import etree as et from lxml.builder import ElementMaker WSS_SCHEMA = "http://schemas.xmlsoap.org/ws/2002/12/secext" ACTOR_SCHEMA = "http://xpto" VERSION_SCHEMA = "2" NSMAP = { 'wss': WSS_SCHEMA, 'S': ACTOR_SCHEMA, 'at': VERSION_SCHEMA, } WSS = ElementMaker(namespace=WSS_SCHEMA, nsmap=NSMAP) security = WSS.Security() security.set("{%s}actor" % ACTOR_SCHEMA, ACTOR_SCHEMA) security.set("{%s}Version" % VERSION_SCHEMA, VERSION_SCHEMA) print(et.tostring(security, encoding="unicode"))
当前输出(含冗余声明)
<wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext" xmlns:S="http://xpto" xmlns:at="2" S:actor="http://xpto" at:Version="2"/>
期望输出(仅保留必要声明)
<wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext" S:actor="http://xpto" at:Version="2"/>
解决方案
冗余声明的根源是初始化ElementMaker时传入了包含所有命名空间的nsmap参数,这会强制在根元素上声明所有映射的命名空间。只需调整命名空间的处理方式:
修改后的代码:
from lxml import etree as et from lxml.builder import ElementMaker WSS_SCHEMA = "http://schemas.xmlsoap.org/ws/2002/12/secext" ACTOR_SCHEMA = "http://xpto" VERSION_SCHEMA = "2" # 仅保留当前元素所属的命名空间 NSMAP = {'wss': WSS_SCHEMA} WSS = ElementMaker(namespace=WSS_SCHEMA, nsmap=NSMAP) security = WSS.Security() # 提前注册属性需要用到的命名空间前缀与URI的映射 et.register_namespace('S', ACTOR_SCHEMA) et.register_namespace('at', VERSION_SCHEMA) # 直接使用前缀+属性名的格式设置属性 security.set("S:actor", ACTOR_SCHEMA) security.set("at:Version", VERSION_SCHEMA) print(et.tostring(security, encoding="unicode"))
关键调整说明
- 缩小ElementMaker的nsmap范围:只包含根元素自身的
wss命名空间,避免自动生成其他命名空间的声明。 - 注册命名空间前缀:通过
et.register_namespace()将S、at前缀与对应的URI绑定,lxml序列化时会自动识别这些前缀对应的命名空间,无需额外在元素上声明。 - 直接使用带前缀的属性名:不再通过
{%s}属性名的格式拼接,直接用"S:actor"这种写法,结合已注册的前缀映射,就能生成正确的带命名空间前缀的属性,同时不会产生冗余声明。
内容的提问来源于stack exchange,提问作者arleite
相关产品推荐
相关产品推荐

