Last active
November 26, 2020 12:19
-
-
Save huseyinyilmaz/1448723 to your computer and use it in GitHub Desktop.
Convert python dictionary to xml
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
# -*- coding: utf-8 -*- | |
import unittest | |
import xmlutils | |
from xml.dom import minidom | |
from collections import Mapping | |
def dict2element(root, structure, doc): | |
""" | |
Gets a dictionary like structure and converts its | |
content into xml elements. After that appends | |
resulted elements to root element. If root element | |
is a string object creates a new elements with the | |
given string and use that element as root. | |
This function returns a xml element object. | |
""" | |
assert isinstance(structure, Mapping), \ | |
'Structure must be a mapping object such as dict' | |
# if root is a string make it a element | |
if isinstance(root, str): | |
root = doc.createElement(root) | |
for key, value in structure.iteritems(): | |
el = doc.createElement("" if key is None else unicode(key)) | |
if isinstance(value, Mapping): | |
dict2element(el, value, doc) | |
else: | |
el.appendChild(doc.createTextNode("" if value is None | |
else unicode(value))) | |
root.appendChild(el) | |
return root | |
def dict2xml(structure, tostring=False): | |
""" | |
Gets a dict like object as a structure and returns a corresponding minidom | |
document object. | |
If str is needed instead of minidom, tostring parameter can be used | |
Restrictions: | |
Structure must only have one root. | |
Structure must consist of str or dict objects (other types will | |
converted into string) | |
Sample structure object would be | |
{'root':{'elementwithtextnode':'text content', | |
'innerelements':{'innerinnerelements':'inner element content'}}} | |
result for this structure would be | |
'<?xml version="1.0" ?> | |
<root> | |
<innerelements> | |
<innerinnerelements>inner element content</innerinnerelements> | |
</innerelements> | |
<elementwithtextnode>text content</elementwithtextnode> | |
</root>' | |
""" | |
# This is main function call. which will return a document | |
assert len(structure) == 1, 'Structure must have only one root element' | |
assert isinstance(structure, Mapping), \ | |
'Structure must be a mapping object such as dict' | |
root_element_name, value = next(structure.iteritems()) | |
impl = minidom.getDOMImplementation() | |
doc = impl.createDocument(None, unicode(root_element_name), None) | |
dict2element(doc.documentElement, value, doc) | |
return doc.toxml() if tostring else doc | |
############# | |
# unittests # | |
############# | |
class TestValidXML(unittest.TestCase): | |
dict_value = {'root': | |
{'elementwithtextnode': 'text content', | |
'innerelements': {'innerinnerelements': 'inner content'}}} | |
str_value = ('<?xml version="1.0" ?>' | |
'<root>' | |
'<innerelements>' | |
'<innerinnerelements>inner content</innerinnerelements>' | |
'</innerelements>' | |
'<elementwithtextnode>text content</elementwithtextnode>' | |
'</root>') | |
unicode_dict_value = {'root': {u'kâğıt': u'ığdır'}} | |
unicode_value = u'<?xml version="1.0" ?><root><kâğıt>ığdır</kâğıt></root>' | |
def test_valid(self): | |
xml_value = xmlutils.dict2xml(self.dict_value) | |
self.assertEqual(xml_value.toxml(), self.str_value) | |
def test_unicode(self): | |
xml_value = xmlutils.dict2xml(self.unicode_dict_value) | |
self.assertEqual(xml_value.toxml(), self.unicode_value) | |
if __name__ == '__main__': | |
unittest.main() |
How do I run the above code?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@nooperpudd Sorry about the late response.
You are right. Code was not supporting unicode. I have change it to support unicode. But instead of encoding it myself I am letting xml library to handle encoding on its own. This version should not have any problem with unicode values.