I might suggest declxml.
Full disclosure: I wrote this library because I was looking for a way to convert between XML and Python data structures without needing to write dozens of lines of imperative parsing/serialization code with ElementTree.
With declxml, you use processors to declaratively define the structure of your XML document and how to map between XML and Python data structures. Processors are used to for both serialization and parsing as well as for a basic level of validation.
Parsing into Python data structures is straightforward:
import declxml as xml
xml_string = """
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
"""
processor = xml.dictionary('foo', [
xml.dictionary('bar', [
xml.array(xml.integer('type', attribute='foobar'))
])
])
xml.parse_from_string(processor, xml_string)
Which produces the output:
{'bar': {'foobar': [1, 2]}}
You can also use the same processor to serialize data to XML
data = {'bar': {
'foobar': [7, 3, 21, 16, 11]
}}
xml.serialize_to_string(processor, data, indent=' ')
Which produces the following output
<?xml version="1.0" ?>
<foo>
<bar>
<type foobar="7"/>
<type foobar="3"/>
<type foobar="21"/>
<type foobar="16"/>
<type foobar="11"/>
</bar>
</foo>
If you want to work with objects instead of dictionaries, you can define processors to transform data to and from objects as well.
import declxml as xml
class Bar:
def __init__(self):
self.foobars = []
def __repr__(self):
return 'Bar(foobars={})'.format(self.foobars)
xml_string = """
<foo>
<bar>
<type foobar="1"/>
<type foobar="2"/>
</bar>
</foo>
"""
processor = xml.dictionary('foo', [
xml.user_object('bar', Bar, [
xml.array(xml.integer('type', attribute='foobar'), alias='foobars')
])
])
xml.parse_from_string(processor, xml_string)
Which produces the following output
{'bar': Bar(foobars=[1, 2])}