python - 如何更改具有命名前缀的 XML 元素的属性

标签 python xml-parsing namespaces elementtree

我在尝试编辑包含带有名称前缀的单个 XML 元素的字符串中的 XML 属性时遇到了真正的麻烦。

我正在尝试使用如下代码:

import xml.etree.ElementTree as ET

def replace_xml_label(xml):
    element = ET.fromstring(xml)
    element.set('label', 'new_test_label')
    return ET.tostring(element).decode('ascii')

xml_1 = '<abc label="test label">test_value</abc>'
xml_2 = '<abc:option label="test label">test_value</abc:option>'

对于xml_1,我得到了预期的输出:

print(replace_xml_label(xml_1))
<abc label="new_test_label">test_value</abc>

但是,我需要使用的 XML 元素的样式具有类似于 xml_2 的名称前缀,这会引发 ParseError:

print(replace_xml_label(xml_2))
Traceback (most recent call last):
 ... in XML parser.feed(text)
xml.etree.ElementTree.ParseError: unbound prefix: line 1, column 0

我的预期输出是:

<abc:option label="new_test_label">test_value</abc:option>

我怀疑该错误与缺少已定义的命名空间有关,但无法成功定义命名空间(例如使用ET.register_namespace('abc', 'my-ns')

尝试就地修改字符串来定义命名空间:

# ...doesn't raise an exception, but the output isn't in the format I need
xml_3 = xml_2.replace('<abc:option', '<abc:option xmlns:abc="my-ns"')
print(replace_xml_label(xml_3))  
<ns0:option xmlns:ns0="myns" label="new_test_label">test_value</ns0:option>

# replacing the output afterwards works, but by this point I may as well have used a regular expression!
print(replace_xml_label(xml_3).replace('ns0', 'abc').replace(' xmlns:abc="my-ns"',''))
<abc:option label="new_test_label">test_value</abc:option>

我是否做错了什么,遗漏了一些明显的东西,或者只是使用了错误的工具?

我更愿意使用标准 Python 3.4+ 库中提供的内容。

最佳答案

当然,问题是由于未声明的前缀造成的。 XML 要求正确声明使用中的所有 namespace 前缀,否则该文档不符合 XML,因此通常无法使用 XML 解析器库进行解析。因此,最终的解决方案是修复当前生成类 XML 文档的一侧,以生成格式良好的 XML。

在解析端解决此问题的一种可能的解决方法是,使用包含未声明前缀声明的父元素包装字符串,例如:

xml_2 = '<abc:option label="test label">test_value</abc:option>'

parent = '<foo xmlns:abc="bar">{}</foo>'
wellformed_xml = parent.format(xml_2)

result = replace_xml_label(wellformed_xml)
print(result)

关于python - 如何更改具有命名前缀的 XML 元素的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34358614/

相关文章:

c++ - C++命名空间的困扰

python - 在 python 中使用正则表达式时什么是单词边界

python - 可以从 pySpark 调用基于 JVM 的算法/函数吗?

c++ - 在命名空间中转发声明类

powershell - 如何使用Powershell从xml获取属性值?

java - 如何防止 XML 注入(inject),如 XML 炸弹和 XXE 攻击

ruby - 使用 let() 辅助函数时 Rspec 中的命名空间问题

python - 如何允许用户将单个列表项输入到列表列表中?

python - 无法在 OS X Lion 中构建 Cython/distutils。

powershell - 使用 Powershell 解析 XML 以在被子节点屏蔽时获取 .Name 属性的值