Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-xmltodict for
openSUSE:Factory checked in at 2022-06-20 15:37:03
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-xmltodict (Old)
and /work/SRC/openSUSE:Factory/.python-xmltodict.new.1548 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-xmltodict"
Mon Jun 20 15:37:03 2022 rev:7 rq:983728 version:0.13.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-xmltodict/python-xmltodict.changes
2022-02-23 16:25:44.431507307 +0100
+++
/work/SRC/openSUSE:Factory/.python-xmltodict.new.1548/python-xmltodict.changes
2022-06-20 15:37:25.214872203 +0200
@@ -1,0 +2,17 @@
+Sun Jun 19 17:47:26 UTC 2022 - Dirk M??ller <[email protected]>
+
+- update to 0.13.0:
+ * Add install info to readme for openSUSE. (#205)
+ * Support defaultdict for namespace mapping (#211)
+ * parse(generator) is now possible (#212)
+ * Processing comments on parsing from xml to dict (connected to #109) (#221)
+ * Add expand_iter kw to unparse to expand iterables (#213)
+ * Fixed some typos
+ * Add support for python3.8
+ * Drop Jython/Python 2 and add Python 3.9/3.10.
+ * Drop OrderedDict in Python >= 3.7
+ * Do not use len() to determine if a sequence is empty
+ * Add more namespace attribute tests
+ * Fix encoding issue in setup.py
+
+-------------------------------------------------------------------
Old:
----
xmltodict-0.12.0.tar.gz
New:
----
xmltodict-0.13.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-xmltodict.spec ++++++
--- /var/tmp/diff_new_pack.BD12JL/_old 2022-06-20 15:37:25.714872934 +0200
+++ /var/tmp/diff_new_pack.BD12JL/_new 2022-06-20 15:37:25.718872939 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-xmltodict
-Version: 0.12.0
+Version: 0.13.0
Release: 0
Summary: Module to make XML working resemble JSON
License: MIT
++++++ xmltodict-0.12.0.tar.gz -> xmltodict-0.13.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/PKG-INFO
new/xmltodict-0.13.0/PKG-INFO
--- old/xmltodict-0.12.0/PKG-INFO 2019-02-11 08:00:08.000000000 +0100
+++ new/xmltodict-0.13.0/PKG-INFO 2022-05-08 08:59:52.086786000 +0200
@@ -1,232 +1,278 @@
Metadata-Version: 2.1
Name: xmltodict
-Version: 0.12.0
+Version: 0.13.0
Summary: Makes working with XML feel like you are working with JSON
Home-page: https://github.com/martinblech/xmltodict
Author: Martin Blech
Author-email: [email protected]
License: MIT
-Description: # xmltodict
-
- `xmltodict` is a Python module that makes working with XML feel like
you are working with [JSON](http://docs.python.org/library/json.html), as in
this
["spec"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):
-
- [](http://travis-ci.org/martinblech/xmltodict)
-
- ```python
- >>> 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 support
-
- By default, `xmltodict` does no XML namespace processing (it just
treats namespace declarations as regular node attributes), but passing
`process_namespaces=True` will make it expand namespaces for you:
-
- ```python
- >>> 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',
- ... }
- ... }
- True
- ```
-
- It also lets you collapse certain namespaces to shorthand prefixes, or
skip them altogether:
-
- ```python
- >>> 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',
- ... },
- ... }
- True
- ```
-
- ## Streaming mode
-
- `xmltodict` is very fast
([Expat](http://docs.python.org/library/pyexpat.html)-based) and has a
streaming mode with a small memory footprint, suitable for big XML dumps like
[Discogs](http://discogs.com/data/) or [Wikipedia](http://dumps.wikimedia.org/):
-
- ```python
- >>> def handle_artist(_, artist):
- ... print(artist['name'])
- ... return True
- >>>
- >>> xmltodict.parse(GzipFile('discogs_artists.xml.gz'),
- ... item_depth=2, item_callback=handle_artist)
- A Perfect Circle
- Fant??mas
- King Crimson
- Chris Potter
- ...
- ```
-
- It can also be used from the command line to pipe objects to a script
like this:
-
- ```python
- import sys, marshal
- while True:
- _, article = marshal.load(sys.stdin)
- print(article['title'])
- ```
-
- ```sh
- $ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | 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:
-
- ```sh
- $ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | gzip >
enwiki.dicts.gz
- ```
-
- And you reuse the dicts with every script that needs them:
-
- ```sh
- $ gunzip enwiki.dicts.gz | script1.py
- $ gunzip enwiki.dicts.gz | script2.py
- ...
- ```
-
- ## Roundtripping
-
- You can also convert in the other direction, using the `unparse()`
method:
-
- ```python
- >>> mydict = {
- ... 'response': {
- ... 'status': 'good',
- ... 'last_updated': '2014-02-16T23:10:12Z',
- ... }
- ... }
- >>> print(unparse(mydict, pretty=True))
- <?xml version="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 the `cdata_key` key in the
python dict, while node properties can be specified with the `attr_prefix`
prefixed to the key name in the python dict. The default value for
`attr_prefix` is `@` and the default value for `cdata_key` is `#text`.
-
- ```python
- >>> import xmltodict
- >>>
- >>> mydict = {
- ... 'text': {
- ... '@color':'red',
- ... '@stroke':'2',
- ... '#text':'This is a test'
- ... }
- ... }
- >>> print(xmltodict.unparse(mydict, pretty=True))
- <?xml version="1.0" encoding="utf-8"?>
- <text stroke="2" color="red">This is a test</text>
- ```
-
- ## Ok, how do I get it?
-
- ### Using pypi
-
- You just need to
-
- ```sh
- $ pip install xmltodict
- ```
-
- ### RPM-based distro (Fedora, RHEL, ???)
-
- There is an [official Fedora package for
xmltodict](https://apps.fedoraproject.org/packages/python-xmltodict).
-
- ```sh
- $ sudo yum install python-xmltodict
- ```
-
- ### Arch Linux
-
- There is an [official Arch Linux package for
xmltodict](https://www.archlinux.org/packages/community/any/python-xmltodict/).
-
- ```sh
- $ sudo pacman -S python-xmltodict
- ```
-
- ### Debian-based distro (Debian, Ubuntu, ???)
-
- There is an [official Debian package for
xmltodict](https://tracker.debian.org/pkg/python-xmltodict).
-
- ```sh
- $ sudo apt install python-xmltodict
- ```
-
- ### FreeBSD
-
- There is an [official FreeBSD port for
xmltodict](https://svnweb.freebsd.org/ports/head/devel/py-xmltodict/).
-
- ```sh
- $ pkg install py36-xmltodict
- ```
-
Platform: all
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: Implementation :: Jython
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Text Processing :: Markup :: XML
-Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+Requires-Python: >=3.4
Description-Content-Type: text/markdown
+License-File: LICENSE
+
+# xmltodict
+
+`xmltodict` is a Python module that makes working with XML feel like you are
working with [JSON](http://docs.python.org/library/json.html), as in this
["spec"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):
+
+[](https://travis-ci.com/martinblech/xmltodict)
+
+```python
+>>> 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 support
+
+By default, `xmltodict` does no XML namespace processing (it just treats
namespace declarations as regular node attributes), but passing
`process_namespaces=True` will make it expand namespaces for you:
+
+```python
+>>> 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',
+... }
+... }
+True
+```
+
+It also lets you collapse certain namespaces to shorthand prefixes, or skip
them altogether:
+
+```python
+>>> 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',
+... },
+... }
+True
+```
+
+## Streaming mode
+
+`xmltodict` is very fast
([Expat](http://docs.python.org/library/pyexpat.html)-based) and has a
streaming mode with a small memory footprint, suitable for big XML dumps like
[Discogs](http://discogs.com/data/) or [Wikipedia](http://dumps.wikimedia.org/):
+
+```python
+>>> def handle_artist(_, artist):
+... print(artist['name'])
+... return True
+>>>
+>>> xmltodict.parse(GzipFile('discogs_artists.xml.gz'),
+... item_depth=2, item_callback=handle_artist)
+A Perfect Circle
+Fant??mas
+King Crimson
+Chris Potter
+...
+```
+
+It can also be used from the command line to pipe objects to a script like
this:
+
+```python
+import sys, marshal
+while True:
+ _, article = marshal.load(sys.stdin)
+ print(article['title'])
+```
+
+```sh
+$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | 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:
+
+```sh
+$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | gzip >
enwiki.dicts.gz
+```
+
+And you reuse the dicts with every script that needs them:
+
+```sh
+$ gunzip enwiki.dicts.gz | script1.py
+$ gunzip enwiki.dicts.gz | script2.py
+...
+```
+
+## Roundtripping
+
+You can also convert in the other direction, using the `unparse()` method:
+
+```python
+>>> mydict = {
+... 'response': {
+... 'status': 'good',
+... 'last_updated': '2014-02-16T23:10:12Z',
+... }
+... }
+>>> print(unparse(mydict, pretty=True))
+<?xml version="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 the `cdata_key` key in the python
dict, while node properties can be specified with the `attr_prefix` prefixed to
the key name in the python dict. The default value for `attr_prefix` is `@` and
the default value for `cdata_key` is `#text`.
+
+```python
+>>> import xmltodict
+>>>
+>>> mydict = {
+... 'text': {
+... '@color':'red',
+... '@stroke':'2',
+... '#text':'This is a test'
+... }
+... }
+>>> print(xmltodict.unparse(mydict, pretty=True))
+<?xml version="1.0" encoding="utf-8"?>
+<text stroke="2" color="red">This is a test</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
the `expand_iter` keyword argument to provide a tag as demonstrated below. Note
that using `expand_iter` will break roundtripping.
+
+```python
+>>> mydict = {
+... "line": {
+... "points": [
+... [1, 5],
+... [2, 6],
+... ]
+... }
+... }
+>>> print(xmltodict.unparse(mydict, pretty=True))
+<?xml version="1.0" encoding="utf-8"?>
+<line>
+ <points>[1, 5]</points>
+ <points>[2, 6]</points>
+</line>
+>>> 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>
+```
+
+## Ok, how do I get it?
+
+### Using pypi
+
+You just need to
+
+```sh
+$ pip install xmltodict
+```
+
+### RPM-based distro (Fedora, RHEL, ???)
+
+There is an [official Fedora package for
xmltodict](https://apps.fedoraproject.org/packages/python-xmltodict).
+
+```sh
+$ sudo yum install python-xmltodict
+```
+
+### Arch Linux
+
+There is an [official Arch Linux package for
xmltodict](https://www.archlinux.org/packages/community/any/python-xmltodict/).
+
+```sh
+$ sudo pacman -S python-xmltodict
+```
+
+### Debian-based distro (Debian, Ubuntu, ???)
+
+There is an [official Debian package for
xmltodict](https://tracker.debian.org/pkg/python-xmltodict).
+
+```sh
+$ sudo apt install python-xmltodict
+```
+
+### FreeBSD
+
+There is an [official FreeBSD port for
xmltodict](https://svnweb.freebsd.org/ports/head/devel/py-xmltodict/).
+
+```sh
+$ pkg install py36-xmltodict
+```
+
+### openSUSE/SLE (SLE 15, Leap 15, Tumbleweed)
+
+There is an [official openSUSE package for
xmltodict](https://software.opensuse.org/package/python-xmltodict).
+
+```sh
+# Python2
+$ zypper in python2-xmltodict
+
+# Python3
+$ zypper in python3-xmltodict
+```
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/README.md
new/xmltodict-0.13.0/README.md
--- old/xmltodict-0.12.0/README.md 2019-02-11 07:36:33.000000000 +0100
+++ new/xmltodict-0.13.0/README.md 2019-12-08 10:15:13.000000000 +0100
@@ -2,7 +2,7 @@
`xmltodict` is a Python module that makes working with XML feel like you are
working with [JSON](http://docs.python.org/library/json.html), as in this
["spec"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):
-[](http://travis-ci.org/martinblech/xmltodict)
+[](https://travis-ci.com/martinblech/xmltodict)
```python
>>> print(json.dumps(xmltodict.parse("""
@@ -163,6 +163,37 @@
<text stroke="2" color="red">This is a test</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
the `expand_iter` keyword argument to provide a tag as demonstrated below. Note
that using `expand_iter` will break roundtripping.
+
+```python
+>>> mydict = {
+... "line": {
+... "points": [
+... [1, 5],
+... [2, 6],
+... ]
+... }
+... }
+>>> print(xmltodict.unparse(mydict, pretty=True))
+<?xml version="1.0" encoding="utf-8"?>
+<line>
+ <points>[1, 5]</points>
+ <points>[2, 6]</points>
+</line>
+>>> 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>
+```
+
## Ok, how do I get it?
### Using pypi
@@ -204,3 +235,15 @@
```sh
$ pkg install py36-xmltodict
```
+
+### openSUSE/SLE (SLE 15, Leap 15, Tumbleweed)
+
+There is an [official openSUSE package for
xmltodict](https://software.opensuse.org/package/python-xmltodict).
+
+```sh
+# Python2
+$ zypper in python2-xmltodict
+
+# Python3
+$ zypper in python3-xmltodict
+```
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/setup.py
new/xmltodict-0.13.0/setup.py
--- old/xmltodict-0.12.0/setup.py 2019-02-11 07:36:33.000000000 +0100
+++ new/xmltodict-0.13.0/setup.py 2022-05-08 08:49:17.000000000 +0200
@@ -8,8 +8,8 @@
import xmltodict
-with open('README.md') as f:
- long_description = f.read()
+with open('README.md', 'rb') as f:
+ long_description = f.read().decode('utf-8')
setup(name='xmltodict',
@@ -22,23 +22,23 @@
url='https://github.com/martinblech/xmltodict',
license=xmltodict.__license__,
platforms=['all'],
- python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
+ python_requires='>=3.4',
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python',
- 'Programming Language :: Python :: 2',
- 'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
- 'Programming Language :: Python :: Implementation :: Jython',
+ 'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Text Processing :: Markup :: XML',
],
py_modules=['xmltodict'],
- tests_require=['nose>=1.0', 'coverage'],
+ tests_require=['nose2', 'coverage'],
)
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_dicttoxml.cpython-310.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_dicttoxml.cpython-310.pyc differ
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_dicttoxml.cpython-37.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_dicttoxml.cpython-37.pyc differ
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_dicttoxml.cpython-39.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_dicttoxml.cpython-39.pyc differ
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_xmltodict.cpython-310.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_xmltodict.cpython-310.pyc differ
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_xmltodict.cpython-37.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_xmltodict.cpython-37.pyc differ
Binary files
old/xmltodict-0.12.0/tests/__pycache__/test_xmltodict.cpython-39.pyc and
new/xmltodict-0.13.0/tests/__pycache__/test_xmltodict.cpython-39.pyc differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/tests/test_dicttoxml.py
new/xmltodict-0.13.0/tests/test_dicttoxml.py
--- old/xmltodict-0.12.0/tests/test_dicttoxml.py 2019-02-11
07:36:33.000000000 +0100
+++ new/xmltodict-0.13.0/tests/test_dicttoxml.py 2019-12-08
10:15:13.000000000 +0100
@@ -46,6 +46,14 @@
self.assertEqual(obj, parse(unparse(obj)))
self.assertEqual(unparse(obj), unparse(parse(unparse(obj))))
+ def test_list_expand_iter(self):
+ obj = {'a': {'b': [['1', '2'], ['3',]]}}
+ #self.assertEqual(obj, parse(unparse(obj, expand_iter="item")))
+ exp_xml = dedent('''\
+ <?xml version="1.0" encoding="utf-8"?>
+ <a><b><item>1</item><item>2</item></b><b><item>3</item></b></a>''')
+ self.assertEqual(exp_xml, unparse(obj, expand_iter="item"))
+
def test_generator(self):
obj = {'a': {'b': ['1', '2', '3']}}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/tests/test_xmltodict.py
new/xmltodict-0.13.0/tests/test_xmltodict.py
--- old/xmltodict-0.12.0/tests/test_xmltodict.py 2019-02-11
07:36:33.000000000 +0100
+++ new/xmltodict-0.13.0/tests/test_xmltodict.py 2022-05-08
08:49:17.000000000 +0200
@@ -1,4 +1,5 @@
from xmltodict import parse, ParsingInterrupted
+import collections
import unittest
try:
@@ -119,6 +120,17 @@
parse, '<a>x</a>',
item_depth=1, item_callback=cb)
+ def test_streaming_generator(self):
+ def cb(path, item):
+ cb.count += 1
+ self.assertEqual(path, [('a', {'x': 'y'}), ('b', None)])
+ self.assertEqual(item, str(cb.count))
+ return True
+ cb.count = 0
+ parse((n for n in '<a x="y"><b>1</b><b>2</b><b>3</b></a>'),
+ item_depth=2, item_callback=cb)
+ self.assertEqual(cb.count, 3)
+
def test_postprocessor(self):
def postprocessor(path, key, value):
try:
@@ -171,7 +183,8 @@
xml = """
<root xmlns="http://defaultns.com/"
xmlns:a="http://a.com/"
- xmlns:b="http://b.com/">
+ xmlns:b="http://b.com/"
+ version="1.00">
<x a:attr="val">1</x>
<a:y>2</a:y>
<b:z>3</b:z>
@@ -179,12 +192,13 @@
"""
d = {
'http://defaultns.com/:root': {
+ '@version': '1.00',
+ '@xmlns': {
+ '': 'http://defaultns.com/',
+ 'a': 'http://a.com/',
+ 'b': 'http://b.com/',
+ },
'http://defaultns.com/:x': {
- '@xmlns': {
- '': 'http://defaultns.com/',
- 'a': 'http://a.com/',
- 'b': 'http://b.com/',
- },
'@http://a.com/:attr': 'val',
'#text': '1',
},
@@ -199,7 +213,8 @@
xml = """
<root xmlns="http://defaultns.com/"
xmlns:a="http://a.com/"
- xmlns:b="http://b.com/">
+ xmlns:b="http://b.com/"
+ version="1.00">
<x a:attr="val">1</x>
<a:y>2</a:y>
<b:z>3</b:z>
@@ -211,12 +226,13 @@
}
d = {
'root': {
+ '@version': '1.00',
+ '@xmlns': {
+ '': 'http://defaultns.com/',
+ 'a': 'http://a.com/',
+ 'b': 'http://b.com/',
+ },
'x': {
- '@xmlns': {
- '': 'http://defaultns.com/',
- 'a': 'http://a.com/',
- 'b': 'http://b.com/',
- },
'@ns_a:attr': 'val',
'#text': '1',
},
@@ -227,11 +243,43 @@
res = parse(xml, process_namespaces=True, namespaces=namespaces)
self.assertEqual(res, d)
+ def test_namespace_collapse_all(self):
+ xml = """
+ <root xmlns="http://defaultns.com/"
+ xmlns:a="http://a.com/"
+ xmlns:b="http://b.com/"
+ version="1.00">
+ <x a:attr="val">1</x>
+ <a:y>2</a:y>
+ <b:z>3</b:z>
+ </root>
+ """
+ namespaces = collections.defaultdict(lambda: None)
+ d = {
+ 'root': {
+ '@version': '1.00',
+ '@xmlns': {
+ '': 'http://defaultns.com/',
+ 'a': 'http://a.com/',
+ 'b': 'http://b.com/',
+ },
+ 'x': {
+ '@attr': 'val',
+ '#text': '1',
+ },
+ 'y': '2',
+ 'z': '3',
+ },
+ }
+ res = parse(xml, process_namespaces=True, namespaces=namespaces)
+ self.assertEqual(res, d)
+
def test_namespace_ignore(self):
xml = """
<root xmlns="http://defaultns.com/"
xmlns:a="http://a.com/"
- xmlns:b="http://b.com/">
+ xmlns:b="http://b.com/"
+ version="1.00">
<x>1</x>
<a:y>2</a:y>
<b:z>3</b:z>
@@ -242,6 +290,7 @@
'@xmlns': 'http://defaultns.com/',
'@xmlns:a': 'http://a.com/',
'@xmlns:b': 'http://b.com/',
+ '@version': '1.00',
'x': '1',
'a:y': '2',
'b:z': '3',
@@ -380,3 +429,31 @@
else:
self.assertTrue(False)
expat.ParserCreate = ParserCreate
+
+ def test_comments(self):
+ xml = """
+ <a>
+ <b>
+ <!-- b comment -->
+ <c>
+ <!-- c comment -->
+ 1
+ </c>
+ <d>2</d>
+ </b>
+ </a>
+ """
+ expectedResult = {
+ 'a': {
+ 'b': {
+ '#comment': 'b comment',
+ 'c': {
+
+ '#comment': 'c comment',
+ '#text': '1',
+ },
+ 'd': '2',
+ },
+ }
+ }
+ self.assertEqual(parse(xml, process_comments=True), expectedResult)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/xmltodict.egg-info/PKG-INFO
new/xmltodict-0.13.0/xmltodict.egg-info/PKG-INFO
--- old/xmltodict-0.12.0/xmltodict.egg-info/PKG-INFO 2019-02-11
08:00:08.000000000 +0100
+++ new/xmltodict-0.13.0/xmltodict.egg-info/PKG-INFO 2022-05-08
08:59:51.000000000 +0200
@@ -1,232 +1,278 @@
Metadata-Version: 2.1
Name: xmltodict
-Version: 0.12.0
+Version: 0.13.0
Summary: Makes working with XML feel like you are working with JSON
Home-page: https://github.com/martinblech/xmltodict
Author: Martin Blech
Author-email: [email protected]
License: MIT
-Description: # xmltodict
-
- `xmltodict` is a Python module that makes working with XML feel like
you are working with [JSON](http://docs.python.org/library/json.html), as in
this
["spec"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):
-
- [](http://travis-ci.org/martinblech/xmltodict)
-
- ```python
- >>> 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 support
-
- By default, `xmltodict` does no XML namespace processing (it just
treats namespace declarations as regular node attributes), but passing
`process_namespaces=True` will make it expand namespaces for you:
-
- ```python
- >>> 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',
- ... }
- ... }
- True
- ```
-
- It also lets you collapse certain namespaces to shorthand prefixes, or
skip them altogether:
-
- ```python
- >>> 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',
- ... },
- ... }
- True
- ```
-
- ## Streaming mode
-
- `xmltodict` is very fast
([Expat](http://docs.python.org/library/pyexpat.html)-based) and has a
streaming mode with a small memory footprint, suitable for big XML dumps like
[Discogs](http://discogs.com/data/) or [Wikipedia](http://dumps.wikimedia.org/):
-
- ```python
- >>> def handle_artist(_, artist):
- ... print(artist['name'])
- ... return True
- >>>
- >>> xmltodict.parse(GzipFile('discogs_artists.xml.gz'),
- ... item_depth=2, item_callback=handle_artist)
- A Perfect Circle
- Fant??mas
- King Crimson
- Chris Potter
- ...
- ```
-
- It can also be used from the command line to pipe objects to a script
like this:
-
- ```python
- import sys, marshal
- while True:
- _, article = marshal.load(sys.stdin)
- print(article['title'])
- ```
-
- ```sh
- $ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | 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:
-
- ```sh
- $ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | gzip >
enwiki.dicts.gz
- ```
-
- And you reuse the dicts with every script that needs them:
-
- ```sh
- $ gunzip enwiki.dicts.gz | script1.py
- $ gunzip enwiki.dicts.gz | script2.py
- ...
- ```
-
- ## Roundtripping
-
- You can also convert in the other direction, using the `unparse()`
method:
-
- ```python
- >>> mydict = {
- ... 'response': {
- ... 'status': 'good',
- ... 'last_updated': '2014-02-16T23:10:12Z',
- ... }
- ... }
- >>> print(unparse(mydict, pretty=True))
- <?xml version="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 the `cdata_key` key in the
python dict, while node properties can be specified with the `attr_prefix`
prefixed to the key name in the python dict. The default value for
`attr_prefix` is `@` and the default value for `cdata_key` is `#text`.
-
- ```python
- >>> import xmltodict
- >>>
- >>> mydict = {
- ... 'text': {
- ... '@color':'red',
- ... '@stroke':'2',
- ... '#text':'This is a test'
- ... }
- ... }
- >>> print(xmltodict.unparse(mydict, pretty=True))
- <?xml version="1.0" encoding="utf-8"?>
- <text stroke="2" color="red">This is a test</text>
- ```
-
- ## Ok, how do I get it?
-
- ### Using pypi
-
- You just need to
-
- ```sh
- $ pip install xmltodict
- ```
-
- ### RPM-based distro (Fedora, RHEL, ???)
-
- There is an [official Fedora package for
xmltodict](https://apps.fedoraproject.org/packages/python-xmltodict).
-
- ```sh
- $ sudo yum install python-xmltodict
- ```
-
- ### Arch Linux
-
- There is an [official Arch Linux package for
xmltodict](https://www.archlinux.org/packages/community/any/python-xmltodict/).
-
- ```sh
- $ sudo pacman -S python-xmltodict
- ```
-
- ### Debian-based distro (Debian, Ubuntu, ???)
-
- There is an [official Debian package for
xmltodict](https://tracker.debian.org/pkg/python-xmltodict).
-
- ```sh
- $ sudo apt install python-xmltodict
- ```
-
- ### FreeBSD
-
- There is an [official FreeBSD port for
xmltodict](https://svnweb.freebsd.org/ports/head/devel/py-xmltodict/).
-
- ```sh
- $ pkg install py36-xmltodict
- ```
-
Platform: all
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: Implementation :: Jython
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Text Processing :: Markup :: XML
-Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*
+Requires-Python: >=3.4
Description-Content-Type: text/markdown
+License-File: LICENSE
+
+# xmltodict
+
+`xmltodict` is a Python module that makes working with XML feel like you are
working with [JSON](http://docs.python.org/library/json.html), as in this
["spec"](http://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html):
+
+[](https://travis-ci.com/martinblech/xmltodict)
+
+```python
+>>> 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 support
+
+By default, `xmltodict` does no XML namespace processing (it just treats
namespace declarations as regular node attributes), but passing
`process_namespaces=True` will make it expand namespaces for you:
+
+```python
+>>> 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',
+... }
+... }
+True
+```
+
+It also lets you collapse certain namespaces to shorthand prefixes, or skip
them altogether:
+
+```python
+>>> 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',
+... },
+... }
+True
+```
+
+## Streaming mode
+
+`xmltodict` is very fast
([Expat](http://docs.python.org/library/pyexpat.html)-based) and has a
streaming mode with a small memory footprint, suitable for big XML dumps like
[Discogs](http://discogs.com/data/) or [Wikipedia](http://dumps.wikimedia.org/):
+
+```python
+>>> def handle_artist(_, artist):
+... print(artist['name'])
+... return True
+>>>
+>>> xmltodict.parse(GzipFile('discogs_artists.xml.gz'),
+... item_depth=2, item_callback=handle_artist)
+A Perfect Circle
+Fant??mas
+King Crimson
+Chris Potter
+...
+```
+
+It can also be used from the command line to pipe objects to a script like
this:
+
+```python
+import sys, marshal
+while True:
+ _, article = marshal.load(sys.stdin)
+ print(article['title'])
+```
+
+```sh
+$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | 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:
+
+```sh
+$ bunzip2 enwiki-pages-articles.xml.bz2 | xmltodict.py 2 | gzip >
enwiki.dicts.gz
+```
+
+And you reuse the dicts with every script that needs them:
+
+```sh
+$ gunzip enwiki.dicts.gz | script1.py
+$ gunzip enwiki.dicts.gz | script2.py
+...
+```
+
+## Roundtripping
+
+You can also convert in the other direction, using the `unparse()` method:
+
+```python
+>>> mydict = {
+... 'response': {
+... 'status': 'good',
+... 'last_updated': '2014-02-16T23:10:12Z',
+... }
+... }
+>>> print(unparse(mydict, pretty=True))
+<?xml version="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 the `cdata_key` key in the python
dict, while node properties can be specified with the `attr_prefix` prefixed to
the key name in the python dict. The default value for `attr_prefix` is `@` and
the default value for `cdata_key` is `#text`.
+
+```python
+>>> import xmltodict
+>>>
+>>> mydict = {
+... 'text': {
+... '@color':'red',
+... '@stroke':'2',
+... '#text':'This is a test'
+... }
+... }
+>>> print(xmltodict.unparse(mydict, pretty=True))
+<?xml version="1.0" encoding="utf-8"?>
+<text stroke="2" color="red">This is a test</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
the `expand_iter` keyword argument to provide a tag as demonstrated below. Note
that using `expand_iter` will break roundtripping.
+
+```python
+>>> mydict = {
+... "line": {
+... "points": [
+... [1, 5],
+... [2, 6],
+... ]
+... }
+... }
+>>> print(xmltodict.unparse(mydict, pretty=True))
+<?xml version="1.0" encoding="utf-8"?>
+<line>
+ <points>[1, 5]</points>
+ <points>[2, 6]</points>
+</line>
+>>> 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>
+```
+
+## Ok, how do I get it?
+
+### Using pypi
+
+You just need to
+
+```sh
+$ pip install xmltodict
+```
+
+### RPM-based distro (Fedora, RHEL, ???)
+
+There is an [official Fedora package for
xmltodict](https://apps.fedoraproject.org/packages/python-xmltodict).
+
+```sh
+$ sudo yum install python-xmltodict
+```
+
+### Arch Linux
+
+There is an [official Arch Linux package for
xmltodict](https://www.archlinux.org/packages/community/any/python-xmltodict/).
+
+```sh
+$ sudo pacman -S python-xmltodict
+```
+
+### Debian-based distro (Debian, Ubuntu, ???)
+
+There is an [official Debian package for
xmltodict](https://tracker.debian.org/pkg/python-xmltodict).
+
+```sh
+$ sudo apt install python-xmltodict
+```
+
+### FreeBSD
+
+There is an [official FreeBSD port for
xmltodict](https://svnweb.freebsd.org/ports/head/devel/py-xmltodict/).
+
+```sh
+$ pkg install py36-xmltodict
+```
+
+### openSUSE/SLE (SLE 15, Leap 15, Tumbleweed)
+
+There is an [official openSUSE package for
xmltodict](https://software.opensuse.org/package/python-xmltodict).
+
+```sh
+# Python2
+$ zypper in python2-xmltodict
+
+# Python3
+$ zypper in python3-xmltodict
+```
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/xmltodict.egg-info/SOURCES.txt
new/xmltodict-0.13.0/xmltodict.egg-info/SOURCES.txt
--- old/xmltodict-0.12.0/xmltodict.egg-info/SOURCES.txt 2019-02-11
08:00:08.000000000 +0100
+++ new/xmltodict-0.13.0/xmltodict.egg-info/SOURCES.txt 2022-05-08
08:59:52.000000000 +0200
@@ -7,6 +7,12 @@
xmltodict.py
tests/test_dicttoxml.py
tests/test_xmltodict.py
+tests/__pycache__/test_dicttoxml.cpython-310.pyc
+tests/__pycache__/test_dicttoxml.cpython-37.pyc
+tests/__pycache__/test_dicttoxml.cpython-39.pyc
+tests/__pycache__/test_xmltodict.cpython-310.pyc
+tests/__pycache__/test_xmltodict.cpython-37.pyc
+tests/__pycache__/test_xmltodict.cpython-39.pyc
xmltodict.egg-info/PKG-INFO
xmltodict.egg-info/SOURCES.txt
xmltodict.egg-info/dependency_links.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/xmltodict-0.12.0/xmltodict.py
new/xmltodict-0.13.0/xmltodict.py
--- old/xmltodict-0.12.0/xmltodict.py 2019-02-11 07:57:59.000000000 +0100
+++ new/xmltodict-0.13.0/xmltodict.py 2022-05-08 08:49:17.000000000 +0200
@@ -15,7 +15,12 @@
except ImportError:
from io import StringIO
-from collections import OrderedDict
+_dict = dict
+import platform
+if tuple(map(int, platform.python_version_tuple()[:2])) < (3, 7):
+ from collections import OrderedDict as _dict
+
+from inspect import isgenerator
try: # pragma no cover
_basestring = basestring
@@ -27,7 +32,7 @@
_unicode = str
__author__ = 'Martin Blech'
-__version__ = '0.12.0'
+__version__ = '0.13.0'
__license__ = 'MIT'
@@ -45,11 +50,12 @@
force_cdata=False,
cdata_separator='',
postprocessor=None,
- dict_constructor=OrderedDict,
+ dict_constructor=_dict,
strip_whitespace=True,
namespace_separator=':',
namespaces=None,
- force_list=None):
+ force_list=None,
+ comment_key='#comment'):
self.path = []
self.stack = []
self.data = []
@@ -66,17 +72,21 @@
self.strip_whitespace = strip_whitespace
self.namespace_separator = namespace_separator
self.namespaces = namespaces
- self.namespace_declarations = OrderedDict()
+ self.namespace_declarations = dict_constructor()
self.force_list = force_list
+ self.comment_key = comment_key
def _build_name(self, full_name):
- if not self.namespaces:
+ if self.namespaces is None:
return full_name
i = full_name.rfind(self.namespace_separator)
if i == -1:
return full_name
namespace, name = full_name[:i], full_name[i+1:]
- short_namespace = self.namespaces.get(namespace, namespace)
+ try:
+ short_namespace = self.namespaces[namespace]
+ except KeyError:
+ short_namespace = namespace
if not short_namespace:
return name
else:
@@ -95,7 +105,7 @@
attrs = self._attrs_to_dict(attrs)
if attrs and self.namespace_declarations:
attrs['xmlns'] = self.namespace_declarations
- self.namespace_declarations = OrderedDict()
+ self.namespace_declarations = self.dict_constructor()
self.path.append((name, attrs or None))
if len(self.path) > self.item_depth:
self.stack.append((self.item, self.data))
@@ -126,7 +136,7 @@
should_continue = self.item_callback(self.path, item)
if not should_continue:
raise ParsingInterrupted()
- if len(self.stack):
+ if self.stack:
data = (None if not self.data
else self.cdata_separator.join(self.data))
item = self.item
@@ -152,6 +162,11 @@
else:
self.data.append(data)
+ def comments(self, data):
+ if self.strip_whitespace:
+ data = data.strip()
+ self.item = self.push_data(self.item, self.comment_key, data)
+
def push_data(self, item, key, data):
if self.postprocessor is not None:
result = self.postprocessor(self.path, key, data)
@@ -185,10 +200,10 @@
def parse(xml_input, encoding=None, expat=expat, process_namespaces=False,
- namespace_separator=':', disable_entities=True, **kwargs):
+ namespace_separator=':', disable_entities=True,
process_comments=False, **kwargs):
"""Parse the given XML input and convert it into a dictionary.
- `xml_input` can either be a `string` or a file-like object.
+ `xml_input` can either be a `string`, a file-like object, or a generator
of strings.
If `xml_attribs` is `True`, element attributes are put in the dictionary
among regular child elements, using `@` as a prefix to avoid collisions. If
@@ -243,21 +258,21 @@
... 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')]))])
+ {'a': {'b:int': [1, 2], 'b': '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')])
+ {'a': '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. The
force_list argument is a tuple of keys. If the key for a given level
of hierarchy is in the force_list argument, that level of hierarchy
will have a list as a child (even if there is only one sub-element).
- The index_keys operation takes precendence over this. This is applied
+ The index_keys operation takes precedence over this. This is applied
after any user-supplied postprocessor has already run.
For example, given this input:
@@ -287,6 +302,36 @@
`force_list` can also be a callable that receives `path`, `key` and
`value`. This is helpful in cases where the logic that decides whether
a list should be forced is more complex.
+
+
+ If `process_comment` is `True` then comment will be added with
comment_key
+ (default=`'#comment'`) to then tag which contains comment
+
+ For example, given this input:
+ <a>
+ <b>
+ <!-- b comment -->
+ <c>
+ <!-- c comment -->
+ 1
+ </c>
+ <d>2</d>
+ </b>
+ </a>
+
+ If called with process_comment=True, it will produce
+ this dictionary:
+ 'a': {
+ 'b': {
+ '#comment': 'b comment',
+ 'c': {
+
+ '#comment': 'c comment',
+ '#text': '1',
+ },
+ 'd': '2',
+ },
+ }
"""
handler = _DictSAXHandler(namespace_separator=namespace_separator,
**kwargs)
@@ -309,6 +354,8 @@
parser.StartElementHandler = handler.startElement
parser.EndElementHandler = handler.endElement
parser.CharacterDataHandler = handler.characters
+ if process_comments:
+ parser.CommentHandler = handler.comments
parser.buffer_text = True
if disable_entities:
try:
@@ -323,6 +370,10 @@
parser.ExternalEntityRefHandler = lambda *x: 1
if hasattr(xml_input, 'read'):
parser.ParseFile(xml_input)
+ elif isgenerator(xml_input):
+ for chunk in xml_input:
+ parser.Parse(chunk,False)
+ parser.Parse(b'',True)
else:
parser.Parse(xml_input, True)
return handler.item
@@ -353,7 +404,8 @@
indent='\t',
namespace_separator=':',
namespaces=None,
- full_document=True):
+ full_document=True,
+ expand_iter=None):
key = _process_namespace(key, namespaces, namespace_separator, attr_prefix)
if preprocessor is not None:
result = preprocessor(key, value)
@@ -368,18 +420,21 @@
if full_document and depth == 0 and index > 0:
raise ValueError('document with multiple roots')
if v is None:
- v = OrderedDict()
+ v = _dict()
elif isinstance(v, bool):
if v:
v = _unicode('true')
else:
v = _unicode('false')
elif not isinstance(v, dict):
- v = _unicode(v)
+ if expand_iter and hasattr(v, '__iter__') and not isinstance(v,
_basestring):
+ v = _dict(((expand_iter, v),))
+ else:
+ v = _unicode(v)
if isinstance(v, _basestring):
- v = OrderedDict(((cdata_key, v),))
+ v = _dict(((cdata_key, v),))
cdata = None
- attrs = OrderedDict()
+ attrs = _dict()
children = []
for ik, iv in v.items():
if ik == cdata_key:
@@ -407,7 +462,8 @@
_emit(child_key, child_value, content_handler,
attr_prefix, cdata_key, depth+1, preprocessor,
pretty, newl, indent, namespaces=namespaces,
- namespace_separator=namespace_separator)
+ namespace_separator=namespace_separator,
+ expand_iter=expand_iter)
if cdata is not None:
content_handler.characters(cdata)
if pretty and children: