You can pass a postprocessing function to xmltodict, which allows you to modify the dict values.
But postprocecssing needs to return a key and a value:
import xmltodict
import json
def postprocessor(path, key, value):
if key == 'Pokemons' and not value:
return key, []
return key, value
xml = """<Something>
<Guitar>
<name>Walden</name>
<strings>5</strings>
</Guitar>
<Pokemons>
</Pokemons>
</Something>"""
res = xmltodict.parse(xml, postprocessor=postprocessor)
print(json.dumps(res, indent=2, sort_keys=True))
Output:
{
"Something": {
"Guitar": {
"name": "Walden",
"strings": "5"
},
"Pokemons": []
}
}
Answer from Maurice Meyer on Stack OverflowGitHub
github.com › martinblech › xmltodict › blob › master › xmltodict.py
xmltodict/xmltodict.py at master · martinblech/xmltodict
>>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value · >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ...
Author martinblech
PyPI
pypi.org › project › xmltodict
xmltodict · PyPI
» pip install xmltodict
Videos
05:46
Parsing XML files using xmltodict - YouTube
03:25
python xmltodict parse example - YouTube
02:49
pip install xmltodict python - YouTube
01:27
Resolving ModuleNotFoundError for xmltodict in Python - YouTube
Python xmltodict indicies error
04:12
Error when parsing XML document using xmltodict python - YouTube
Omz Software
omz-software.com › pythonista › docs › ios › xmltodict.html
xmltodict — Python 3.6.1 documentation
February 19, 2020 - >>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ... postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of expat (such as defusedexpat) by using the expat parameter.
Readthedocs
xmltodict.readthedocs.io › en › latest › CHANGELOG
CHANGELOG - xmltodict
Merge branch 'master' of github.com:martinblech/xmltodict · preserve xml attribute order (fixes #13) fix #12: postprocess cdata items too · added info about official fedora package · Merge pull request #11 from ralphbean/master · Include REAMDE, LICENSE, and tests in the distributed tarball. take all characters (no need to strip and filter) fixed CLI (marshal only takes dict, not OrderedDict) ignore MANIFEST · implemented postprocessor callback (#6) update readme with install instructions ·
Tanium
tanium.github.io › pytan › _modules › xmltodict.html
xmltodict — PyTan v2.1.6 2.1.6 documentation
postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of `expat` (such as `defusedexpat`) by using the `expat` parameter. E.g: >>> import defusedexpat >>> xmltodict.parse('<a>hello</a>', expat=defusedexpat.pyexpat) OrderedDict([(u'a', u'hello')]) """ handler = _DictSAXHandler(namespace_separator=namespace_separator, **kwargs) if isinstance(xml_input, _unicode): if not encoding: encoding = 'utf-8' xml_input = xml_input.encode(encoding) if not process_namespaces: namespace_separator = None parser = expat.ParserCreate
Top answer 1 of 2
1
You can pass a postprocessing function to xmltodict, which allows you to modify the dict values.
But postprocecssing needs to return a key and a value:
import xmltodict
import json
def postprocessor(path, key, value):
if key == 'Pokemons' and not value:
return key, []
return key, value
xml = """<Something>
<Guitar>
<name>Walden</name>
<strings>5</strings>
</Guitar>
<Pokemons>
</Pokemons>
</Something>"""
res = xmltodict.parse(xml, postprocessor=postprocessor)
print(json.dumps(res, indent=2, sort_keys=True))
Output:
{
"Something": {
"Guitar": {
"name": "Walden",
"strings": "5"
},
"Pokemons": []
}
}
2 of 2
0
xmltodict.parse (with force_list arg) convert xml to a OrderedDict with tag as key irrespective for if node is empty or not (in case of empty node None value is stored in dict).
Therefore you have to filter your dict result for None yourself.
To filter dict you can define your custom method:
def filter_dict(item):
if not item:
return ''
elif isinstance(item, list):
return [it for it in item if it]
elif not hasattr(item, 'items'):
return item
else:
return {key: filter_dict(value) for key, value in item.items()}
>>> res = xmltodict.parse(xml, force_list=('Pokemons',))
>>> res = filter_dict(res)
>>> pokemons = res['Something']['Pokemons']
>>> pokemons
>>> []
Stack Overflow
stackoverflow.com › questions › 53744074 › xmltodict-unparse-parse-not-the-same
python - xmltodict unparse parse not the same - Stack Overflow
def postprocessor(path, key, value): if key.startswith("value"): try: return key, int(value) except (ValueError, TypeError): return key, value return key, value test_data_re = xmltodict.parse(xml_str, dict_constructor=dict, postprocessor=postprocessor) print("xml_str back to dict : ", test_data_re['settings']) This would produce: xml_str back to dict : {'value1': 1, 'parent_lvl1': {'parent_Lvl2': {'value1': 2, 'value2': 3}}} Btw, a good place to look for xmltodict sample usages is xmltodict tests, check it out.
GitHub
github.com › martinblech › xmltodict › issues › 107
postprocessor doesn't have effect on attributes? · Issue #107 · martinblech/xmltodict
June 11, 2015 - >>> def postprocessor(path, key, value): ... try: ... return key, int(value) ... except (ValueError, TypeError): ... return key, value >>> doc="""<mydoc has="an attribute" version=2><and><many>elements</many><many>more elements</many><numbers>2</numbers></and></mydoc>""" >>> json.dumps(xmltodict.parse(doc)) '{"mydoc": {"@has": "an attribute", "@version": "2", "and": {"many": ["elements", "more elements"], "numbers": "2"}}}' >>> json.dumps(xmltodict.parse(doc, postprocessor=postprocessor)) '{"mydoc": {"@has": "an attribute", "@version": "2", "and": {"many": ["elements", "more elements"], "numbers": 2}}}' As of here, @version should be converted integer but didn't, while numbers converted as integer 2.
Author 1kko
Readthedocs
warriorframework.readthedocs.io › en › latest › _modules › Framework › OSS › xmltodict.html
Framework.OSS.xmltodict — warriorframework documentation
postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of `expat` (such as `defusedexpat`) by using the `expat` parameter. E.g: >>> import defusedexpat >>> xmltodict.parse('<a>hello</a>', expat=defusedexpat.pyexpat) OrderedDict([(u'a', u'hello')]) You can use the force_list argument to force lists to be created even when there is only a single child of a given level of hierarchy.
Readthedocs
taf-docs.readthedocs.io › en › latest › _modules › taf › testlib › xmltodict.html
taf.testlib.xmltodict — taf 0.0.1 documentation
postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of `expat` (such as `defusedexpat`) by using the `expat` parameter. E.g: >>> import defusedexpat >>> xmltodict.parse('<a>hello</a>', expat=defusedexpat.pyexpat) OrderedDict([(u'a', u'hello')]) """ handler = _DictSAXHandler(*args, **kwargs) parser = expat.ParserCreate() parser.ordered_attributes = True parser.StartElementHandler = handler.startElement parser.EndElementHandler = handler.endElement parser.CharacterDataHandler = handler.characters try: parser.ParseF
GitHub
github.com › martinblech › xmltodict › blob › master › tests › test_xmltodict.py
xmltodict/tests/test_xmltodict.py at master · martinblech/xmltodict
def test_postprocessor(): def postprocessor(path, key, value): try: return key + ':int', int(value) except (ValueError, TypeError): return key, value · assert {'a': {'b:int': [1, 2], 'b': 'x'}} == parse('<a><b>1</b><b>2</b><b>x</b></a>', postprocessor=postprocessor) ·
Author martinblech
GitHub
github.com › DimitriPapadopoulos › xmltodict › blob › 7e85c54011a1853c7588cb03d0cbb8cf12f08ef4 › xmltodict.py
xmltodict/xmltodict.py at 7e85c54011a1853c7588cb03d0cbb8cf12f08ef4 · DimitriPapadopoulos/xmltodict
>>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value · >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ...
Author DimitriPapadopoulos
HotExamples
python.hotexamples.com › examples › xmltodict › - › parse › python-parse-function-examples.html
Python parse Examples, xmltodict.parse Python Examples - HotExamples
March 15, 2019 - """ import xmltodict if self.postprocessor: obj = xmltodict.parse(f, attr_prefix=self.attr_prefix, postprocessor=self.postprocessor) else: obj = xmltodict.parse(f, attr_prefix=self.attr_prefix) # If node list was given, walk down the tree if self.node_list: for node in self.node_list: obj = obj[node] # If the top-level XML object in the file is a list # then yield each element separately; otherwise, yield # the top-level object.
PyPI
pypi.org › project › xmltodict-fast
xmltodict-fast · PyPI
xml = "<a><item>one</item></a>" xmltodict.parse(xml, force_list=("item",)) # {'a': {'item': ['one']}} ← always a list, even for a single element · def int_postprocessor(path, key, value): try: return key, int(value) except (ValueError, TypeError): return key, value xmltodict.parse("<root><count>42</count></root>", postprocessor=int_postprocessor) # {'root': {'count': 42}} mydict = {"line": {"points": [[1, 5], [2, 6]]}} print(xmltodict.unparse(mydict, pretty=True, expand_iter="coord")) <?xml version="1.0" encoding="utf-8"?> <line> <points> <coord>1</coord> <coord>5</coord> </points> <points> <coord>2</coord> <coord>6</coord> </points> </line> disable_entities=True (default) blocks XML entity expansion (billion-laughs / XML-bomb attacks).
» pip install xmltodict-fast
OMZ Software
omz-software.com › editorial › docs › ios › xmltodict.html
xmltodict — Editorial Documentation
>>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ... postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of expat (such as defusedexpat) by using the expat parameter.
Unixunion
unixunion.github.io › libsolace.xml2dict.html
libsolace.xml2dict module — libsolace 2.0 documentation
>>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ...
OMZ Software
omz-software.com › pythonista2 › docs › ios › xmltodict.html
xmltodict — Pythonista Documentation
>>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ... postprocessor=postprocessor) OrderedDict([(u'a', OrderedDict([(u'b:int', [1, 2]), (u'b', u'x')]))]) You can pass an alternate version of expat (such as defusedexpat) by using the expat parameter.
GitHub
github.com › martinblech › xmltodict › blob › master › CHANGELOG.md
xmltodict/CHANGELOG.md at master · martinblech/xmltodict
Merge branch 'master' of github.com:martinblech/xmltodict · preserve xml attribute order (fixes #13) fix #12: postprocess cdata items too · added info about official fedora package · Merge pull request #11 from ralphbean/master · Include README, LICENSE, and tests in the distributed tarball. take all characters (no need to strip and filter) fixed CLI (marshal only takes dict, not OrderedDict) ignore MANIFEST · #8 preprocessing callback in unparse() implemented postprocessor callback (#6) update readme with install instructions ·
Author martinblech
Unixunion
unixunion.github.io › _modules › libsolace › xml2dict.html
libsolace.xml2dict — libsolace 2.0 documentation
Usage example:: >>> def postprocessor(path, key, value): ... try: ... return key + ':int', int(value) ... except (ValueError, TypeError): ... return key, value >>> xmltodict.parse('<a><b>1</b><b>2</b><b>x</b></a>', ...
ProgramCreek
programcreek.com › python › example › 82408 › xmltodict.parse
Python Examples of xmltodict.parse
def _add_batch(self, catalog_entry, job_id, start_date, order_by_clause=True): endpoint = "job/{}/batch".format(job_id) url = self.bulk_url.format(self.sf.instance_url, endpoint) body = self.sf._build_query_string(catalog_entry, start_date, order_by_clause=order_by_clause) headers = self._get_bulk_headers() headers['Content-Type'] = 'text/csv' with metrics.http_request_timer("add_batch") as timer: timer.tags['sobject'] = catalog_entry['stream'] resp = self.sf._make_request('POST', url, headers=headers, body=body) batch = xmltodict.parse(resp.text) return batch['batchInfo']['id']