比较字符串并不总是有效。考虑两个节点等效时,属性的顺序应该无关紧要。但是,如果您进行字符串比较,则顺序显然很重要。
我不确定这是问题还是功能,但我的 lxml.etree 版本在从文件或字符串中解析属性时会保留属性的顺序:
>>> from lxml import etree
>>> h1 = etree.XML('<hat color="blue" price="39.90"/>')
>>> h2 = etree.XML('<hat price="39.90" color="blue"/>')
>>> etree.tostring(h1) == etree.tostring(h2)
False
这可能与版本有关(我在 Ubuntu 上使用 Python 2.7.3 和 lxml.etree 2.3.2);我记得大约一年前,当我想(出于可读性原因)时,我找不到控制属性顺序的方法。
由于我需要比较由不同序列化程序生成的 XML 文件,我认为除了递归比较每个节点的标记、文本、属性和子节点之外别无他法。当然还有尾巴,如果那里有什么有趣的东西的话。
lxml和xml.etree.ElementTree的比较
事实是它可能依赖于实现。显然,lxml 使用有序 dict 或类似的东西,标准 xml.etree.ElementTree 不保留属性的顺序:
Python 2.7.1 (r271:86832, Nov 27 2010, 17:19:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from lxml import etree
>>> h1 = etree.XML('<hat color="blue" price="39.90"/>')
>>> h2 = etree.XML('<hat price="39.90" color="blue"/>')
>>> etree.tostring(h1) == etree.tostring(h2)
False
>>> etree.tostring(h1)
'<hat color="blue" price="39.90"/>'
>>> etree.tostring(h2)
'<hat price="39.90" color="blue"/>'
>>> etree.dump(h1)
<hat color="blue" price="39.90"/>>>> etree.dump(h2)
<hat price="39.90" color="blue"/>>>>
(是的,缺少换行符。但这是一个小问题。)
>>> import xml.etree.ElementTree as ET
>>> h1 = ET.XML('<hat color="blue" price="39.90"/>')
>>> h1
<Element 'hat' at 0x2858978>
>>> h2 = ET.XML('<hat price="39.90" color="blue"/>')
>>> ET.dump(h1)
<hat color="blue" price="39.90" />
>>> ET.dump(h2)
<hat color="blue" price="39.90" />
>>> ET.tostring(h1) == ET.tostring(h2)
True
>>> ET.dump(h1) == ET.dump(h2)
<hat color="blue" price="39.90" />
<hat color="blue" price="39.90" />
True
另一个问题可能是比较时什么被认为不重要。例如,一些片段可能包含额外的空格,我们不想关心。这样,编写一些完全符合我们需要的序列化函数总是更好。