假设我有2个这样的XML文件:
version1.xml:
<object>
<name>boat</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>0</xmin>
<ymin>434</ymin>
<xmax>152</xmax>
<ymax>504</ymax>
</bndbox>
</object>
version2.xml:
<object><name>boat</name><pose>Unspecified</pose><truncated>0</truncated><difficult>0</difficult><bndbox><xmin>0</xmin><ymin>434</ymin><xmax>152</xmax><ymax>504</ymax></bndbox></object>
它们之间的唯一区别是空格,它使第一个空格更易于阅读。我试图找到如何将第二种格式转换为第一种格式。
我知道我可以使用一些解决方法,例如从GitHub gist中使用此功能(在其他情况下也是如此):
from xml.dom import minidom
from xml.etree import ElementTree
def prettify(elem):
"""
Return a pretty-printed XML string for the Element.
"""
rough_string = ElementTree.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=' ')
但我不是要这样做(我的需求涉及部分格式化的XML,该XML不能与上述功能完美配合使用。)
如果我检查每个元素的文本差异,我将得到以下信息:
import xml.etree.ElementTree as ET
xml_path1 = 'path/to/version1.xml'
xml_path2 = 'path/to/version2.xml'
tree1 = ET.parse(xml_path1)
annot1 = tree1.getroot()
tree2 = ET.parse(xml_path2)
annot2 = tree2.getroot()
for elem1, elem2 in zip(annot1.iter(), annot2.iter()):
if repr(elem1.text) != repr(elem2.text):
print(elem1, repr(elem1.text), elem2, repr(elem2.text))
输出:
<Element 'object' at 0x7fb26fc2d9f8> '\n\t' <Element 'object' at 0x7fb1c4e4da48> None
<Element 'bndbox' at 0x7fb1c4e4d8b8> '\n\t\t' <Element 'bndbox' at 0x7fb1c4e4dbd8> None
如果我将指定的文本更改为相应的version1文本,则它的确会将格式更改为受影响的元素,但是那样。
ET.dump(annot2)
输出:
<object>
<name>boat</name><pose>Unspecified</pose><truncated>0</truncated><difficult>0</difficult><bndbox>
<xmin>0</xmin><ymin>434</ymin><xmax>152</xmax><ymax>504</ymax></bndbox></object>
当然具有所需的输出:
ET.dump(annot1)
输出:
<object>
<name>boat</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>0</xmin>
<ymin>434</ymin>
<xmax>152</xmax>
<ymax>504</ymax>
</bndbox>
</object>
那么,格式化处理了什么?我知道它实际上并不影响XML的内容(机器认为内容与我认为的相同),但是元素树保存此信息的地方使我难以理解。
xmin
的元素为什么只显示该值并隐藏格式文本,而实际上封装其他子元素的其他诸如bndbox
的元素却显示这些格式字符串?答案 0 :(得分:1)
缺少的空格位于Element.tail
(docs)中。
在生成输出时,ElementTree会打印开始元素,内容,结束元素,然后打印尾部。
这是格式化子树的技巧(将文档的其余部分保留下来):
"\n"
替换字符串中的"\n" + (" "*level)
,其中level
是子树的深度。或者,您可以通过将子树包装在level
包装元素中来创建新文档,漂亮地打印整个文档,然后再次找到子树。