比较字符串并不总是有效的。对于判断两个节点是否相等,属性的顺序不应该有影响。但是,如果你进行字符串比较,顺序显然是很重要的。
我不确定这是一个问题还是一个特性,但我的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使用有序字典或类似的东西,而标准的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
另一个问题可能是在比较时什么被认为是不重要的。例如,某些片段可能包含额外的空格,我们不想关心它们。因此,编写一些序列化函数以确切地满足我们的需求总是更好的。