Skip to content

Commit

Permalink
added functionality to correctly parse xml lists
Browse files Browse the repository at this point in the history
  • Loading branch information
Charlemagne3 committed Apr 18, 2016
1 parent 0612b65 commit d085a68
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
2 changes: 1 addition & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Django>=1.6
djangorestframework>=2.4.3
pytest-django==2.6
pytest-django==2.9.1
pytest==2.5.2
pytest-cov==1.6
flake8==2.2.2
9 changes: 8 additions & 1 deletion rest_framework_xml/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ def parse(self, stream, media_type=None, parser_context=None):

return data

def _check_xml_list(self, element):
"""
Checks that an element has multiple tags and that they are all the same,
to validate that the element is a properly formatted list
"""
return len(element) > 1 and len(set([child.tag for child in element])) <= 1

def _xml_convert(self, element):
"""
convert the xml `element` into the corresponding python object
Expand All @@ -48,7 +55,7 @@ def _xml_convert(self, element):
return self._type_convert(element.text)
else:
# if the fist child tag is list-item means all children are list-item
if children[0].tag == "list-item":
if self._check_xml_list(element):
data = []
for child in children:
data.append(self._xml_convert(child))
Expand Down
56 changes: 53 additions & 3 deletions tests/test_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


from django.test import TestCase
from django.utils import unittest
from django.utils.six.moves import StringIO
from rest_framework_xml.parsers import XMLParser
from rest_framework_xml.compat import etree
Expand Down Expand Up @@ -52,15 +51,66 @@ def setUp(self):
}
]
}
self._invalid_list_input = StringIO(
'<?xml version="1.0" encoding="utf-8"?>'
'<root>'
'<list>'
'<list-item><sub_id>1</sub_id><sub_name>first</sub_name></list-item>'
'<list-item2><sub_id>2</sub_id><sub_name>second</sub_name></list-item2>'
'<list-item2><sub_id>3</sub_id><sub_name>third</sub_name></list-item2>'
'</list>'
'</root>'
)
self._invalid_list_output = {
"list": {
"list-item": {
"sub_id": 1,
"sub_name": "first"
},
"list-item2": {
"sub_id": 3,
"sub_name": "third"
}
}
}
self._valid_list_input = StringIO(
'<?xml version="1.0" encoding="utf-8"?>'
'<root>'
'<list>'
'<list-item><sub_id>1</sub_id><sub_name>first</sub_name></list-item>'
'<list-item><sub_id>2</sub_id><sub_name>second</sub_name></list-item>'
'</list>'
'</root>'
)
self._valid_list_output = {
"list": [
{
"sub_id": 1,
"sub_name": "first"
},
{
"sub_id": 2,
"sub_name": "second"
}
]
}

@unittest.skipUnless(etree, 'defusedxml not installed')
def test_parse(self):
parser = XMLParser()
data = parser.parse(self._input)
self.assertEqual(data, self._data)

@unittest.skipUnless(etree, 'defusedxml not installed')
def test_complex_data_parse(self):
parser = XMLParser()
data = parser.parse(self._complex_data_input)
self.assertEqual(data, self._complex_data)

def test_invalid_list_parse(self):
parser = XMLParser()
data = parser.parse(self._invalid_list_input)
self.assertEqual(data, self._invalid_list_output)

def test_valid_list_parse(self):
parser = XMLParser()
data = parser.parse(self._valid_list_input)
self.assertEqual(data, self._valid_list_output)
2 changes: 0 additions & 2 deletions tests/test_renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from decimal import Decimal

from django.test import TestCase
from django.utils import unittest
from django.utils.six.moves import StringIO
from rest_framework_xml.renderers import XMLRenderer
from rest_framework_xml.parsers import XMLParser
Expand Down Expand Up @@ -97,7 +96,6 @@ def test_render_list(self):
self.assertXMLContains(content, '<sub_data_list><list-item>')
self.assertXMLContains(content, '</list-item></sub_data_list>')

@unittest.skipUnless(etree, 'defusedxml not installed')
def test_render_and_parse_complex_data(self):
"""
Test XML rendering.
Expand Down

0 comments on commit d085a68

Please sign in to comment.