Skip to content
Snippets Groups Projects
Commit f5fff373 authored by Gavin M. Roy's avatar Gavin M. Roy
Browse files

Add XML parser and tests

parent 727a7246
No related branches found
No related tags found
No related merge requests found
import unittest
from tornado_aws import xml
class TestCase(unittest.TestCase):
def test_generic_xml(self):
expectation = {'test': {'foo': 'bar', 'baz': {'qux': 'corgie'}}}
value = """<?xml version="1.0" encoding="UTF-8"?>
<test><foo>bar</foo><baz><qux>corgie</qux></baz></test>"""
self.assertDictEqual(xml.loads(value), expectation)
def test_generic_xml_with_attributes(self):
expectation = {'test': {'foo': 'bar',
'baz': {'qux': 'corgie', '@val': '1'}}}
value = """<?xml version="1.0" encoding="UTF-8"?>
<test><foo>bar</foo><baz val="1"><qux>corgie</qux></baz></test>"""
self.assertDictEqual(xml.loads(value), expectation)
def test_generic_xml_with_text_and_children(self):
expectation = {'test': {'foo': 'bar',
'baz': {'qux': 'corgie',
'@val': '1',
'#text': 'gorge'}}}
value = """<?xml version="1.0" encoding="UTF-8"?>
<test><foo>bar</foo><baz val="1">gorge<qux>corgie</qux></baz></test>"""
self.assertDictEqual(xml.loads(value), expectation)
def test_invalid_xml(self):
with self.assertRaises(ValueError):
xml.loads('foo')
"""
XML Deserialization
===================
Parse XML return content and return it as a dict.
"""
from collections import defaultdict
from xml.etree import ElementTree as etree
def loads(content):
"""Return the XML document returned from AWS as a dict
:param str content: Response content from AWS
:rtype: dict
:raises: ValueError
"""
try:
return _xml_to_dict(etree.XML(content))
except etree.ParseError as error:
raise ValueError(str(error))
def _xml_to_dict(t):
"""Process child nodes, initially taken from
https://stackoverflow.com/a/10076823/13203
:param xml.etree.ElementTree.Element t: The XML node to process
"""
d = {t.tag: {} if t.attrib else None}
children = list(t)
if children:
dd = defaultdict(list)
for dc in map(_xml_to_dict, children):
for k, v in dc.items():
dd[k].append(v)
d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.items()}}
if t.attrib:
d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())
if t.text:
text = t.text.strip()
if (children or t.attrib) and text:
d[t.tag]['#text'] = text
else:
d[t.tag] = t.text.strip()
return dict(d)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment