Ada*_*ott 33 python xml elementtree
我有一个可以从XML字符串构建自己的对象,并将自己写入XML字符串.我想编写一个单元测试来测试通过XML的循环跳过,但是我在比较两个XML版本时遇到了麻烦.空白和属性顺序似乎是问题.有关如何做到这一点的任何建议?这是在Python中,我正在使用ElementTree(这并不重要,因为我只是在这个级别处理字符串中的XML).
Mik*_*bov 16
这是一个老问题,但接受的Kozyarchuk的答案对我来说不起作用,因为属性顺序,并且minidom解决方案也不起作用(不知道为什么,我没有调试它).
这就是我最终提出的:
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)
Run Code Online (Sandbox Code Playgroud)
这也产生了一个diff,在大型xml文件的情况下可能会有所帮助.
Koz*_*huk 14
首先规范化2 XML,然后你可以比较它们.我使用了以下使用lxml
obj1 = objectify.fromstring(expect)
expect = etree.tostring(obj1)
obj2 = objectify.fromstring(xml)
result = etree.tostring(obj2)
self.assertEquals(expect, result)
Run Code Online (Sandbox Code Playgroud)
如果问题实际上只是空格和属性顺序,并且您没有其他构造而不是文本和元素需要担心,则可以使用标准XML解析器解析字符串并手动比较节点.这是一个使用minidom的例子,但你可以简单地在etree中写相同:
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
Run Code Online (Sandbox Code Playgroud)
如果您需要更全面的等效比较,涵盖其他类型节点的可能性,包括CDATA,PI,实体引用,注释,文档类型,命名空间等,您可以使用DOM Level 3 Core方法isEqualNode.minidom和etree都没有,但是pxdom是一个支持它的实现:
def isEqualXML(a, b):
da, db= pxdom.parseString(a), pxdom.parseString(a)
return da.isEqualNode(db)
Run Code Online (Sandbox Code Playgroud)
(如果需要指定实体引用和CDATA部分是否与其替换的等效项匹配,则可能需要更改解析中的某些DOMConfiguration选项.)
稍微更迂回的方法是解析,然后重新序列化为规范形式并进行字符串比较.pxdom再次支持DOM Level 3 LS选项'canonical-form',您可以使用它来执行此操作; 使用stdlib的minidom实现的另一种方法是使用c14n.但是你必须为此安装PyXML扩展,所以你仍然无法在stdlib中完成它:
from xml.dom.ext import c14n
def isEqualXML(a, b):
da, bd= minidom.parseString(a), minidom.parseString(b)
a, b= c14n.Canonicalize(da), c14n.Canonicalize(db)
return a==b
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14088 次 |
| 最近记录: |