Skip to content

Commit

Permalink
Added Cobra dict-to-etree conversion and tests
Browse files Browse the repository at this point in the history
This was a missing part of the Cobra implementation.
Now we can convert a dict back to etree (XML).
  • Loading branch information
dagwieers authored and sanand0 committed Mar 11, 2018
1 parent c0a8915 commit 9cfaeb2
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,4 @@ Roadmap

* Test cases for Unicode
* Support for namespaces and namespace prefixes
* Support XML comments
45 changes: 43 additions & 2 deletions tests/test_xmljson.py
Original file line number Diff line number Diff line change
Expand Up @@ -602,10 +602,51 @@ def test_data(self):


class TestCobra(TestXmlJson):
@unittest.skip('To be written')

def test_etree(self, converter=None):
'Cobra conversion from data to etree'
pass
eq = self.check_etree(xmljson.cobra)

eq({'animal': {'attributes': {}}}, '<animal/>')
eq({'animal': {'attributes': {}, 'children': ['Deka']}}, '<animal>Deka</animal>')
eq({'animal': {'attributes': {}, 'children': [1]}}, '<animal>1</animal>')
eq({'animal': {'attributes': {'name': 1}}}, '<animal name="1"/>')
eq({'animal': 'is my cat'},
'<animal>is my cat</animal>')
eq({'animal': {'attributes': {}, 'children': [{'dog': 'Charlie'}, {'cat': 'Deka'}]}},
'<animal><dog>Charlie</dog><cat>Deka</cat></animal>')
eq({'animal': {'attributes': {}, 'children': [{'dog': 'Charlie'}, {'dog': 'Mad Max'}]}},
'<animal><dog>Charlie</dog><dog>Mad Max</dog></animal>')
#eq({'animal': {'attributes': {}, 'children': [{'dog': {'attributes': {}, 'children': ['Charlie', 'Mad Max']}}]}},
# '<animal><dog>Charlie</dog><dog>Mad Max</dog></animal>')
eq({'animal': {'attributes': {'dog': 'Charlie', 'cat': 'Deka'}}},
'<animal dog="Charlie" cat="Deka"/>')
eq({'animal': {'attributes': {}, 'children': [' in my house ', {'dog': 'Charlie'}]}},
'<animal> in my house <dog>Charlie</dog></animal>')
eq({'animal': {'attributes': {'dog': 'Charlie'}, 'children': [' in my house ']}},
'<animal dog="Charlie"> in my house </animal>')

# Test edge cases
eq('x', '<x/>') # Strings become elements
eq({}) # Empty objects become empty nodes
eq(Dict([ # Multiple keys become multiple nodes
('x', 'a'),
('y', 'b')
]), '<x>a</x>', '<y>b</y>')
with self.assertRaises(Exception):
eq({'x': {'@x': 1}}, '<x x="1"/>')

# Nested elements
eq({'alice': {'attributes': {}, 'children': [
{'bob': {'attributes': {}, 'children': [{'charlie': {'attributes': {}}}]}},
{'david': {'attributes': {}, 'children': [{'edgar': {'attributes': {}}}]}}]}},
'<alice><bob><charlie/></bob><david><edgar/></david></alice>')

# Multiple elements at the same level become array elements.
eq({'alice': {'attributes': {}, 'children': [
{'bob': {'attributes': {}, 'children': [{'charlie': {'attributes': {}}}]}},
{'bob': {'attributes': {}, 'children': [{'david': {'attributes': {}}}]}}]}},
'<alice><bob><charlie/></bob><bob><david/></bob></alice>')

@unittest.skip('To be written')
def test_html(self):
Expand Down
29 changes: 29 additions & 0 deletions xmljson/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,35 @@ class Cobra(XMLData):
def __init__(self, **kwargs):
super(Cobra, self).__init__(simple_text=True, text_content=True,
xml_fromstring=False, **kwargs)
def etree(self, data, root=None):
'''Convert data structure into a list of etree.Element'''
result = self.list() if root is None else root
if isinstance(data, (self.dict, dict)):
for key, value in data.items():
if isinstance(value, (self.dict, dict)):
elem = self.element(key)
result.append(elem)

if 'attributes' in value:
for k, v in value['attributes'].items():
elem.set(k, self._tostring(v))
else:
raise ValueError("Cobra convention requires an attributes key for each element")

if 'children' in value:
for v in value['children']:
self.etree(v, root=elem)
else:
elem = self.element(key)
elem.text = self._tostring(value)
result.append(elem)
else:
if root is not None:
root.text = self._tostring(data)
else:
result.append(self.element(self._tostring(data)))

return result

def data(self, root):
'''Convert etree.Element into a dictionary'''
Expand Down

0 comments on commit 9cfaeb2

Please sign in to comment.