使用ElementTree和Python覆盖XML文件时保留现有命名空间
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了使用ElementTree和Python覆盖XML文件时保留现有命名空间,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2889字,纯文字阅读大概需要5分钟。
内容图文
![使用ElementTree和Python覆盖XML文件时保留现有命名空间](/upload/InfoBanner/zyjiaocheng/707/e85fc94a38064c92b921f377874d9853.jpg)
我有一个以下格式的XML文件
<?xml version="1.0" encoding="utf-8"?>
<foo>
<bar>
<bat>1</bat>
</bar>
<a>
<b xmlns="urn:schemas-microsoft-com:asm.v1">
<c>1</c>
</b>
</a>
</foo>
我想将bat的值更改为’2’并将文件更改为:
<?xml version="1.0" encoding="utf-8"?>
<foo>
<bar>
<bat>2</bat>
</bar>
<a>
<b xmlns="urn:schemas-microsoft-com:asm.v1">
<c>1</c>
</b>
</a>
</foo>
我这样打开这个文件
tree = ET.parse(filePath)
root = tree.getroot()
然后我将bat的值更改为’2’并保存文件,如下所示:
tree.write(filePath, "utf-8", True, None, "xml")
bat的值成功更改为2,但XML文件现在看起来像这样.
<?xml version="1.0" encoding="utf-8"?>
<foo xmlns:ns0="urn:schemas-microsoft-com:asm.v1">
<bar>
<bat>2</bat>
</bar>
<a>
<ns0:b>
<ns0:c>1</ns0:c>
</ns0:b>
</a>
</foo>
为了解决具有名为ns0的命名空间的问题,我在解析文档之前执行以下操作
ET.register_namespace('', "urn:schemas-microsoft-com:asm.v1")
这摆脱了ns0名称空间,但xml文件现在看起来像这样
<?xml version="1.0" encoding="utf-8"?>
<foo xmlns="urn:schemas-microsoft-com:asm.v1">
<bar>
<bat>2</bat>
</bar>
<a>
<b>
<c>1</c>
</b>
</a>
</foo>
我该怎么做以获得我需要的输出?
解决方法:
据我所知,没有办法通过xml.etree.ElementTree方法来实现你的目标.通过挖掘xml.etree源代码和xml规范,我发现库的行为没有错,也没有道理.无论如何它不允许你正在寻找的输出.
要使用该库实现目标,您必须自定义渲染行为.为了最好地满足您的需求,我编写了以下渲染功能.
from xml.etree import ElementTree as ET
from re import findall, sub
def render(root, buffer='', namespaces=None, level=0, indent_size=2, encoding='utf-8'):
buffer += f'<?xml version="1.0" encoding="{encoding}" ?>\n' if not level else ''
root = root.getroot() if isinstance(root, ET.ElementTree) else root
_, namespaces = ET._namespaces(root) if not level else (None, namespaces)
for element in root.iter():
indent = ' ' * indent_size * level
tag = sub(r'({[^}]+}\s*)*', '', element.tag)
buffer += f'{indent}<{tag}'
for ns in findall(r'{[^}]+}', element.tag):
ns_key = ns[1:-1]
if ns_key not in namespaces: continue
buffer += ' xmlns' + (f':{namespaces[ns_key]}' if namespaces[ns_key] != '' else '') + f'="{ns_key}"'
del namespaces[ns_key]
for k, v in element.attrib.items():
buffer += f' {k}="{v}"'
buffer += '>' + element.text.strip() if element.text else '>'
children = list(element)
for child in children:
sep = '\n' if buffer[-1] != '\n' else ''
buffer += sep + render(child, level=level+1, indent_size=indent_size, namespaces=namespaces)
buffer += f'{indent}</{tag}>\n' if 0 != len(children) else f'</{tag}>\n'
return buffer
通过向上面的render()函数提供xml输入数据,如下所示:
data =\
'''<?xml version="1.0" encoding="utf-8"?>
<foo>
<bar>
<bat>1</bat>
</bar>
<a>
<b xmlns="urn:schemas-microsoft-com:asm.v1">
<c>1</c>
</b>
</a>
</foo>'''
root = ET.ElementTree(ET.fromstring(data))
ET.register_namespace('', "urn:schemas-microsoft-com:asm.v1")
print(render(root))
它打印出您正在寻找的输出:
<?xml version="1.0" encoding="utf-8" ?>
<foo>
<bar>
<bat>1</bat>
</bar>
<a>
<b xmlns="urn:schemas-microsoft-com:asm.v1">
<c>1</c>
</b>
</a>
</foo>
内容总结
以上是互联网集市为您收集整理的使用ElementTree和Python覆盖XML文件时保留现有命名空间全部内容,希望文章能够帮你解决使用ElementTree和Python覆盖XML文件时保留现有命名空间所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。