1 r"""
2 A simple, fast way to create dotted-name APIs for XML data
3
4 simplexmlapi exposes an API similar to those of the marshal and pickle modules.
5
6 An XML document may be loaded into a L{SimpleXmlApi} object and traversed using
7 Python-like dotted names. One may also map attributes of the L{SimpleXmlApi}
8 object to given dotted names.
9
10 Each segment of the dotted name will be resolved to the first child element
11 with that tag name. If no such element exists, it will be resolved to an
12 attribute on the current element. If no such attribute exists, an exception
13 will be raised.
14
15 Traversing the tree manually -- that is, without using an attribute map -- will
16 return a L{DotNode} or L{DotNodeAttribute} instance. To get the text value of a node
17 or attribute, access the '_' property or call the C{getValue()} method. When
18 accessing an attribute mapping, the text value is returned automatically; no
19 call to C{getValue()} is necessary.
20
21 If multiple matching child elements exist, C{__0} may be appended to the name,
22 where C{'0'} is the index of the desired element.
23
24 In case of tag name/attribute conflicts, attribute resolution may be specified
25 explicitly by appending C{__a} to the name.
26
27 Parsing an XML document and traversing elements with dotted names:
28
29 >>> import simplexmlapi
30 >>> s = '''
31 ... <xml> <obj>
32 ... <prop name="value">A Value</prop>
33 ... <prop name="thing">A Thing</prop>
34 ... </obj> </xml>
35 ... '''
36 >>> api = simplexmlapi.loads(s)
37 >>> api.obj.prop._
38 u'A Value'
39 >>> api.obj.prop.name._
40 'value'
41 >>> api.obj.prop__1.name._
42 'thing'
43 >>> api.obj.prop__1.name__a._
44 'thing'
45 >>> from StringIO import StringIO
46 >>> io = StringIO(s)
47 >>> api = simplexmlapi.load(io)
48 >>> api.obj.prop._
49 u'A Value'
50
51 Mapping dotted names to attributes:
52
53 >>> import simplexmlapi
54 >>> s = '''
55 ... <xml> <obj>
56 ... <prop name="value">A Value</prop>
57 ... <prop name="thing">A Thing</prop>
58 ... </obj> </xml>
59 ... '''
60 >>> api = simplexmlapi.loads(s)
61 >>> api.add_mapping('value', 'obj.prop__0')
62 >>> api.add_mapping('thing', 'obj.prop__1')
63 >>> api.value
64 u'A Value'
65 >>> api.thing
66 u'A Thing'
67 >>> attr_map = dict(value="obj.prop__0", thing="obj.prop__1")
68 >>> api2 = simplexmlapi.loads(s, map=attr_map)
69 >>> api2.value
70 u'A Value'
71 >>> api2.thing
72 u'A Thing'
73
74 Extending L{SimpleXmlApi}:
75
76 >>> import simplexmlapi
77 >>> class SampleApi(simplexmlapi.SimpleXmlApi):
78 ... _map = {
79 ... 'value' : 'obj.prop__0',
80 ... 'thing' : 'obj.prop__1' }
81 ...
82 >>> s = '''
83 ... <xml>
84 ... <obj>
85 ... <prop name="value">A Value</prop>
86 ... <prop name="thing">A Thing</prop>
87 ... </obj>
88 ... </xml>
89 ... '''
90 >>> api = simplexmlapi.loads(s, cls=SampleApi)
91 >>> api.value
92 u'A Value'
93 >>> api.thing
94 u'A Thing'
95
96 """
97 __version__ = '0.1.1'
98 __all__ = ['load', 'loads', 'SimpleXmlApi']
99
100 from api import SimpleXmlApi, factory as _factory
101
102 -def load(fp, map=None, cls=None, **kwargs):
103 """
104 Parse C{fp} (a file-like object containing an XML document) and return a
105 dotted-name-walkable L{SimpleXmlApi} instance.
106
107 If C{map} is specified, attributes will be created on the returned
108 instance mapping L{map}'s keys to its associated dotted-name values.
109
110 To use a custom L{SimpleXmlApi} subclass, specify it with the C{cls}
111 kwarg.
112 """
113 return _factory(fp.read(), map, cls, **kwargs)
114
115
116 -def loads(s, map=None, cls=None, **kwargs):
117 """
118 Parse C{s} (a C{str} or C{unicode} instance containing an XML document)
119 and return a dotted-name-walkable L{SimpleXmlApi} instance.
120
121 If map is specified, attributes will be created on the returned
122 instance mapping map's keys to its associated dotted-name values.
123
124 To use a custom L{SimpleXmlApi} subclass, specify it with the L{cls}
125 kwarg.
126 """
127 return _factory(s, map, cls, **kwargs)
128