Search code examples
pythonattributesxmltodictdicttoxml

xmltodict and back again; attributes get their own tag


I'm trying to create something that imports an XML, compares some of the values to values from another XML or values in an Oracle Database, and then write it back again with some values changed. I've tried simply importing the xml and then exporting it again, but that already leads to an issue for me; xml attributes are not shown as attributes within the tag anymore, instead they get their own child tag.

I think it's the same problem as described here, in which the top answer says that the issue has been open for years. I'm hoping you guys know an elegant way to fix this, because the only thing I can think of is doing a replace after the export.

import xmltodict
from dicttoxml import dicttoxml

testfile = '<Testfile><Amt Ccy="EUR">123.45</Amt></Testfile>'
print(testfile)
print('\n')

orgfile = xmltodict.parse(testfile)
print(orgfile)
print('\n')

newfile = dicttoxml(orgfile, attr_type=False).decode()
print(newfile)

Result:

D:\python3 Test.py
<Testfile><Amt Ccy="EUR">123.45</Amt></Testfile>


OrderedDict([('Testfile', OrderedDict([('Amt', OrderedDict([('@Ccy', 'EUR'), ('#
text', '123.45')]))]))])


<?xml version="1.0" encoding="UTF-8" ?><root><Testfile><Amt><key name="@Ccy">EUR
</key><key name="#text">123.45</key></Amt></Testfile></root>

You can see the input tag Amt Ccy="EUR" gets converted to Amt with child tags.


Solution

  • I'm not sure which libraries you're actually using, but xmltodict has an unparse method, that does exactly what you want:

    import xmltodict
    
    testfile = '<Testfile><Amt Ccy="EUR">123.45</Amt></Testfile>'
    print(testfile)
    print('\n')
    
    orgfile = xmltodict.parse(testfile)
    print(orgfile)
    print('\n')
    
    newfile = xmltodict.unparse(orgfile, pretty=False)
    print(newfile)
    

    Output:

    <Testfile><Amt Ccy="EUR">123.45</Amt></Testfile>
    
    
    OrderedDict([('Testfile', OrderedDict([('Amt', OrderedDict([('@Ccy', 'EUR'), ('#text', '123.45')]))]))])
    
    
    <?xml version="1.0" encoding="utf-8"?>
    <Testfile><Amt Ccy="EUR">123.45</Amt></Testfile>