def isEqualXML(a, b):
da, db= minidom.parseString(a), minidom.parseString(b)
return isEqualElement(da.documentElement, db.documentElement)
def isEqualElement(a, b):
if a.tagName!=b.tagName:
return False
if sorted(a.attributes.items())!=sorted(b.attributes.items()):
return False
if len(a.childNodes)!=len(b.childNodes):
return False
for ac, bc in zip(a.childNodes, b.childNodes):
if ac.nodeType!=bc.nodeType:
return False
if ac.nodeType==ac.TEXT_NODE and ac.data!=bc.data:
return False
if ac.nodeType==ac.ELEMENT_NODE and not isEqualElement(ac, bc):
return False
return True
from doctest import Example
from lxml.doctestcompare import LXMLOutputChecker
class XmlTest(TestCase):
def assertXmlEqual(self, got, want):
checker = LXMLOutputChecker()
if not checker.check_output(want, got, 0):
message = checker.output_difference(Example("", want), got, 0)
raise AssertionError(message)
如果问题实际上只是空白和属性顺序,并且除了文本和元素之外没有其他构造要担心,那么可以使用标准XML解析器解析字符串并手动比较节点。下面是一个使用minidom的示例,但是您可以在etree中简单地编写相同的代码:
如果需要更彻底的等价性比较,包括其他类型节点(包括CDATA、PIs、实体引用、注释、doctype、名称空间等)的可能性,可以使用DOM级别3的核心方法isEqualNode。minidom和etree都没有,但pxdom是一个支持它的实现:
(如果需要指定实体引用和CDATA节是否与其替换的等价项匹配,则可能需要更改解析中的某些DOMConfiguration选项。)
一种更为迂回的方法是解析,然后重新序列化为规范形式并进行字符串比较。同样,pxdom支持DOM级别3 LS选项“canonical form”,您可以使用该选项;使用stdlib的minidom实现的另一种方法是使用c14n
首先规范化2个XML,然后可以比较它们。我使用了lxml
这是一个老问题,但是接受的Kozyarchuk's answer由于属性顺序而对我不起作用,minidom solution也不起作用(不知道为什么,我还没有调试它)。
这就是我最后想到的:
这也会产生一个diff,在处理大型xml文件时会很有帮助。
相关问题 更多 >
编程相关推荐