Created
September 22, 2014 16:50
-
-
Save luiscoms/7c7f82015e27be2752b1 to your computer and use it in GitHub Desktop.
Convert python dictionary to xml
This file contains hidden or 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 -*- | |
| ''' Code based on | |
| Huseyin Yilmaz - Convert python dictionary to xml - https://gist.github.com/huseyinyilmaz/1448723 | |
| Ye Lui - dict2xml - https://gist.github.com/jaux/1478881 | |
| Simple Dictionary XML Serializer - https://gist.github.com/reimund/5435343 | |
| ''' | |
| from xml.dom import minidom | |
| from collections import Mapping | |
| import unittest | |
| def dict2element(root, structure, doc, cdatalist=[], attrlist=[]): | |
| """ | |
| 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' | |
| # 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(str(key)) | |
| if isinstance(value, Mapping): | |
| dict2element(el, value, doc, cdatalist, attrlist) | |
| elif isinstance(value, list): | |
| for item in value: | |
| item_el = doc.createElement(str(key)) | |
| dict2element(item_el, item, doc, cdatalist, attrlist) | |
| root.appendChild(item_el) | |
| continue | |
| else: | |
| value = str(value) if value is not None else '' | |
| if key in cdatalist: | |
| value = doc.createCDATASection(value) | |
| elif key in attrlist: | |
| root.setAttribute(key, value) | |
| continue | |
| else: | |
| value = doc.createTextNode(value) | |
| el.appendChild(value) | |
| root.appendChild(el) | |
| return root | |
| def dict2xml(structure, tostring=False, cdatalist=[], attrlist=[]): | |
| """ | |
| 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) | |
| """ | |
| # 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, str(root_element_name), None) | |
| dict2element(doc.documentElement, value, doc, cdatalist, attrlist) | |
| return doc.toxml() if tostring else doc | |
| # Unit tests | |
| class TestSequenceFunctions(unittest.TestCase): | |
| @unittest.expectedFailure | |
| def testEmptyList(self): | |
| d1 = [] | |
| res = dict2xml(d1) | |
| print res.toxml() | |
| @unittest.expectedFailure | |
| def testEmptyDict(self): | |
| d1 = {} | |
| res = dict2xml(d1) | |
| print res.toxml() | |
| def testMinimal(self): | |
| d1 = { | |
| 'root': {} | |
| } | |
| res = dict2xml(d1) | |
| self.assertEquals(res.toxml(), '<?xml version="1.0" ?><root/>') | |
| def testInnerElement(self): | |
| d1 = { | |
| 'root': { | |
| 'elementwithtextnode': 'text content', | |
| 'innerelements': { | |
| 'innerinnerelements': 'inner element content' | |
| } | |
| } | |
| } | |
| # self.failUnless(lines) | |
| res = dict2xml(d1) | |
| self.assertEquals(res.toxml(), '<?xml version="1.0" ?><root><innerelements><innerinnerelements>inner element content</innerinnerelements></innerelements><elementwithtextnode>text content</elementwithtextnode></root>') | |
| def testInnerElements(self): | |
| d1 = { | |
| 'root': { | |
| 'elementwithtextnode': 'text content', | |
| 'innerelements': [ | |
| { | |
| 'innerinnerelements': 'inner element content' | |
| }, | |
| { | |
| 'innerinnerelements': 'inner element content' | |
| } | |
| ] | |
| } | |
| } | |
| # self.failUnless(lines) | |
| res = dict2xml(d1) | |
| self.assertEquals(res.toxml(), '<?xml version="1.0" ?><root><innerelements><innerinnerelements>inner element content</innerinnerelements></innerelements><innerelements><innerinnerelements>inner element content</innerinnerelements></innerelements><elementwithtextnode>text content</elementwithtextnode></root>') | |
| def testCDATA(self): | |
| d1 = { | |
| 'root': { | |
| 'cdatatextnode': 'text content', | |
| } | |
| } | |
| res = dict2xml(d1, False, ['cdatatextnode']) | |
| self.assertEquals(res.toxml(), '<?xml version="1.0" ?><root><cdatatextnode><![CDATA[text content]]></cdatatextnode></root>') | |
| def testAttribute(self): | |
| d1 = { | |
| 'root': { | |
| 'elementwithattr': { | |
| 'attribute': 'xyz', | |
| } | |
| } | |
| } | |
| res = dict2xml(d1, False, [], ['attribute']) | |
| self.assertEquals(res.toxml(), '<?xml version="1.0" ?><root><elementwithattr attribute="xyz"/></root>') | |
| if __name__ == '__main__': | |
| unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment