我正在使用 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>
Element to be
<a:value>
like the first one.
问题在于
copy.deepcopy()
在
lxml.etree
元素上无法完全保留命名空间信息。虽然它复制了元素和属性,但是命名空间的关联方式在复制过程中会丢失。
解决方案是使用
lxml.etree
自带的复制机制,它正确地处理命名空间:
import os
from lxml import etree
def load_tree_from_file(filename):
with open(filename, 'r') as f:
return etree.parse(f)
tree = load_tree_from_file('Input.xml')
port = tree.find('{hello}port')
v = port.find('{hello}v')
# 使用 etree.ElementTree.copy() 进行复制
v2 = etree.ElementTree.copy(v)
port.append(v2)
d = os.path.dirname(__file__)
tree.write(os.path.join(d, 'Output.xml'), pretty_print=True)
这段代码使用
etree.ElementTree.copy(v)
来创建
v
元素的副本。
etree.ElementTree.copy()
函数会正确地复制元素及其所有子元素,包括命名空间信息。这样,输出文件中的第二个
<v>
元素就会保留原始的命名空间前缀:
<haul>
<uuid>abc</uuid>
<port xmlns="hello" xmlns:a="hello">
<v>
<a:value>0</a:value>
<type>int</type>
</v>
<v>
<a:value>0</a:value>
<type>int</type>
</v>
</port>
</haul>
总结:
-
不要使用
copy.deepcopy()
复制lxml.etree
元素。 -
使用
etree.ElementTree.copy()
来确保正确复制命名空间信息。