我正在使用 lxml.etree 库将 XML 文件拼接在一起,并且命名空间在写入时被删除。
Input.xml
<?xml version="1.0" encoding="UTF-8"?>
<haul>
<uuid>abc</uuid>
<port xmlns="hello"
xmlns:a="hello">
<v>
<a:value>0</a:value>
<type>int</type>
</v>
</port>
</haul>
我尝试了这段代码:
test.py
tree = load_tree_from_file('Input.xml')
port = tree.find('{hello}port')
v = port.find('{hello}v')
v2=copy.deepcopy(v)
port.append(v2)
d = os.path.dirname(__file__)
tree.write(os.path.join(d, 'Output.xml'))
我得到了这个输出:
Output.xml
<haul>
<uuid>abc</uuid>
<port xmlns="hello" xmlns:a="hello">
<v>
<a:value>0</a:value>
<type>int</type>
</v>
<v>
<value>0</value>
<type>int</type>
</v>
</port>
</haul>
我期望并且需要
<value>
元素与第一个元素一样 <a:value>
。
命名空间不会被删除,因为特定节点的
a
命名空间为 hello
,这也与使用 xmlns="hello"
指定的默认命名空间相同。 这允许省略标签的 a:
前缀,因为 <a:value/>
和 <value/>
是相同的表示。如果 a
命名空间绑定到其他内容,执行类似的操作将显示您期望的输出类型:
>>> from lxml import etree
>>> ixml = b'''<?xml version="1.0" encoding="UTF-8"?>
... <haul>
... <uuid>abc</uuid>
... <port xmlns="hello"
... xmlns:a="goodbye">
... <v>
... <a:value>0</a:value>
... <type>int</type>
... </v>
... </port>
... </haul>'''
>>> tree = etree.fromstring(ixml)
>>> port = tree.find('{hello}port')
>>> v = port.find('{hello}v')
>>> v2 = copy.deepcopy(v)
>>> port.append(v2)
>>> print(etree.tostring(tree).decode())
<haul>
<uuid>abc</uuid>
<port xmlns="hello" xmlns:a="goodbye">
<v>
<a:value>0</a:value>
<type>int</type>
</v>
<v>
<a:value>0</a:value>
<type>int</type>
</v>
</port>
</haul>
虽然这个示例自然有两个独立的命名空间,所以它可能不能代表您想要做的事情。在任何情况下,提供的输出
lxml
对于这里的两种情况都是正确的,因为问题中的版本默认命名空间和 a
命名空间是相同的,因此可以安全地省略它,而这个答案中的上述示例有两个单独的命名空间,因此必须包含它们。 有关这些表示如何工作的更多示例可以在此答案中找到。