Last active
March 16, 2017 09:34
-
-
Save jcbsv/1a7f37e93e9f3d25470f27e15c365817 to your computer and use it in GitHub Desktop.
Supplement to Stackoverflow answer http://stackoverflow.com/questions/42774573/python-function-for-xml-list/42786367
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
import json | |
from xml.etree import ElementTree | |
tree = ElementTree.parse('raml20.xml') | |
ns = {'ns': 'raml20.xsd'} | |
nsP, nsList, nsItem = ('{%s}%s' % (ns['ns'], i) for i in ('p', 'list', 'item')) | |
def pkv(o): | |
"""Return dict with name:text of p elements""" | |
return {k.attrib['name']: k.text for k in o.iter(nsP)} | |
def parse(tree): | |
root = tree.getroot() | |
objs = {} | |
for mo in root.findall('./ns:cmData/ns:managedObject', ns): | |
obj = pkv(mo) | |
for i in mo.iter(nsList): | |
obj[i.attrib['name']] = [pkv(j) for j in i.iter(nsItem)] | |
objs[mo.attrib['distName']] = obj | |
return objs | |
def diff_dicts(d1, d2, ignore_keys=set()): | |
"""Return dict with differences between the dicts provided as arguments""" | |
k1 = set(d1.keys()) | |
k2 = set(d2.keys()) | |
diff = {} | |
diff.update( | |
{i: (d1[i], d2[i]) for i in (k1 & k2) - ignore_keys if d1[i] != d2[i]}) | |
diff.update({i: (d1.get(i), d2.get(i)) for i in (k1 ^ k2) - ignore_keys}) | |
return diff | |
def diff_lists(l1, l2): | |
"""Return dict with differences between lists of dicts provided as arguments""" | |
diff = {} | |
# note: assumes that lists are of same length | |
for i, (d1, d2) in enumerate(zip(l1, l2)): | |
d = diff_dicts(d1, d2) | |
if d: | |
diff[i] = d | |
return diff | |
def diff_objects(o1, o2): | |
"""Return dict with differences between two objects (dicts) provided as arguments""" | |
listkeys = set( | |
i for o in (o1, o2) for i in o if isinstance(o.get(i), list)) | |
diff = diff_dicts(o1, o2, listkeys) | |
for i in listkeys: | |
if i in o1 and i in o2: | |
diff.update({i: diff_lists(o1[i], o2[i])}) | |
else: | |
diff.update({i: (o1.get(i), o2.get(i))}) | |
return diff | |
def compare_objects(reference, objs): | |
diffs = [] | |
for k, o in objs.items(): | |
diff = diff_objects(reference, o) | |
if diff: | |
diffs.append((k, diff)) | |
return diffs | |
reference = ... # set your reference object here | |
res = compare_objects(reference, parse(tree)) | |
print(json.dumps(res, indent=2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment