Last active
December 18, 2017 13:20
-
-
Save josuebrunel/ca2f8357b7ddfff6586af851be4e04d5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from dateutil.parser import parse as dateutil_parse | |
from lxml import etree, objectify as xobject | |
def is_clean(element): | |
if not element.getchildren() and element.text is None: | |
return False | |
return all(is_clean(child) for child in element.iterchildren()) | |
class BaseType(object): | |
"""Base data binding object | |
""" | |
tagname = None | |
namespace = None | |
nsmap = None | |
def __repr__(self): | |
return '<%s>' % self.tagname | |
@classmethod | |
def make_element(cls, tagname, value=None, namespace=None, nsmap=None): | |
M = xobject.ElementMaker(annotate=False, namespace=namespace, | |
nsmap=nsmap) | |
return M(tagname, value) | |
@property | |
def xml(self): | |
if isinstance(self, (ListType, DateType)): | |
return self.make_element(self.tagname, self.value, namespace=self.namespace) | |
tag = self.make_element(self.tagname, namespace=self.namespace, nsmap=self.nsmap) | |
for subelt in self.sequence: | |
attr = getattr(self, subelt, None) | |
if not attr: | |
continue | |
if isinstance(attr, (str, unicode)): | |
tag.append(self.make_element(subelt, attr, namespace=self.namespace)) | |
else: | |
xml = attr.xml | |
if not is_clean(xml): | |
continue | |
tag.append(xml) | |
xobject.deannotate(tag, xsi_nil=True) | |
return tag | |
def __str__(self): | |
return etree.tostring(self.xml, pretty_print=True) | |
class ListType(BaseType): | |
"""Data binding class for ListType | |
""" | |
allowed_values = None | |
def __init__(self, value): | |
if value not in self.allowed_values: | |
raise ValueError('<%s> value (%s) not in %s' % (self.tagname, value, | |
self.allowed_values)) | |
self.value = value | |
class DateType(BaseType): | |
def __init__(self, value): | |
self.value = dateutil_parse(value).date().isoformat() | |
class ComplexType(BaseType): | |
"""Data binding class for ComplexType | |
""" | |
sequence = None | |
# Couple example of Python objects | |
class Sex(ListType): | |
tagname = 'Sexe' | |
allowed_values = ('M', 'F') | |
class Credentials(ComplexType): | |
tagname = 'credentials' | |
sequence = ('login', 'password') | |
def __init__(self, data): | |
self.login = data['login'] | |
self.password = data['password'] | |
class Profile(ComplexType): | |
tagname = 'online' | |
sequence = ('url', 'credentials') | |
def __init__(self, data): | |
self.url = data['url'] | |
self.credentials = Credentials(data) | |
class Identity(ComplexType): | |
tagname = 'Identite' | |
sequence = ('firstname', 'lastname', 'birthdate') | |
def __init__(self, data): | |
self.firstname = data['firstname'] | |
self.lastname = data['lastname'] | |
self.birthdate = data['birthdate'] | |
class Address(ComplexType): | |
tagname = 'Adresse' | |
sequence = ('street', 'city', 'county', 'state', 'zipcode') | |
def __init__(self, data): | |
self.street = data['address_street'] | |
self.city = data['address_city'] | |
self.county = data['address_county'] | |
self.state = data['address_state'] | |
self.zipcode = data['address_zipcode'] | |
class Person(ComplexType): | |
tagname = 'Personne' | |
sequence = ('identity', 'sex', 'address', 'profile') | |
def __init__(self, data): | |
self.identity = Identity(data) | |
self.sex = Sex(data['sex']) | |
self.address = Address(data) | |
self.profile = Profile(data) | |
# Data | |
DATA = { | |
'firstname': 'Josh', | |
'lastname': 'Loking', | |
'sex': 'M', | |
'birthdate': '2000-11-11', | |
'address_street': 'Main Street G. Washington', | |
'address_city': 'Ravenhill', | |
'address_county': 'Orange', | |
'address_state': 'Tennesse', | |
'address_zipcode': '99999', | |
'url': 'https://twitter.com/t0k3n', | |
'login': 't0k3n@example.com', | |
'password': 'Hakarimashita' | |
} | |
if __name__ == '__main__': | |
person = Person(DATA) | |
print(person) |
josue%debian:~/workspace/reddit/pyobj2xml$python pyobject2xml.py
<Personne xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Identite>
<firstname>Josh</firstname>
<lastname>Loking</lastname>
<birthdate>2000-11-11</birthdate>
</Identite>
<Sexe>M</Sexe>
<Adresse>
<street>Main Street G. Washington</street>
<city>Ravenhill</city>
<county>Orange</county>
<state>Tennesse</state>
<zipcode>99999</zipcode>
</Adresse>
<online>
<url>https://twitter.com/t0k3n</url>
<credentials>
<login>t0k3n@example.com</login>
<password>Hakarimashita</password>
</credentials>
</online>
</Personne>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is the result