Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple dictionary to xml serializer.
"""
Simple xml serializer.
@author Reimund Trost 2013
Example:
mydict = {
'name': 'The Andersson\'s',
'size': 4,
'children': {
'total-age': 62,
'child': [
{ 'name': 'Tom', 'sex': 'male', },
{
'name': 'Betty',
'sex': 'female',
'grandchildren': {
'grandchild': [
{ 'name': 'herbert', 'sex': 'male', },
{ 'name': 'lisa', 'sex': 'female', }
]
},
}
]
},
}
print(dict2xml(mydict, 'family'))
Output:
<family name="The Andersson's" size="4">
<children total-age="62">
<child name="Tom" sex="male"/>
<child name="Betty" sex="female">
<grandchildren>
<grandchild name="herbert" sex="male"/>
<grandchild name="lisa" sex="female"/>
</grandchildren>
</child>
</children>
</family>
"""
def dict2xml(d, root_node=None):
wrap = False if None == root_node or isinstance(d, list) else True
root = 'objects' if None == root_node else root_node
root_singular = root[:-1] if 's' == root[-1] and None == root_node else root
xml = ''
children = []
if isinstance(d, dict):
for key, value in dict.items(d):
if isinstance(value, dict):
children.append(dict2xml(value, key))
elif isinstance(value, list):
children.append(dict2xml(value, key))
else:
xml = xml + ' ' + key + '="' + str(value) + '"'
else:
for value in d:
children.append(dict2xml(value, root_singular))
end_tag = '>' if 0 < len(children) else '/>'
if wrap or isinstance(d, dict):
xml = '<' + root + xml + end_tag
if 0 < len(children):
for child in children:
xml = xml + child
if wrap or isinstance(d, dict):
xml = xml + '</' + root + '>'
return xml
@native-api

This comment has been minimized.

Copy link

@native-api native-api commented Jul 12, 2013

unsafe against XML special charaters in input

@jarrar

This comment has been minimized.

Copy link

@jarrar jarrar commented May 11, 2014

But excellent for simple object serialization needs

@zappfinger

This comment has been minimized.

Copy link

@zappfinger zappfinger commented Sep 1, 2014

Looks interesting. And the other way around? From XML to dict?

@Gerst20051

This comment has been minimized.

Copy link

@Gerst20051 Gerst20051 commented Feb 17, 2016

i was able to do str(value.encode('ascii', 'ignore'))

@jharms

This comment has been minimized.

Copy link

@jharms jharms commented Jun 1, 2016

also available using pip install dict2xml.

@jonahfang

This comment has been minimized.

Copy link

@jonahfang jonahfang commented Sep 14, 2016

change line 59 to avalid unicode error:

xml = '%s %s="%s"' % (xml,key,value)
@abeaclark

This comment has been minimized.

Copy link

@abeaclark abeaclark commented Jan 19, 2018

Thanks for the great code! Would you mind adding a license? I want to make sure everything is in order if I use it.

@thomaswpp

This comment has been minimized.

Copy link

@thomaswpp thomaswpp commented Jul 31, 2018

Thank You Very Much.. I made a small modification to attributes to be accepted starting with @.
Example: dict2xml(d, "NFe")

{
    'infNFe': 
            {'@versao': '3.10', '@Id': '35150469012656000120550030000783031122216144', 
         'ide': {
                      'mod', '55', 'serie', '3', 'nNF', '78303', 'dhEmi', '20/04/2015T15:36:3603:00', 
                       'dhSaiEnt', '21/04/2015T15:36:3603:00', 'idDest', '1', 'indFinal', '0', 'indPres', '9', 
                        'procEmi', '0', 'verProc', '61000', 'tpEmis', '1', 'finNFe', '1', 'natOp', 'SAIDA', 'tpNF', '1', 'indPag', '0'
                    }
            }
} 
<NFe>
<infNFe versao="3.10" Id="35150469012656000120550030000783031122216144">
<ide>
<mod>55</mod>
<tpNF>1</tpNF>
<idDest>1</idDest>
<indFinal>0</indFinal>
<dhEmi>20/04/2015T15:36:3603:00</dhEmi>
<natOp>SAIDA</natOp>
<indPres>9</indPres>
<tpEmis>1</tpEmis>
<nNF>78303</nNF>
<serie>3</serie>
<procEmi>0</procEmi>
<indPag>0</indPag>
<verProc>61000</verProc>
<dhSaiEnt>21/04/2015T15:36:3603:00</dhSaiEnt>
<finNFe>1</finNFe>
</ide>
</infNFe>
</NFe>
def dict2xml(d, root_node=None):
    wrap          =  False if None == root_node or isinstance(d, list) else True
    root          = 'objects' if None == root_node else root_node
    root_singular = root[:-1] if 's' == root[-1] and None == root_node else root
    xml           = ''
    attr          = ''
    children      = []

    if isinstance(d, dict):
        # print(d)
        for key, value in dict.items(d):
            if isinstance(value, dict):
                children.append(dict2xml(value, key))
            elif isinstance(value, list):
                children.append(dict2xml(value, key))
            elif key[0] == '@':
                attr = attr + ' ' + key[1::] + '="' + str(value) + '"'
            else:
                xml = '<' + key + ">" + str(value) + '</' + key + '>' 
                children.append(xml)

    else:
        #if list
        for value in d:
            children.append(dict2xml(value, root_singular))

    end_tag = '>' if 0 < len(children) else '/>'
    
    if wrap or isinstance(d, dict):
        xml = '<' + root + attr + end_tag

    if 0 < len(children):
        for child in children:
            xml = xml + child

        if wrap or isinstance(d, dict):
            xml = xml + '</' + root + '>'

    return xml
@solua100

This comment has been minimized.

Copy link

@solua100 solua100 commented Oct 2, 2020

Thanks @thomaswpp, your modify fit my problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.