Pysxm
Simple Python XML Marshaller
Install / Use
/learn @josuebrunel/PysxmREADME
Simple XML Python Marshaller
.. image:: https://github.com/josuebrunel/pysxm/actions/workflows/python-app.yml/badge.svg :target: https://github.com/josuebrunel/pysxm/actions/workflows/python-app.yml .. image:: https://coveralls.io/repos/github/josuebrunel/pysxm/badge.svg?branch=master :target: https://coveralls.io/github/josuebrunel/pysxm?branch=master .. image:: http://pepy.tech/badge/pysxm :target: http://pepy.tech/count/pysxm
pysxm is a simple and extensible xml python marshaller. It comes with two simple and basic types:
- SimpleType
- ComplexType
It supports py2 and py3 and uses lxml.objectify under the hood.
Installation
.. code:: python
pip install pysxm
Quickstart
.. code:: python
In [1]: from pysxm import ComplexType
In [2]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: def __init__(self, fname, lname):
...: self.fname = fname
...: self.lname = lname
...:
In [3]: person = Person('token', 'black')
In [4]: print(person)
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<lname>black</lname>
<fname>token</fname>
</person>
Let's say, we want a different tag for our object. An attribute tagname or _tagname can be set to define the xml tag name of the object.
.. code:: python
In [5]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: tagname = 'student'
...: def __init__(self, fname, lname):
...: self.fname = fname
...: self.lname = lname
...:
In [6]: person = Person('token', 'black')
In [7]: print(person)
<student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<lname>black</lname>
<fname>token</fname>
</student>
A sequence or _sequence (tuple or list) attribute can be set to decide of the order or the presence of an subelement in the xml.
.. code:: python
In [8]: class Person(ComplexType):
...: attrib = {'description': 'a random person'}
...: tagname = 'student'
...: _sequence = ('city', 'fname')
...:
...: def __init__(self, fname, lname, city):
...: self.fname = fname
...: self.lname = lname
...: self.city = city
...:
In [9]: person = Person('token', 'black', 'south park')
In [10]: print(person)
<student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random person">
<city>south park</city>
<fname>token</fname>
</student>
Let's add a namespace to our object.
.. code:: python
In [11]: class Person(ComplexType):
...: attrib = {'description': 'a random south park character'}
...: nsmap = {'sp': 'http://southpark/xml/'}
...:
...: def __init__(self, fname, lname, city):
...: self.fname = fname
...: self.lname = lname
...: self.city = city
...:
In [12]: person = Person('token', 'black', 'south park')
In [13]: print(person)
<sp:person xmlns:sp="http://southpark/xml/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" description="a random south park character">
<sp:lname>black</sp:lname>
<sp:city>south park</sp:city>
<sp:fname>token</sp:fname>
</sp:person>
Let's make sure that a person's group is either coon or goth. To do so, we can inherit from SimpleType object and define a restriction by overriding check_restriction(self, value) method.
.. code:: python
In [7]: from pysxm import ComplexType, SimpleType
In [8]: class Group(SimpleType):
...: allowed_groups = ('coon', 'goth')
...: def check_restriction(self, value):
...: if value not in self.allowed_groups:
...: raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))
...:
In [9]: class Person(ComplexType):
...: def __init__(self, fname, lname, group):
...: self.fname = fname
...: self.lname = lname
...: self.group = Group(group)
...:
In [10]: Person('token', 'black', 'boys')
...
<ipython-input-8-116b49042116> in check_restriction(self, value)
3 def check_restriction(self, value):
4 if value not in self.allowed_groups:
----> 5 raise ValueError('<%s> value %s not in %s' % (self.tagname, value, self.allowed_groups))
6
ValueError: <group> value boys not in ('coon', 'goth')
In [11]: print(Person('token', 'black', 'goth'))
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<group>goth</group>
<fname>token</fname>
</person>
Note: ComplexType can have ComplexType and SimpleType as attribute
.. code:: python
from pysxm import ComplexType, SimpleType
class AdultAge(SimpleType):
tagname = 'age'
attrib = {'minvalue': '18', 'maxvalue': '100'}
def check_restriction(self, value):
if int(value) < 18:
raise ValueError("<%s> '%d' < 18" % (self.tagname, value))
class Credentials(ComplexType):
def __init__(self, login, password):
self.login = login
self.password = password
class Person(ComplexType):
def __init__(self, fname, lname, credentials, age):
self.fname = fname
self.lname = lname
self.credentials = Credentials(credentials['login'], credentials['password'])
self.age = AdultAge(age)
In [3]: data = {
...: 'fname': 'token', 'lname': 'black',
...: 'credentials': {'login': 't0ken', 'password': 'l33tolite'},
...: 'age': '30'}
In [4]: person = Person(**data)
In [5]: print(person)
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<credentials>
<login>t0ken</login>
<password>l33tolite</password>
</credentials>
<age maxvalue="100" minvalue="18">30</age>
<fname>token</fname>
</person>
In [6]: person.save('token.xml')
The save method (object.save(<filename>)) allows you to save the xml result into a file.
.. code:: python
In [7]: cat token.xml
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lname>black</lname>
<credentials>
<login>t0ken</login>
<password>l33tolite</password>
</credentials>
<age maxvalue="100" minvalue="18">30</age>
<fname>token</fname>
</person>
The ext module ^^^^^^^^^^^^^^
Pysxm comes with a couple of extended types. Those types are defined in pysxm.ext module.
DataComplexType """""""""""""""
This is a simple DataClass of ComplexType. Here is how you can set one up:
.. code:: python
from pysxm.ext import DataComplexType, XSimpleType
class Game(DataComplexType):
platform = XSimpleType('platform', ['xboxone', 'xboxx'], lambda v, av: v in av)
>>> game = Game(name='state of decay 2', editor='undead labs', platform='xboxone')
>>> print(game)
<game>
<name>state of decay 2</name>
<platform>xboxone</platform>
<editor>undead labs</editor>
</game>
XSimpleType """""""""""
It gets tiresome to subclass a SimpleType everytime you want to check a value. To overcome that, pysxm provides a descriptor called XSimpleType:
.. code:: python
class XSimpleType(object):
def __init__(name=None, restriction=None, checker=None, error_msg=None, **kwargs):
'''name: it's the name of the attribute.
restriction: self explanatory
checker: the fucntion that checks the input value
error_msg: message returned when checking fails
kwargs: as tagname, attrib or nsmap
'''
Here is an example:
.. code:: python
class XboxGamer(ComplexType):
platform = XSimpleType('platform', ('xone', 'xbox360', 'xbox'), lambda v, av: v in av)
score = XSimpleType('score', (4000, 1000000), lambda v, av: int(av[0]) <= int(v) < int(av[1]))
lastlogin = XDateTimeType('lastlogin')
def __init__(self, gamertag, platform, score, lastlogin):
self.gamertag = gamertag
self.platform = platform
self.score = score
self.lastlogin = lastlogin
In [1]: print(gamer_data)
{'gamertag': 'LokingHD', 'platform': 'ps4', 'score': '22526', 'lastlogin': '2018-03-21'}
In [2]: XboxGamer(**gamer_data)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-2-61f95466da46> in <module>()
----> 1 XboxGamer(**gamer_data)
/home/josue/workspace/dev/pysxdb/pysxm/ext.pyc in check(self, instance, value)
77 if not self.checker(value, self.restriction_values):
78 raise ValueError('tagname <%s> value %s is invalid: expected (%s)'
---> 79 % (instance.tagname, value, self.restriction_values))
80
81 def check_restriction(self, instance, value):
ValueError: tagname <xboxgamer> value ps4 is invalid: expected (('xone', 'xbox360', 'xbox'))
In [3]: gamer_data['platform'] = 'xone'
In [4]: gamer = XboxGamer(**gamer_data)
In [5]: print(gamer)
<xboxgamer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<gamertag>LokingHD</gamertag>
<platform>xone</platform>
<score>22526</score>
<lastlogin>2018-03-21T00:00:00</lastlogin>
</xboxgamer>
Most of the types defined in pysxm.ext are descriptors and they're subclassable.
Voila :wink:
Related Skills
node-connect
352.9kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
111.5kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
111.5kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
352.9kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
