2.3.20.2. Content¶
This module provides XML serialization/deserialization features.
It is intented to provide a way to define python classes able to load/save data from/to XML elements, strings or files. The idea is to make a close but non restrictive link between XML and Python objects models with the least possible effort.
Below is an example to briefly introduce how to use this module. This could be simplified because there are shortcuts for default type, values and other stuff but we will be as explicit as possible to demonstrate how this module work.
Suppose you have or want the following XML syntax:
<Report>
<MapFigure showgrid="True" output="meteo.png">
<Title>Temperature and Wind</Title>
<BoundingBox lonmin="-10" lonmax="10" latmin="40" latmax="60">
<ColorBar levels="0,5,10,15,20,25,30"/>
<Data file="/path/to/data/file" variable="temperature"/>
<Data file="/path/to/data/file" variable="wind" plot="windbarbs"/>
</Map>
</Report>
This can be serialized with the following python definitions:
class BoundingBox(XmlConfig):
xml_attributes = {
'lonmin':{type:float, default:-180},
'lonmax':{type:float, default:180},
'latmin':{type:float, default:-90},
'latmax':{type:float, default:90},
}
def parseFloatList(floatListString):
return map(float, floatListString.split(','))
class ColorBar(XmlConfig):
xml_attributes = {
'levels':{type:parseFloatList, default:[0, 10, 20, 30]},
}
class Data(XmlConfig):
xml_attributes = {
'file':{type:unicode, default:None},
'variable':{type:unicode, default:None},
'plot':{type=unicode, default:'fillcolor'},
}
class MapFigure(XmlConfig):
xml_attributes = {
'showgrid':{type:bool, default:False},
'temperature':{type:unicode, default:'output.png'},
}
xml_childnodes = {
'boundingBox':{'type':BoundingBox, single:True},
'colorBar':{'type':BoundingBox, single:True},
'data':{'type':Data},
}
xml_textnodes = {
'title':{'type':unicode, 'tagName':'Title', single:True},
}
class Report(XmlConfig):
xml_childnodes = {
'mapFigures':{type:MapFigure},
}
To load a file ‘report.xml’ containing the XML code above, you can either do:
r = Report()
r.load_xml_file('report.xml')
or
r = Report.from_xml_file('report.xml')
To save a xml file from the loaded object above you can do:
r.save_xml_file('report.xml')
Warning
- This module make use of xml.etree.ElementTree and works with python >= 2.6.
- Some XML functionnalities are not handled, there is no namespace support although namespaces can be ignored when loading XML data. When specifying an attribute name as ‘namespace:name’ the namespace is ignored when loading but is kept when saving.
- When loading a list of elements into a dictionnary (e.g. using an attribute value as key), the order will be kept if the module collections.OrderedDict is available (python > 2.7)
-
class
XmlConfig
(*args, **kwargs)[source]¶ Bases:
object
Base class for XML serializations/deserializations.
- Subclasses can define the following class attributes which define the serialization specifications:
- xml_tag_name: The corresponding xml element name (default is the class name formatted by
xml_element_name()
). - xml_attributes: Attribute specifications, see
load_xml_attributes()
- xml_childnodes: Children elements specifications, see
load_xml_childnodes()
- xml_textnodes: Text children elements specifications, see
load_xml_textnodes()
- xml_tag_name: The corresponding xml element name (default is the class name formatted by
These attributes can also be passed as named arguments to the constructor to extend or overwrite those declared in the class definition.
XML attributes, childnodes and textnodes are stored in this instance (object) attributes.
-
classmethod
from_url
(url, *a, **k)[source]¶ Factory method instanciating from xml string returned by url.
-
set_current_file
(f)[source]¶ Set the currently used xml file. This method automatically called when loading/saving xml file
-
classmethod
tag_name
()[source]¶ Return the xml element name for this class or instance. If cls.xml_tag_name is not set, return class name formatted by
xml_element_name()
-
to_xml_stream
(stream, pretty=True, indent=' ', encoding='UTF-8', **kwargs)[source]¶ Dump object to a file object like stream.
-
xml_attributes
= {}¶
-
xml_childnodes
= {}¶
-
xml_tag_name
= ''¶
-
xml_textnodes
= {}¶
-
class
XmlConfigDict
(*args, **kwargs)[source]¶ Bases:
collections.OrderedDict
,vacumm.misc.xml.XmlConfig
Convenient class inheriting Dict and XmlConfig to avoid metaclasses conflict when Dict is collections.OrderedDict
-
class
XmlConfigList
(*args, **kwargs)[source]¶ Bases:
list
,vacumm.misc.xml.XmlConfig
Convenient class inheriting list and XmlConfig
-
class
XmlConfigMetaClass
[source]¶ Bases:
type
Metaclass used to pass the xml element from XmlConfig.from_xml_elt to XmlConfig.__init__. This allow XmlConfig descendants to use the loaded data in their __init__ straight after XmlConfig.__init__ have been called
If your implementation already inherit from a metaclass based class, you may use the code at: http://code.activestate.com/recipes/204197-solving-the-metaclass-conflict/
-
create_xml_element
(name, attributes=None, childnodes=None, skipNone=True, **kwargs)[source]¶ Create an xml element with given attributes and children
Params: - name: the element tag name
- attributes, optional: dict of attributes name:value
- childnodes, optional: list/tuple/dict of ElementTree.Element object
- skipNone, optional: skip attributes which value is None
Return: a ElementTree.Element object
-
findchildren
(elt, name)[source]¶ Find children of an element ignoring namespaces
Params: - elt: element to search in
- name: searched element tag name
Return: a generator on ElementTree.Element objects
-
getattribute
(elt, name, default=None)[source]¶ Get the attribute value of an element ignoring namespaces
Params: - elt: element to search in
- name: searched attribute name
- default, optional: default value when elt has no such attribute
Return: attribute value or default
-
hasattribute
(elt, name)[source]¶ Check the presence of an element attribute ignoring namespaces
Params: - elt: element to search in
- name: searched attribute name
Return: boolean
-
load_xml_attributes
(elt=None, attributes=None, dst=None, create=False)[source]¶ Deserialize attributes from an element
Params: - elt: element to search in
- attributes: specification for attributes deserialization
- This may be either:
- a list of attribute names
- a dict of attributes {name:spec, …} with name as a string and spec as:
- a type function
- a list or tuple (type function, default value)
- a dict {‘type’:function, ‘default’:value}
- dst: an object that will be populated with the attributes
- create: whether to create attributes in dst with the default value when they are not in elt
The type must be a callable taking the attribute value as single string argument and returning the converted value With no type function, attributes are loaded without modification (as string)
Return: dict of deserialized attributes
-
load_xml_childnodes
(elt=None, childnodes=None, dst=None, create=False)[source]¶ Deserialize children from an element
Params: - elt: element to search in
- childnodes: specification for children deserialization
- This must be a dict of object attribute {name:spec, …} with name as a string and spec as:
- a type function
- a list or tuple (type function, default value)
- a dict with the entries:
- type: a XmlConfig subclass
- default: default value, expected as instance or list or dict of XMlConfig object(s), depending on the single/key parameters
- create: whether to create the instance or list when there are no such children in elt
- args: positionnal arguments for XmlConfig children creation
- kwargs: named arguments for XmlConfig children creation
- single: whether we expect a single instance or a list of instance as result in dst (default is False). This may also be an integer specifying the child 0-based index.
- self: whether we want to register loaded children in dst as dict entries (default is False)
- key: which children attribute to use as key when loading with self=True
- dst: an object that will be populated with the children
- create: whether to create attributes in dst with the default value when they are not in elt
The type must be a subclass of XmlConfig which will be used to deserialize the children elements
Return: a tuple (attributes, elements, entries) of the loaded data
-
load_xml_textnodes
(elt=None, textnodes=None, dst=None, create=False, xml_element_name=<function xml_element_name>)[source]¶ Deserialize text node children from an element
Params: - elt: element to search in
- textnodes: specification for text node children deserialization
- This must be a dict of object attribute {name:spec, …} with name as a string and spec as:
- the text nodes tag name
- a list or tuple (tag name, default value)
- a dict with the entries:
- tagName: the text nodes tag name (default is the textnode name formatted by xml_element_name)
- type: a factory function taking the text node content as argument
- default: default value, expected as instance or list depending on the single parameter
- args: positionnal arguments for children creation
- kwargs: named arguments for children creation
- single: whether we expect a single instance or a list of instance as result in dst (default is False). This may also be an integer specifying the child 0-based index.
- dst: an object that will be populated with the text node children
- create: whether to create attributes in dst with the default value when they are not in elt
The type must be a callable taking the text node value as single string argument and returning the converted value.
With no type function, text nodes are loaded without modification (as string)
Return: None
-
pretty_indent
(elem, level=0, indent=' ')[source]¶ Indent an ElementTree element avoiding extraneous spaces around node text.
-
register
(obj, attributes=None, elements=None, entries=None)[source]¶ Populate an object with data
Params: - obj: the object to be manipulated
- attributes, optional: dict, used with setattr on obj
- elements, optional: list, used with obj.extend
- entries, optional: dict, used with obj.update
Return: obj