-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement XML deep equal function (#3)
* Implement XML deep equal function * More tests * More tests
- Loading branch information
Showing
2 changed files
with
118 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import unittest | ||
import xml.etree.ElementTree as ET | ||
|
||
from tind_commons.xmlutils import deep_equal | ||
|
||
class DeepEqualTests(unittest.TestCase): | ||
def test_obviously_equal_documents(self): | ||
doc = "<a>1<b>2</b>d</a>" | ||
|
||
a_element = ET.fromstring(doc) | ||
b_element = ET.fromstring(doc) | ||
|
||
self.assertTrue(deep_equal(a_element, b_element)) | ||
|
||
def test_different_contents(self): | ||
a_doc = "<a>1<b>2</b></a>" | ||
b_doc = "<a>2<b>2</b></a>" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertFalse(deep_equal(a_element, b_element)) | ||
|
||
def test_different_tails(self): | ||
a_doc = "<a>1<b>2</b></a>" | ||
b_doc = "<a>1<b>2</b> </a>" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertFalse(deep_equal(a_element, b_element)) | ||
|
||
def test_attribute_order_is_insignificant(self): | ||
a_doc = """<a b="c" d="e"></a>""" | ||
b_doc = """<a d="e" b="c"></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertTrue(deep_equal(a_element, b_element)) | ||
|
||
def test_all_attributes(self): | ||
a_doc = """<a b="c" d="e"></a>""" | ||
b_doc = """<a b="c"></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertFalse(deep_equal(a_element, b_element)) | ||
|
||
def test_attribute_contents(self): | ||
a_doc = """<a b="c"></a>""" | ||
b_doc = """<a b="d"></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertFalse(deep_equal(a_element, b_element)) | ||
|
||
def test_namespace_aware(self): | ||
a_doc = """<a xmlns="foo"></a>""" | ||
b_doc = """<a xmlns="bar"></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertFalse(deep_equal(a_element, b_element)) | ||
|
||
def test_namespace_prefix_aware(self): | ||
a_doc = """<x:a xmlns:x="foo"></x:a>""" | ||
b_doc = """<a xmlns="foo"></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertTrue(deep_equal(a_element, b_element)) | ||
|
||
def test_comments_are_insignificant(self): | ||
a_doc = """<a><!-- This is a comment --></a>""" | ||
b_doc = """<a></a>""" | ||
|
||
a_element = ET.fromstring(a_doc) | ||
b_element = ET.fromstring(b_doc) | ||
|
||
self.assertTrue(deep_equal(a_element, b_element)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
def deep_equal(a_element, b_element): | ||
"""Computes whether two different elements are deep equal. | ||
Two elements are considered deep equal if: | ||
1. Their tag names are equal | ||
2. Their attributes are equal | ||
3. Their text contents (including the tail contents) are equal | ||
3. Their children are pairwise deep equal | ||
""" | ||
if a_element.tag != b_element.tag: | ||
return False | ||
|
||
if len(a_element.items()) != len(b_element.items()): | ||
return False | ||
|
||
for key in a_element.keys(): | ||
if a_element.get(key) != b_element.get(key): | ||
return False | ||
|
||
if a_element.tail != b_element.tail: | ||
return False | ||
|
||
if a_element.text != b_element.text: | ||
return False | ||
|
||
if len(a_element) != len(b_element): | ||
return False | ||
|
||
for pair in zip(a_element, b_element): | ||
if not deep_equal(*pair): | ||
return False | ||
|
||
return True |