Package: dicttoxml
SummaryConverts a Python dictionary or other native data type into a valid XML string.DetailsSupports item (int,float,long,decimal.Decimal,bool,str,unicode,datetime,noneand other number-like objects) and collection (list,set,tupleanddict, as well as iterable and dict-like objects) data types, with arbitrary nesting for the collections. Items with adatetimetype are converted to ISO format strings. Items with aNonetype become empty XML elements.The root object passed into thedicttoxmlmethod can be any of the supported data types.To satisfy XML syntax, the method prepends an<?xml version="1.0" encoding="UTF-8" ?>element and wraps the output in a<root> ... </root>element. However, this can be disabled to create XML snippets. Alternately, a custom root element can be specified by passing in the optionalcustom_root=foobarargument.For lists of items, if each item is also a collection data type (lists,dict), the elements of that item are wrapped in a generic<item> ... </item>element.Each element includes an optionaltypeattribute with the data type. By default, the type attribute it included but it can be excluded by passing an optionalattr_type=Falseargument when calling thedicttoxmlmethod.Note:datetimedata types are converted into ISO format strings, andunicodeanddatetimedata types get astrattribute.Python -> XML
integer   int
long      long
float     float
Decimal   number
string    str
unicode   str
datetime  str
None      null
boolean   bool
list      list
set       list
tuple     list
dict      dictElements with an unsupported data type raise a TypeError exception.If an element name is invalid XML, it is rendered with the name "key" and the invalid name is included as anameattribute. E.g.{ "^.{0,256}$": "foo" }would be rendered<key name="^.{0,256}$">foo</key>. An exception is element names with spaces, which are converted to underscores.This module should work in Python 3.6+. You might be able to get it to work in Python 2.x but that is no longer supported.InstallationThe dicttoxml module ispublished on the Python Package Index, so you can install it usingpip.pip install dicttoxmlAlternately, you can download the tarballed installer -dicttoxml-[VERSION].tar.gz- for this package from thedistdirectory on github and uncompress it. Then, from a terminal or command window, navigate into the unzipped folder and type the command:python setup.py installThat should be all you need to do.Basic UsageOnce installed, import the library into your script and convert a dict into xml by running thedicttoxmlfunction:>>> import dicttoxml
>>> xml = dicttoxml.dicttoxml(some_dict)Alternately, you can import thedicttoxml()function from the library.>>> from dicttoxml import dicttoxml
>>> xml = dicttoxml(some_dict)That's it!JSON to XMLLet's say you want to fetch a JSON object from a URL and convert it into XML. Here's how you can do that:>>> import json
>>> import urllib
>>> import dicttoxml
>>> page = urllib.urlopen('http://quandyfactory.com/api/example')
>>> content = page.read()
>>> obj = json.loads(content)
>>> print(obj)
{u'mylist': [u'foo', u'bar', u'baz'], u'mydict': {u'foo': u'bar', u'baz': 1}, u'ok': True}
>>> xml = dicttoxml.dicttoxml(obj)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><mylist><item type="str">foo</item><item type="str">bar</item><item type="str">baz</item></mylist><mydict><foo type="str">bar</foo><baz type="int">1</baz></mydict><ok type="bool">true</ok></root>It's that simple.XML SnippetInstead of creating a full XML document, you can create an XML snippet for inclusion into another XML document.Continuing with the example from above:>>> xml_snippet = dicttoxml.dicttoxml(obj, root=False)
>>> print(xml_snippet)
<mylist><item type="str">foo</item><item type="str">bar</item><item type="str">baz</item></mylist><mydict><foo type="str">bar</foo><baz type="int">1</baz></mydict><ok type="bool">true</ok>With the optionalrootargument set toFalse, the method converts the dict into XML without including an<?xml>prolog or a<root>element to enclose all the other elements.Custom RootBy default, dicttoxml wraps all the elements in a<root> ... </root>element. Starting in version 1.5, you can change the name of the root element to something else by passing an optionalcustom_root=some_custom_rootargument to thedicttoxmlmethod.Using our example:>>> xml = dicttoxml.dicttoxml(obj, custom_root='some_custom_root')
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><some_custom_root><mydict><foo>bar</foo><baz>1</baz></mydict><mylist><item>foo</item><item>bar</item><item>baz</item></mylist><ok>true</ok></some_custom_root>As you can see, the name of the root element has changed tosome_custom_root.Omit XML DeclarationPerhaps you want your outputted XML to have arootbut no XML declaration. Starting with version 1.7.15, can calldicttoxmlwith the optionalxml_declarationargument set toFalse:>>> xml = dicttoxml.dicttoxml(xml_declaration=False)
>>> print(xml)
<root><ok type="bool">true</ok><mylist type="list"><item type="str">foo</item><item type="str">bar</item><item type="str">baz</item></mylist><mydict type="dict"><foo type="str">bar</foo><baz type="int">1</baz></mydict></root>As you can see, the XML declaration has been omitted.Disable Type AttributesBy default, dicttoxml includes a type attribute for each element. Starting in version 1.4, you can turn this off by passing an optionalattr_type=Falseargument to thedicttoxmlmethod.Using our example:>>> xml = dicttoxml.dicttoxml(obj, attr_type=False)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><mydict><foo>bar</foo><baz>1</baz></mydict><mylist><item>foo</item><item>bar</item><item>baz</item></mylist><ok>true</ok></root>As you can see, the only difference is that the type attributes are now absent.Change or Suppress XML Encoding AttributeBy default, dicttoxml renders the XML element with anencoding="UTF-8"attribute. Starting in version 1.7.6, you can change the encoding by using the optionalencodingargument to thedicttoxmlmethod. For example, to render an XML file with encoding "ISO-8859-1", you would call:>>> xml = dicttoxml.dicttoxml(obj, encoding="ISO-8859-1")Or if you prefer, you can suppress the encoding attribute altogether by setting the optionalinclude_encodingargument toFalse:>>> xml = dicttoxml.dicttoxml(obj, include_encoding=False)Again, by default, theinclude_encodingargument is set toTrueand theencodingargument is set toUTF-8.Unique ID AttributesStarting in version 1.1, you can set an optionalidsparameter so that dicttoxml gives each element a uniqueidattribute.With theidsflag on, the function generates a unique randomly-generated ID for each element based on the parent element in the formparent_unique. For list items, the id is in the formparent_unique_index.Continuing with our example:>>> xml_with_ids = dicttoxml.dicttoxml(obj, ids=True)
>>> print(parseString(xml_with_ids).toprettyxml())
<?xml version="1.0" ?>
<root>
        <mylist id="root_160980" type="list">
                <item id="mylist_609405_1" type="str">foo</item>
                <item id="mylist_609405_2" type="str">bar</item>
                <item id="mylist_609405_3" type="str">baz</item>
        </mylist>
        <mydict id="root_140407" type="dict">
                <foo id="mydict_260437" type="str">bar</foo>
                <baz id="mydict_111194" type="int">1</baz>
        </mydict>
        <ok id="root_612831" type="bool">true</ok>
</root>Note that the default XML output remains the same as previous, so as not to break compatibility for existing uses.Dict-Like and Iterable ObjectsStarting in version 1.3, dicttoxml accepts dict-like objects that are derived from thedictbase class and treats them like dicts. For example:>>> import collections
>>> dictlike = collections.OrderedDict({'foo': 1, 'bar': 2, 'baz': 3})
>>> xml = dicttoxml.dicttoxml(dictlike)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><baz type="int">3</baz><foo type="int">1</foo><bar type="int">2</bar></root>Also starting in version 1.3, dicttoxml accepts iterable objects and treats them like lists. For example:>>> myiter = range(1,11)
>>> xml = dicttoxml.dicttoxml(myiter)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><item type="int">1</item><item type="int">2</item><item type="int">3</item><item type="int">4</item><item type="int">5</item><item type="int">6</item><item type="int">7</item><item type="int">8</item><item type="int">9</item><item type="int">10</item></root>As always, this remains compatible with arbitrary nesting of objects and types.Define Custom Item NamesStarting in version 1.7, if you don't want item elements in a list to be called 'item', you can specify the element name using a function that takes the parent element name (i.e. the list name) as an argument.>>> import dicttoxml
>>> obj = {u'mylist': [u'foo', u'bar', u'baz'], u'mydict': {u'foo': u'bar', u'baz': 1}, u'ok': True}
>>> my_item_func = lambda x: 'list_item'
>>> xml = dicttoxml.dicttoxml(obj, item_func=my_item_func)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><mydict type="dict"><foo type="str">bar</foo><baz type="int">1</baz></mydict><mylist type="list"><list_item type="str">foo</list_item><list_item type="str">bar</list_item><list_item type="str">baz</list_item></mylist><ok type="bool">True</ok></root>The benefit of taking the parent element name as an argument is that you can write the function to do something with it. Let's say you have an object with some lists of specific items:>>> obj = {'shrubs': ['abelia', 'aralia', 'aucuba', 'azalea', 'bamboo', 'barberry', 'bluebeard', 'boxwood', 'camellia', 'dogwood', 'elderberry', 'enkianthus', 'firethorn', 'fuchsia', 'hazel', 'heath', 'heather', 'holly', 'honeysuckle', 'hydrangea', 'laurel', 'lilac', 'mock orange', 'rhododendron', 'rose', 'rose of sharon', 'rosemary', 'smokebush', 'spirea', 'sweetbox', 'viburnum', 'weigela', 'yucca'], 'trees': ['ash', 'aspen', 'birch', 'butternut', 'cedar', 'cottonwood', 'elm', 'fir', 'hawthorn', 'larch', 'locust', 'maple', 'oak', 'pine', 'spruce', 'sycamore', 'willow']}You can define each item name to be the singular of its parent name by returning all but the last character.>>> my_item_func = lambda x: x[:-1]
>>> xml = dicttoxml.dicttoxml(obj, item_func=my_item_func)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><shrubs type="list"><shrub type="str">abelia</shrub><shrub type="str">aralia</shrub><shrub type="str">aucuba</shrub><shrub type="str">azalea</shrub><shrub type="str">bamboo</shrub><shrub type="str">barberry</shrub><shrub type="str">bluebeard</shrub><shrub type="str">boxwood</shrub><shrub type="str">camellia</shrub><shrub type="str">dogwood</shrub><shrub type="str">elderberry</shrub><shrub type="str">enkianthus</shrub><shrub type="str">firethorn</shrub><shrub type="str">fuchsia</shrub><shrub type="str">hazel</shrub><shrub type="str">heath</shrub><shrub type="str">heather</shrub><shrub type="str">holly</shrub><shrub type="str">honeysuckle</shrub><shrub type="str">hydrangea</shrub><shrub type="str">laurel</shrub><shrub type="str">lilac</shrub><shrub type="str">mock orange</shrub><shrub type="str">rhododendron</shrub><shrub type="str">rose</shrub><shrub type="str">rose of sharon</shrub><shrub type="str">rosemary</shrub><shrub type="str">smokebush</shrub><shrub type="str">spirea</shrub><shrub type="str">sweetbox</shrub><shrub type="str">viburnum</shrub><shrub type="str">weigela</shrub><shrub type="str">yucca</shrub></shrubs><trees type="list"><tree type="str">ash</tree><tree type="str">aspen</tree><tree type="str">birch</tree><tree type="str">butternut</tree><tree type="str">cedar</tree><tree type="str">cottonwood</tree><tree type="str">elm</tree><tree type="str">fir</tree><tree type="str">hawthorn</tree><tree type="str">larch</tree><tree type="str">locust</tree><tree type="str">maple</tree><tree type="str">oak</tree><tree type="str">pine</tree><tree type="str">spruce</tree><tree type="str">sycamore</tree><tree type="str">willow</tree></trees></root>Of course, this can be combined with other optional arguments, like disabling type attributes or custom root element names.CDATAStarting in version 1.7.1, you can wrap values in CDATA by setting the optionalcdataargument toTrue.>>> import dicttoxml
>>> obj = {u'mylist': [u'foo', u'bar', u'baz'], u'mydict': {u'foo': u'bar', u'baz': 1}, u'ok': True}
>>> xml = dicttoxml.dicttoxml(obj, cdata=True)
>>> print(xml)
<?xml version="1.0" encoding="UTF-8" ?><root><mydict type="dict"><foo type="str"><![CDATA[bar]]></foo><baz type="int"><![CDATA[1]]></baz></mydict><mylist type="list"><item type="str"><![CDATA[foo]]></item><item type="str"><![CDATA[bar]]></item><item type="str"><![CDATA[baz]]></item></mylist><ok type="bool"><![CDATA[True]]></ok></root>If you do not setcdatatoTrue, the default value isFalseand values are not wrapped.Return a StringBy default, dicttoxml outputs the generated XML as abytesobject:>>> xml = dicttoxml.dicttoxml(obj)
>>> type(xml).__name__
'bytes'Starting in version 1.7.14, when you call the dicttoxml function, you can set an optionalreturn_bytesargument toFalseto return astrobject instead:>>> xml = dicttoxml.dicttoxml(obj, return_bytes=False)
>>> type(xml).__name__
'str'But by default,return_bytesis set toTrue.Pretty-PrintingAs they say, Python comes with batteries included. You can easily syntax-check and pretty-print your XML using Python'sxml.dom.minidommodule.Again, continuing with our example:>>> from xml.dom.minidom import parseString
>>> dom = parseString(xml)
>>> print(dom.toprettyxml())
<?xml version="1.0" ?>
<root>
    <mylist type="list">
        <item type="str">foo</item>
        <item type="str">bar</item>
        <item type="str">baz</item>
    </mylist>
    <mydict type="dict">
        <foo type="str">bar</foo>
        <baz type="int">1</baz>
    </mydict>
    <ok type="bool">true</ok>
</root>This makes the XML easier to read. If it is not well-formed, the xml parser will raise an exception.DebuggingYou can enable debugging informationby calling theset_debug()method:>>> import dicttoxml
>>> dicttoxml.set_debug(debug=True)
Debug mode is on. Events are logged at: dicttoxml.log
>>> xml = dicttoxml.dicttoxml(some_dict)By default, debugging information is logged todicttoxml.log, but you can change this:>>> dicttoxml.set_debug(debug=True, filename='/path/to/some_other_filename.log')
Debug mode is on. Events are logged at: some_other_filename.logTo turn debug mode off, just callset_debugwith an argument ofFalse:>>> dicttoxml.set_debug(debug=False)If you encounter any errors in the code, please file an issue on github:https://github.com/quandyfactory/dicttoxml/issues.AuthorAuthor: Ryan McGrealEmail:ryan@quandyfactory.comRepository:http://github.com/quandyfactory/dicttoxmlVersionVersion: 1.7.16Release Date: 2022-12-23Revision HistoryVersion 1.7.16Release Date: 2022-12-23Changes:Resolvedissue #98andissue #99(big thanks toadrien-berchetfor identifying the issue and proposing the solution)Addedpython_requires=">=3.6"tosetup.pyVersion 1.7.15Release Date: 2022-12-02Changes:Fixedissue #43Implementedissue #82Small fixes to readme.mdVersion 1.7.14Release Date: 2022-12-02Changes:Handle floating point keys as perissue #61Option to return string instead of bytes as perissue #55Reorganized readme.md to have a better flow.Version 1.7.13Release Date: 2022-11-29Changes:Fixedissue #53, dicttoxml(None) and dicttoxml("name") break in 1.7Fixedissue #96, update readme section on debuggingVersion 1.7.12Release Date: 2022-11-29Changes:Fixedissue #95: changed project.toml to support Python 3.6+ and updated readme documentation.Version 1.7.11Release Date: 2022-11-28Changes:Simplified solution to issue 94Version 1.7.9Release Date: 2022-11-28Changes:Fixedissue #94Version 1.7.8Release Date: 2022-11-28Changes:Fixedissue #67andissue #81: Boolean values now export into XML in lowercase (true, false) instead of capitalized (True, False).Version 1.7.7Release Date: 2022-11-27Changes:Fixedissue #58andissue #60on github: debug is turned off by default, and no longer prints "Debug mode is off" in the console.Version 1.7.6Release Date: 2022-11-26Changes:Fixedissue #88on github.Made XML encoding attribute optional and editable as perissue 83on github.Version 1.7.5Release Date: 2022-06-06Changes:Fixedisue #91on github.Version 1.7.4Release Date: 2016-07-08Changes:Fixedbug #46on github. Thanks torobbincatzfor identifying and reporting the issue.Version 1.7.3Release Date: 2016-07-07Changes:Updated README.markdownVersion 1.7.2Release Date: 2016-07-07Changes:XML-encodes values to avoid XML injection. Big thanks tothomaskonradon Github, viaissue #41.Version 1.7.1Release Date: 2016-07-06Changes:Added ability to wrap values with CDATA. Big thanks toLeviTauleon Github, viapull request #45.Version 1.7Release Date: 2016-06-13Changes:First of all, sorry for such a log delay between releases! I have not been a responsible steward of this project and I aim to change that from now on. This is the first in a series of updates I will be pushing over the next couple of months to get caught up on the backlog of issues and pull requests.Added ability to customizelistanddictitem names via a function argument passed into thedicttoxml()function. Customizeable item name function takes the item's parent element as an argument. Big thanks toviktor-zireaelon Github, viapull request #40.Updated code style to more closely follow PEP8.Version 1.6.6Release Date: 2015-04-09Changes:PyPi does not want to upload version 1.6.5. It's returning anUpload failed (500): Internal Server Errormessage when I try to upload the code. I'm incrementing the version by one and reinstalling it to see if that fixes the issue.Version 1.6.5Release Date: 2015-04-09Changes:Fixedissue #37, elements with boolean values were getting a "number" type attribute. The issue was thatisinstance(True, numbers.Number)returnsTrue. I modified theget_xml_type()function to test forbooleanbefore testing fornumbers.Number. Thanks tobadsequelfor identifying and reporting the issue.Version 1.6.4Release Date: 2015-03-11Changes:Fixedissue #36, logging was throwing an UnicodeDecodeError on non-ASCII characters in dictionary values. Thanks tobeef9999for identifying and reporting the issue.Version 1.6.3Release Date: 2015-03-05Changes:Updated README.markdown to reflect changes made in v. 1.6.2.Version 1.6.2Release Date: 2015-03-05Changes:Fixedissue #35, dicttoxml fails to identify adecimal.Decimalas a number. This is done by replacingtype(val).__name__ in ('int', 'long')with the more genericisinstance(val, number.Number). Thanks tojmagnussonfor finding and fixing the error.Version 1.6.1Release Date: 2015-03-05Changes:Mergedpull request #34, fix misleading TypeError inconvert_dict(). Thanks tojmagnussonfor finding and fixing the error.Version 1.6.0Release Date: 2015-02-23Changes:Fixedissue #32, duplication in test for list-like data types.Version 1.5.9Release Date: 2015-02-23Changes:Mergedpull request #33to replace invocations ofloggingwithLOG. Thanks tomfriedenhagenfor identifying the issue with the logger, and toseyhunsfor supplying a pull request that could be merged automatically.Version 1.5.8Release Date: 2015-01-06Changes:Fixedissue #30viapull request #31. Thanks toisaac-councillfor identifying the issue and providing a fix.Version 1.5.7Release Date: 2014-12-09Changes:Fixedissue #29. Thanks tobirdsarahfor identifying this performance issue and providing a fix.Version 1.5.6Release Date: 2014-08-18Changes:Fixedissue #24. Thanks togdude2002for identifying the issue.Abstracted all XML validity tests to a single functionmake_valid_xml_name(key, attr)Version 1.5.5Release Date: 2014-06-16Changes:Fixedissue #21. Thanks tolichenbofor identifying the issue and providing a fix.Abstracted setting XML type attribute into a function,get_xml_type().Standardized variable names inside functions (e.g.k->key,v->val).Cleaned up README so it works as both Markdown (for github) and ReStructuredText (for PyPi)Version 1.5.4Release Date: 2014-06-03Changes:Fixedissue #20.  Thanks tolichenbofor identifying the issue and providing a fix.Version 1.5.3Release Date: 2014-06-08Changes:Minor updates to README.markdownVersion 1.5.2Release Date: 2014-06-03Changes:Minor updates to README.markdownVersion 1.5.1Release Date: 2014-06-03Changes:Minor updates to README.markdownVersion 1.5Release Date: 2014-06-03Changes:Added ability to set a custom root element, as perissue #18bymurielsilveira.Version 1.4Release Date: 2014-06-03Changes:Element type attribute made optional via pull request from [gauravub](https://github.com/gauravub]to resolveissue #17.Version 1.3.7Release Date: 2014-04-21Changes:UpdatedMANIFEST.inandsetup.pyso the licence and readme are properly included in the distribution.Version 1.3.6Release Date: 2014-04-21Changes:AddedMANIFEST.into include theLICENCE.txtandREADME.markdownfiles in the distribution, as perissue #15.Version 1.3.5Release Date: 2014-04-14Changes:dicttoxml()accepts[None]as a parameter and returns a valid XML object, as perissue #13.Version 1.3.4Release Date: 2014-04-14Changes:dicttoxml()now acceptsNoneas a parameter and returns a valid XML object, as perissue #13.Version 1.3.3Release Date: 2014-04-14Changes:Automatically converts spaces in key names to underscores, as perissue #12.Version 1.3.2Release Date: 2014-04-14Changes:Added convert_none() function to convert a null value into XMLAddedkey_is_valid_xml()function to test if a key is valid XMLUpdatedconvert_kv(),convert_bool()andconvert_none()functions to test whether the key is a valid XML name and, if it is not, to render it as<key name="{invalidname}">value</key>. This addressesissue 10.Version 1.3.1Release Date: 2013-07-12Changes:Updated README to note support for dict-like and iterable objects.Version 1.3Release Date: 2013-07-12Changes:changed test for dict type fromtype(x)=dicttoisinstance(x,dict)to include dict-like subclases derived from dict, as perissue 9.Added test forisinstance(x,collections.Iterable)to test for list, set, tuple to accommodate iterable objects, as perissue 9.Version 1.2Release Date: 2013-07-11Changes:Fixed typo in convert_list() exception raise as perissue 8.Version 1.1.2Release Date: 2013-05-06Changes:Renamed github repo from dict2xml to dicttoxml to match PyPI name.Version 1.1.1Release Date: 2013-05-06Changes:Fixed README.markdownVersion 1.1Release Date: 2013-05-06Changes:Added an optionalidsargument to give each element a unique, randomly generated id attribute.All elements now inlcude atypeattribute.Updated readme with more examples and Python 3 compatible syntax.Thanks tocpetzforsuggestingthis feature.Verson 1.0Release Date: 2013-03-04Changes:Replaced debug function withloggingmodule.Converted code to work in Python 2.6+ and Python 3.Fixed unresolved isoformat reference inconvert_list.Bug thanks toregisdfor forking code and making several important fixes!Version 0.9.1Release Date: 2013-03-03Changes:Mergedpull requestfromregisdto fixissue #5, in which special XML characters were not being escaped properly.Version 0.9Release Date: 2013-02-27Changes:Added support for tuples.Version 0.8Release Date: 2013-02-23Changes:Changed name to dicttoxml and published to the Python Package Index (PyPI).Version 0.7Release Date: 2012-09-12Changes:Fixedissue #4- thanks to PaulMdx for finding it and suggesting a fix.Version 0.6Release Date: 2012-07-13Changes:Merged pull request from0902hornon github to escape special XML characters.Version 0.5Release Date: 2012-02-28Changes:Added support for datetime objects (converts them into ISO format strings) and sets (converts them into lists).Fixedbug 2by raising an exception on unsupported data types.Version 0.4Release Date: 2012-01-26Changes:Added optionalrootargument (defaultTrue) on whether to wrap the generated XML in an XML declaration and a root element.Added ability to convert a root object of other data types - int, float, str, unicode, list - as well as dict.Correctedlicenseattribute insetup.py.Renamednotify()function todebug_notify()and made it more comprehensive.Version 0.3Release Date: 2012-01-24Changes:Fixed inconsistent str/string attributes.Version 0.2Release Date: 2012-01-24Changes:Fixed bug in list items.Added element attribute with data type.Version 0.1Release Date: 2012-01-24Changes:First commit.Copyright and LicenceCopyright 2012 by Ryan McGreal.Released under the GNU General Public Licence, Version 2:http://www.gnu.org/licenses/old-licenses/gpl-2.0.html