测试xml.etree.ElementTree的等效性

one*_*ter 24 python elementtree python-3.x

我对两个xml元素的等价感兴趣; 我发现测试元素的串串是有效的; 然而,这似乎是hacky.

有没有更好的方法来测试两个etree元素的等价性?

直接比较元素:

import xml.etree.ElementTree as etree
h1 = etree.Element('hat',{'color':'red'})
h2 = etree.Element('hat',{'color':'red'})

h1 == h2  # False
Run Code Online (Sandbox Code Playgroud)

将Elements作为字符串进行比较:

etree.tostring(h1) == etree.tostring(h2)  # True
Run Code Online (Sandbox Code Playgroud)

Ita*_*mar 26

这个比较功能对我有用:

def elements_equal(e1, e2):
    if e1.tag != e2.tag: return False
    if e1.text != e2.text: return False
    if e1.tail != e2.tail: return False
    if e1.attrib != e2.attrib: return False
    if len(e1) != len(e2): return False
    return all(elements_equal(c1, c2) for c1, c2 in zip(e1, e2))
Run Code Online (Sandbox Code Playgroud)

  • 这是一个解决方案.确保空格不会干扰,例如使用`etree.XMLParser(remove_blank_text = True)`.通过避免在`all()`中构建列表来改进.请注意``zip()`的工作原理,因为`len()`之前已经过测试. (3认同)
  • 整洁的!无论元素顺序如何,这似乎都有效,即使对于具有相同标记名的元素也是如此。 (2认同)
  • @Shillington如果元素顺序不同,您会希望比较返回“False”,不是吗?属性顺序则是另一回事。 (2认同)

len*_*enz 7

比较字符串并不总是有效.考虑两个节点等效,属性的顺序无关紧要.但是,如果你进行字符串比较,那么顺序显然很重要.

我不确定它是一个问题还是一个功能,但是我的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
Run Code Online (Sandbox Code Playgroud)

这可能与版本有关(我在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"/>>>>
Run Code Online (Sandbox Code Playgroud)

(是的,缺少新行.但这是一个小问题.)

>>> 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
Run Code Online (Sandbox Code Playgroud)

另一个问题可能是比较不重要的问题.例如,某些片段可能包含额外的空格,我们不想关心.这样,编写一些完全符合我们需要的序列化函数总是更好.

  • `.dump(...)`返回`None`,所以`ET.dump(h1)== ET.dump(h2)`实际上是将`None`与`None`比较。 (2认同)

fab*_*ioM -1

请勿镀金。你的那个是一个很好的比较。最后的 XML 是 TEXT。