Package: xmltodict
xmltodictxmltodictis a Python module that makes working with XML feel like you are working withJSON, as in this"spec":>>>print(json.dumps(xmltodict.parse("""...  <mydocument has="an attribute">...    <and>...      <many>elements</many>...      <many>more elements</many>...    </and>...    <plus a="complex">...      element as well...    </plus>...  </mydocument>...  """),indent=4)){"mydocument":{"@has":"an attribute","and":{"many":["elements","more elements"]},"plus":{"@a":"complex","#text":"element as well"}}}Namespace supportBy default,xmltodictdoes no XML namespace processing (it just treats namespace declarations as regular node attributes), but passingprocess_namespaces=Truewill make it expand namespaces for you:>>>xml="""... <root xmlns="http://defaultns.com/"...       xmlns:a="http://a.com/"...       xmlns:b="http://b.com/">...   <x>1</x>...   <a:y>2</a:y>...   <b:z>3</b:z>... </root>... """>>>xmltodict.parse(xml,process_namespaces=True)=={...'http://defaultns.com/:root':{...'http://defaultns.com/:x':'1',...'http://a.com/:y':'2',...'http://b.com/:z':'3',...}...}TrueIt also lets you collapse certain namespaces to shorthand prefixes, or skip them altogether:>>>namespaces={...'http://defaultns.com/':None,# skip this namespace...'http://a.com/':'ns_a',# collapse "http://a.com/" -> "ns_a"...}>>>xmltodict.parse(xml,process_namespaces=True,namespaces=namespaces)=={...'root':{...'x':'1',...'ns_a:y':'2',...'http://b.com/:z':'3',...},...}TrueStreaming modexmltodictis very fast (Expat-based) and has a streaming mode with a small memory footprint, suitable for big XML dumps likeDiscogsorWikipedia:>>>defhandle_artist(_,artist):...print(artist['name'])...returnTrue>>>>>>xmltodict.parse(GzipFile('discogs_artists.xml.gz'),...item_depth=2,item_callback=handle_artist)APerfectCircleFantômasKingCrimsonChrisPotter...It can also be used from the command line to pipe objects to a script like this:importsys,marshalwhileTrue:_,article=marshal.load(sys.stdin)print(article['title'])$bunzip2enwiki-pages-articles.xml.bz2|xmltodict.py2|myscript.py
AccessibleComputing
Anarchism
AfghanistanHistory
AfghanistanGeography
AfghanistanPeople
AfghanistanCommunications
Autism
...Or just cache the dicts so you don't have to parse that big XML file again. You do this only once:$bunzip2enwiki-pages-articles.xml.bz2|xmltodict.py2|gzip>enwiki.dicts.gzAnd you reuse the dicts with every script that needs them:$gunzipenwiki.dicts.gz|script1.py
$gunzipenwiki.dicts.gz|script2.py
...RoundtrippingYou can also convert in the other direction, using theunparse()method:>>>mydict={...'response':{...'status':'good',...'last_updated':'2014-02-16T23:10:12Z',...}...}>>>print(unparse(mydict,pretty=True))<?xmlversion="1.0"encoding="utf-8"?><response><status>good</status><last_updated>2014-02-16T23:10:12Z</last_updated></response>Text values for nodes can be specified with thecdata_keykey in the python dict, while node properties can be specified with theattr_prefixprefixed to the key name in the python dict. The default value forattr_prefixis@and the default value forcdata_keyis#text.>>>importxmltodict>>>>>>mydict={...'text':{...'@color':'red',...'@stroke':'2',...'#text':'This is a test'...}...}>>>print(xmltodict.unparse(mydict,pretty=True))<?xmlversion="1.0"encoding="utf-8"?><textstroke="2"color="red">Thisisatest</text>Lists that are specified under a key in a dictionary use the key as a tag for each item. But if a list does have a parent key, for example if a list exists inside another list, it does not have a tag to use and the items are converted to a string as shown in the example below.  To give tags to nested lists, use theexpand_iterkeyword argument to provide a tag as demonstrated below. Note that usingexpand_iterwill break roundtripping.>>>mydict={..."line":{..."points":[...[1,5],...[2,6],...]...}...}>>>print(xmltodict.unparse(mydict,pretty=True))<?xmlversion="1.0"encoding="utf-8"?><line><points>[1,5]</points><points>[2,6]</points></line>>>>print(xmltodict.unparse(mydict,pretty=True,expand_iter="coord"))<?xmlversion="1.0"encoding="utf-8"?><line><points><coord>1</coord><coord>5</coord></points><points><coord>2</coord><coord>6</coord></points></line>Ok, how do I get it?Using pypiYou just need to$pipinstallxmltodictRPM-based distro (Fedora, RHEL, …)There is anofficial Fedora package for xmltodict.$sudoyuminstallpython-xmltodictArch LinuxThere is anofficial Arch Linux package for xmltodict.$sudopacman-Spython-xmltodictDebian-based distro (Debian, Ubuntu, …)There is anofficial Debian package for xmltodict.$sudoaptinstallpython-xmltodictFreeBSDThere is anofficial FreeBSD port for xmltodict.$pkginstallpy36-xmltodictopenSUSE/SLE (SLE 15, Leap 15, Tumbleweed)There is anofficial openSUSE package for xmltodict.# Python2$zypperinpython2-xmltodict# Python3$zypperinpython3-xmltodict