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.

Show comment
Hide comment
@native-api

native-api Jul 12, 2013

unsafe against XML special charaters in input

native-api commented Jul 12, 2013

unsafe against XML special charaters in input

@jarrar

This comment has been minimized.

Show comment
Hide comment
@jarrar

jarrar May 11, 2014

But excellent for simple object serialization needs

jarrar commented May 11, 2014

But excellent for simple object serialization needs

@zappfinger

This comment has been minimized.

Show comment
Hide comment
@zappfinger

zappfinger Sep 1, 2014

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

zappfinger commented Sep 1, 2014

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

@Gerst20051

This comment has been minimized.

Show comment
Hide comment
@Gerst20051

Gerst20051 Feb 17, 2016

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

Gerst20051 commented Feb 17, 2016

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

@jharms

This comment has been minimized.

Show comment
Hide comment
@jharms

jharms Jun 1, 2016

also available using pip install dict2xml.

jharms commented Jun 1, 2016

also available using pip install dict2xml.

@jonahfang

This comment has been minimized.

Show comment
Hide comment
@jonahfang

jonahfang Sep 14, 2016

change line 59 to avalid unicode error:

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

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.

Show comment
Hide comment
@abeaclark

abeaclark 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.

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.

Show comment
Hide comment
@thomaswpp

thomaswpp 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

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment