maxml 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
maxml-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,330 @@
1
+ Metadata-Version: 2.4
2
+ Name: maxml
3
+ Version: 1.0.0
4
+ Summary: A streamlined pure Python XML serializer.
5
+ Author: Daniel Sissman
6
+ License-Expression: MIT
7
+ Project-URL: documentation, https://github.com/bluebinary/maxml/blob/main/README.md
8
+ Project-URL: changelog, https://github.com/bluebinary/maxml/blob/main/CHANGELOG.md
9
+ Project-URL: repository, https://github.com/bluebinary/maxml
10
+ Project-URL: issues, https://github.com/bluebinary/maxml/issues
11
+ Project-URL: homepage, https://github.com/bluebinary/maxml
12
+ Keywords: xml,serialization,xml serialization,xml writer
13
+ Platform: any
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: hybridmethod==1.0.*
22
+ Provides-Extra: development
23
+ Requires-Dist: black==24.10.*; extra == "development"
24
+ Requires-Dist: pytest==8.3.*; extra == "development"
25
+ Requires-Dist: pytest-codeblocks==0.17.0; extra == "development"
26
+ Provides-Extra: distribution
27
+ Requires-Dist: build; extra == "distribution"
28
+ Requires-Dist: twine; extra == "distribution"
29
+ Requires-Dist: wheel; extra == "distribution"
30
+
31
+ # MaXML: A Pure Python XML Serializer
32
+
33
+ The MaXML library provides a streamlined pure Python XML serializer.
34
+
35
+ ### Requirements
36
+
37
+ The MaXML library has been tested with Python 3.10, 3.11, 3.12 and 3.13. The library is
38
+ not compatible with Python 3.9 or earlier.
39
+
40
+ ### Installation
41
+
42
+ The MaXML library is available from PyPI, so may be added to a project's dependencies
43
+ via its `requirements.txt` file or similar by referencing the MaXML library's name,
44
+ `maxml`, or the library may be installed directly into your local runtime environment
45
+ using `pip` via the `pip install` command by entering the following into your shell:
46
+
47
+ $ pip install maxml
48
+
49
+ ### Example Usage
50
+
51
+ To use the MaXML library, import the library's and begin creating your XML document:
52
+
53
+ ```python
54
+ import maxml
55
+
56
+ root = maxml.Element(name="my:node", namespace="http://namespace.example.org/my")
57
+
58
+ child = root.subelement(name="my:child-node")
59
+
60
+ child.set("my-attribute", "my-attribute-value")
61
+
62
+ child.text = "testing"
63
+
64
+ root.tostring(pretty=True)
65
+ ```
66
+
67
+ The above example will result in the following XML:
68
+
69
+ ```xml
70
+ <my:node xmlns:my="http://namespace.example.org/my">
71
+ <my:child-node my-attribute="my-attribute-value">testing</my:child-node>
72
+ </my:node>
73
+ ```
74
+
75
+ ### Methods & Properties
76
+
77
+ The MaXML library provides two main classes for use in creating and serializing XML, the
78
+ `Elements` class that is used to represent nodes in the XML document tree along with any
79
+ attributes those nodes have, their associated namespaces, any text content and children,
80
+ and the `Namespace` class for holding information about namespaces.
81
+
82
+ The classes and their methods and properties are listed below:
83
+
84
+ #### Element Class
85
+
86
+ The `Element` class constructor `Element(...)` takes the following arguments:
87
+
88
+ * `name` (`str`) – The required `name` argument sets the prefixed name of the element.
89
+
90
+ * `text` (`str`) – The optional `text` argument can be used to specify the text content
91
+ of the element; alternatively it can be set later via the `text` property.
92
+
93
+ * `namespace` (`Namespace` | `str`) – The optional `namespace` argument can be used to
94
+ specify the namespace for the element while it is being created; the namespace can
95
+ either be specified as the URI that corresponds with the prefix specified as part of
96
+ the element's name, or can be a reference to a `Namespace` class instance that holds
97
+ the corresponding `prefix` and matching `URI`. If the matching namespace has already
98
+ been registered before the element is created via the class' `register_element()`
99
+ method, then it is not necessary to specify a `namespace` argument when an element
100
+ that references that namespace (via its `name` prefix) is created.
101
+
102
+ * `mixed` (`bool`) – The optional `mixed` argument can be used to override the default
103
+ mixed-content mode of the element; by default each element allows mixed-content
104
+ which means that the element can contain both text content and children; if an
105
+ element should only be allowed to contain text content or children, then
106
+ `mixed` can be set to `False` during the construction of the element, which will
107
+ then prevent both content types from being serialized and will instead result in an
108
+ error being raised.
109
+
110
+ * `parent` (`Element`) – The optional `parent` property is used internally by the
111
+ library when sub-elements are created to set the appropriate parent reference; this
112
+ property should not be set manually unless one is conformable with the possible
113
+ side-effects that may occur.
114
+
115
+ The `Element` class provides the following methods:
116
+
117
+ * `register_namespace(prefix: str, uri: str)` – The `register_namespace()` method
118
+ supports registering namespaces globally for the module or per instance depending
119
+ on whether the method is called on the class directly or whether it is called on a
120
+ specific instance of the class.
121
+
122
+ If a namespace is registered globally for the module, the registered namespaces
123
+ become available for use by any instance of the class created within the program
124
+ after that point. This is especially useful for widely used XML namespaces which
125
+ obviates the need to re-register these widely used namespaces for each instance.
126
+
127
+ If there are namespaces which are specific to a document that is being created
128
+ and that won't be used elsewhere in the program, then those namespaces can be
129
+ registered on the specific class instance within which they will be used without
130
+ affecting the global list of registered namespaces.
131
+
132
+ Each namespace consists of a prefix which can be used to prefix element names
133
+ and the URI associated with that namespace prefix.
134
+
135
+ For example, the 'rdf' prefix is associated with the following canonical URI:
136
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
137
+
138
+ This would be registered globally by calling:
139
+
140
+ ```python
141
+ from maxml import Element
142
+
143
+ Element.register_namespace(
144
+ prefix="rdf",
145
+ uri="http://www.w3.org/1999/02/22-rdf-syntax-ns#",
146
+ )
147
+ ```
148
+
149
+ Or this would be registered locally on an instance of the class before its use by a
150
+ sub-element by calling:
151
+
152
+ ```python
153
+ from maxml import Element
154
+
155
+ element = Element(name="my:test", namespace="http://namespace.example.org/my")
156
+
157
+ element.register_namespace(
158
+ prefix="rdf",
159
+ uri="http://www.w3.org/1999/02/22-rdf-syntax-ns#",
160
+ )
161
+ ```
162
+
163
+ Where `instance` was the variable referencing the desired instance of the class.
164
+
165
+ * `set(name: str, value: object)` (`Element`) – The `set()` supports setting a named
166
+ attribute value on the current element; if the named attribute already exists, its
167
+ value is overwritten. The `set()` method returns a reference to `self` so it may be
168
+ chained with other calls on the element.
169
+
170
+ * `get(name: str, default: object = None)` (`object` | `None`) – The `get()` supports
171
+ getting the value of a named attribute on the Element if the named attribute exists,
172
+ returning the optional `default` value if the named attributes does not exist or if
173
+ the `default` value has not been specified, returning `None` otherwise.
174
+
175
+ * `unset(name: str)` (`Element`) – The `set()` supports unsetting a named attribute on
176
+ the element. The `unset()` method returns a reference to `self` so it may be chained
177
+ with other calls on the element.
178
+
179
+ * `subelement(name: str, **kwargs)` (`Element`) – The `subelement()` method creates a
180
+ child element nested under the current element. It requires a `name` and optionally
181
+ accepts all of the other arguments that the `Element` class constructor accepts as
182
+ documented above. When a child element is created, its parent is automatically set
183
+ to the element it is nested under. The `subelement()` method returns a reference to
184
+ the newly created element, thus other calls on that element may be chained.
185
+
186
+ * `find(path: str)` (`Element` | `None`) – The `find()` method can be used to find the
187
+ matching element nested within the current element as specified by the element path
188
+ which consists of one or more prefixed names and optional wildcard characters.
189
+
190
+ The path to the element we wish to find can be specified from the root node of the
191
+ tree by starting the path with the "//" marker which indicates the root node, or the
192
+ path can be specified as a relative path by omitting this, which will result in the
193
+ search starting at the current element node. The path should be specified with the
194
+ name of the element at each level of the nesting that should be matched against to
195
+ reach the desired node; each element node name should be separated by a single "/"
196
+ character, and if any node name could be matched as part of the search the wildcard
197
+ character "*" can be used in place of an element node name.
198
+
199
+ * `findall(path: str)` (`list[Element]`) – The `findall()` method can be used to find
200
+ the matching elements nested within the current element as specified by the element
201
+ path which consists of one or more prefixed names and optional wildcard characters.
202
+
203
+ The `findall()` method uses the same search path format as the `find()` method
204
+ described above, the only difference being that if multiple elements are found at
205
+ the end of the search, all matching elements will be returned instead of the first
206
+ match found as is the case with the `find` method.
207
+
208
+ * `tostring(pretty: bool = False, indent: str | int = None, encoding: str = None)` –
209
+ The `tostring()` method supports serializing the current element tree to a string,
210
+ or to a bytes array if a string encoding, such as 'UTF-8' is specified.
211
+
212
+ To create a 'pretty' printed string, set the `pretty` argument to `True` and set an
213
+ optional indent, which by default is set to two spaces per level of indentation. To
214
+ set the indent level to 1 or more spaces, set `indent` to a positive integer value
215
+ of the number of spaces that should be used for the indentation per level of nesting
216
+ or to use a different whitespace character, such as a tab, set the `indent` value to
217
+ a tab character using the escape sequence for a tab, `"\t"`.
218
+
219
+ To have the method return an encoded `bytes` sequence instead of a unicode string,
220
+ set the optional `encoding` argument to a valid string encoding, such as `"UTF-8"`.
221
+
222
+ The `Element` class provides the following properties:
223
+
224
+ * `prefix` (`str`) – The `prefix` property returns the prefix portion of the element's
225
+ tag full name, for example `my` from `my:test`.
226
+
227
+ * `name` (`str`) – The `name` property getter returns the name portion of the element's
228
+ tag full name, for example `test` from `my:test`.
229
+
230
+ * `fullname` (`str`) – The `fullname` property returns the full name of the element's
231
+ tag, for example `my:test`.
232
+
233
+ * `namespace` (`Namespace`) – The `namespace` property returns the namespace associated
234
+ with the element, as either registered before the element was created, or created by
235
+ the process of creating the element if the optional `namespace` property was used.
236
+
237
+ * `depth` (`int`) – The `depth` property returns depth of the element in the tree.
238
+
239
+ * `parent` (`Element` | `None`) – The `parent` property returns the parent, if any, of
240
+ the element; the root node of the tree will not have a parent, while all other
241
+ elements will have an assigned parent, set automatically when a sub-element is made.
242
+
243
+ * `children` (`list[Element]`) – The `children` property returns the list of children
244
+ elements associated with the element, if any have been assigned.
245
+
246
+ * `attributes` (`dict[str, str]`) – The `attributes` property returns a dictionary of
247
+ the attributes associated with the element, if any have been assigned, where the key
248
+ of each entry is the name of the attribute and the value is its value.
249
+
250
+ * `text` (`str` | `None`) – The `text` property returns the text of the element if any
251
+ has been assigned or `None` otherwise.
252
+
253
+ * `mixed` (`bool`) – The `mixed` property returns the mixed-content status of the
254
+ element which determines whether the element can have both text content and children
255
+ or if at most it can only have one or the other. By default each element allows both
256
+ content types, but by setting the `mixed` argument on the `Element` constructor to
257
+ `False`, mixed-content mode will be turned-off.
258
+
259
+ * `root` (`Element`) – The `root` property returns the root element of the tree from
260
+ anywhere else within the tree.
261
+
262
+ * `namespaces` (`set[Namespace]`) – The `namespaces` property returns the full `set` of
263
+ namespaces associated with the element including any inherited from its parents; the
264
+ set can be used to inspect the associated namespaces, but its primary use is to help
265
+ facilitate the serialization of the document.
266
+
267
+ * `namespaced` (`set[Namespace]`) – The `namespaced` property returns the unique `set`
268
+ of namespaces associated with the element that have not already been referenced by
269
+ a parent node, thus ensuring only the newly referenced namespaces are introduced in
270
+ the serialized document rather than potentially repeated references to namespaces
271
+ which have already been referenced previously; the set can be used to inspect the
272
+ associated namespaces, but its primary use is to help facilitate the serialization.
273
+
274
+ #### Namespace Class
275
+
276
+ The `Namespace` class constructor `Namespace(...)` takes the following arguments:
277
+
278
+ * `prefix` (`str`) – The required `prefix` argument sets the namespace prefix.
279
+ * `uri` (`str`) – The required `uri` argument sets the namespace URI.
280
+
281
+ The `Namespace` class provides the following methods:
282
+
283
+ * `copy()` (`Namespace`) – The `copy()` method creates an independent copy of the
284
+ current Namespace instance and returns it.
285
+
286
+ * `promote()` (`Namespace`) – The `promote()` marks the current Namespace instance as
287
+ having been 'promoted' which allows it to be listed before any attributes on the
288
+ Element it is associated with; as this method returns a reference to `self` it may
289
+ be chained with other calls.
290
+
291
+ * `unpromote()` (`Namespace`) – The `unpromote()` marks the current Namespace instance
292
+ as having been 'un-promoted' preventing it from being listed before any attributes
293
+ on the Element it is associated with; as this method returns a reference to `self`
294
+ it may be chained with other calls.
295
+
296
+ The `Namespace` class provides the following properties:
297
+
298
+ * `prefix` (`str`) – The `prefix` property returns the prefix held by the namespace.
299
+ * `uri` (`str`) – The `uri` property returns the URI held by the namespace.
300
+ * `promoted` (`bool`) – The `promoted` property getter returns the promoted state of the
301
+ Namespace instance as set or unset through the `promote()` and `unpromote()` helper
302
+ methods or via the `promoted` property setter.
303
+ * `promoted` (`bool`) – The `promoted` property setter supports setting the `promoted`
304
+ property value via the property accessor.
305
+
306
+
307
+ ### Unit Tests
308
+
309
+ The MaXML library includes a suite of comprehensive unit tests which ensure that the
310
+ library functionality operates as expected. The unit tests were developed with and are
311
+ run via `pytest`.
312
+
313
+ To ensure that the unit tests are run within a predictable runtime environment where all of the necessary dependencies are available, a [Docker](https://www.docker.com) image is created within which the tests are run. To run the unit tests, ensure Docker and Docker Compose is [installed](https://docs.docker.com/engine/install/), and perform the following commands, which will build the Docker image via `docker compose build` and then run the tests via `docker compose run` – the output of running the tests will be displayed:
314
+
315
+ ```shell
316
+ $ docker compose build
317
+ $ docker compose run tests
318
+ ```
319
+
320
+ To run the unit tests with optional command line arguments being passed to `pytest`, append the relevant arguments to the `docker compose run tests` command, as follows, for example passing `-vv` to enable verbose output:
321
+
322
+ ```shell
323
+ $ docker compose run tests -vv
324
+ ```
325
+
326
+ See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding available optional command line arguments.
327
+
328
+ ### Copyright & License Information
329
+
330
+ Copyright © 2025 Daniel Sissman; licensed under the MIT License.
maxml-1.0.0/README.md ADDED
@@ -0,0 +1,300 @@
1
+ # MaXML: A Pure Python XML Serializer
2
+
3
+ The MaXML library provides a streamlined pure Python XML serializer.
4
+
5
+ ### Requirements
6
+
7
+ The MaXML library has been tested with Python 3.10, 3.11, 3.12 and 3.13. The library is
8
+ not compatible with Python 3.9 or earlier.
9
+
10
+ ### Installation
11
+
12
+ The MaXML library is available from PyPI, so may be added to a project's dependencies
13
+ via its `requirements.txt` file or similar by referencing the MaXML library's name,
14
+ `maxml`, or the library may be installed directly into your local runtime environment
15
+ using `pip` via the `pip install` command by entering the following into your shell:
16
+
17
+ $ pip install maxml
18
+
19
+ ### Example Usage
20
+
21
+ To use the MaXML library, import the library's and begin creating your XML document:
22
+
23
+ ```python
24
+ import maxml
25
+
26
+ root = maxml.Element(name="my:node", namespace="http://namespace.example.org/my")
27
+
28
+ child = root.subelement(name="my:child-node")
29
+
30
+ child.set("my-attribute", "my-attribute-value")
31
+
32
+ child.text = "testing"
33
+
34
+ root.tostring(pretty=True)
35
+ ```
36
+
37
+ The above example will result in the following XML:
38
+
39
+ ```xml
40
+ <my:node xmlns:my="http://namespace.example.org/my">
41
+ <my:child-node my-attribute="my-attribute-value">testing</my:child-node>
42
+ </my:node>
43
+ ```
44
+
45
+ ### Methods & Properties
46
+
47
+ The MaXML library provides two main classes for use in creating and serializing XML, the
48
+ `Elements` class that is used to represent nodes in the XML document tree along with any
49
+ attributes those nodes have, their associated namespaces, any text content and children,
50
+ and the `Namespace` class for holding information about namespaces.
51
+
52
+ The classes and their methods and properties are listed below:
53
+
54
+ #### Element Class
55
+
56
+ The `Element` class constructor `Element(...)` takes the following arguments:
57
+
58
+ * `name` (`str`) – The required `name` argument sets the prefixed name of the element.
59
+
60
+ * `text` (`str`) – The optional `text` argument can be used to specify the text content
61
+ of the element; alternatively it can be set later via the `text` property.
62
+
63
+ * `namespace` (`Namespace` | `str`) – The optional `namespace` argument can be used to
64
+ specify the namespace for the element while it is being created; the namespace can
65
+ either be specified as the URI that corresponds with the prefix specified as part of
66
+ the element's name, or can be a reference to a `Namespace` class instance that holds
67
+ the corresponding `prefix` and matching `URI`. If the matching namespace has already
68
+ been registered before the element is created via the class' `register_element()`
69
+ method, then it is not necessary to specify a `namespace` argument when an element
70
+ that references that namespace (via its `name` prefix) is created.
71
+
72
+ * `mixed` (`bool`) – The optional `mixed` argument can be used to override the default
73
+ mixed-content mode of the element; by default each element allows mixed-content
74
+ which means that the element can contain both text content and children; if an
75
+ element should only be allowed to contain text content or children, then
76
+ `mixed` can be set to `False` during the construction of the element, which will
77
+ then prevent both content types from being serialized and will instead result in an
78
+ error being raised.
79
+
80
+ * `parent` (`Element`) – The optional `parent` property is used internally by the
81
+ library when sub-elements are created to set the appropriate parent reference; this
82
+ property should not be set manually unless one is conformable with the possible
83
+ side-effects that may occur.
84
+
85
+ The `Element` class provides the following methods:
86
+
87
+ * `register_namespace(prefix: str, uri: str)` – The `register_namespace()` method
88
+ supports registering namespaces globally for the module or per instance depending
89
+ on whether the method is called on the class directly or whether it is called on a
90
+ specific instance of the class.
91
+
92
+ If a namespace is registered globally for the module, the registered namespaces
93
+ become available for use by any instance of the class created within the program
94
+ after that point. This is especially useful for widely used XML namespaces which
95
+ obviates the need to re-register these widely used namespaces for each instance.
96
+
97
+ If there are namespaces which are specific to a document that is being created
98
+ and that won't be used elsewhere in the program, then those namespaces can be
99
+ registered on the specific class instance within which they will be used without
100
+ affecting the global list of registered namespaces.
101
+
102
+ Each namespace consists of a prefix which can be used to prefix element names
103
+ and the URI associated with that namespace prefix.
104
+
105
+ For example, the 'rdf' prefix is associated with the following canonical URI:
106
+ "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
107
+
108
+ This would be registered globally by calling:
109
+
110
+ ```python
111
+ from maxml import Element
112
+
113
+ Element.register_namespace(
114
+ prefix="rdf",
115
+ uri="http://www.w3.org/1999/02/22-rdf-syntax-ns#",
116
+ )
117
+ ```
118
+
119
+ Or this would be registered locally on an instance of the class before its use by a
120
+ sub-element by calling:
121
+
122
+ ```python
123
+ from maxml import Element
124
+
125
+ element = Element(name="my:test", namespace="http://namespace.example.org/my")
126
+
127
+ element.register_namespace(
128
+ prefix="rdf",
129
+ uri="http://www.w3.org/1999/02/22-rdf-syntax-ns#",
130
+ )
131
+ ```
132
+
133
+ Where `instance` was the variable referencing the desired instance of the class.
134
+
135
+ * `set(name: str, value: object)` (`Element`) – The `set()` supports setting a named
136
+ attribute value on the current element; if the named attribute already exists, its
137
+ value is overwritten. The `set()` method returns a reference to `self` so it may be
138
+ chained with other calls on the element.
139
+
140
+ * `get(name: str, default: object = None)` (`object` | `None`) – The `get()` supports
141
+ getting the value of a named attribute on the Element if the named attribute exists,
142
+ returning the optional `default` value if the named attributes does not exist or if
143
+ the `default` value has not been specified, returning `None` otherwise.
144
+
145
+ * `unset(name: str)` (`Element`) – The `set()` supports unsetting a named attribute on
146
+ the element. The `unset()` method returns a reference to `self` so it may be chained
147
+ with other calls on the element.
148
+
149
+ * `subelement(name: str, **kwargs)` (`Element`) – The `subelement()` method creates a
150
+ child element nested under the current element. It requires a `name` and optionally
151
+ accepts all of the other arguments that the `Element` class constructor accepts as
152
+ documented above. When a child element is created, its parent is automatically set
153
+ to the element it is nested under. The `subelement()` method returns a reference to
154
+ the newly created element, thus other calls on that element may be chained.
155
+
156
+ * `find(path: str)` (`Element` | `None`) – The `find()` method can be used to find the
157
+ matching element nested within the current element as specified by the element path
158
+ which consists of one or more prefixed names and optional wildcard characters.
159
+
160
+ The path to the element we wish to find can be specified from the root node of the
161
+ tree by starting the path with the "//" marker which indicates the root node, or the
162
+ path can be specified as a relative path by omitting this, which will result in the
163
+ search starting at the current element node. The path should be specified with the
164
+ name of the element at each level of the nesting that should be matched against to
165
+ reach the desired node; each element node name should be separated by a single "/"
166
+ character, and if any node name could be matched as part of the search the wildcard
167
+ character "*" can be used in place of an element node name.
168
+
169
+ * `findall(path: str)` (`list[Element]`) – The `findall()` method can be used to find
170
+ the matching elements nested within the current element as specified by the element
171
+ path which consists of one or more prefixed names and optional wildcard characters.
172
+
173
+ The `findall()` method uses the same search path format as the `find()` method
174
+ described above, the only difference being that if multiple elements are found at
175
+ the end of the search, all matching elements will be returned instead of the first
176
+ match found as is the case with the `find` method.
177
+
178
+ * `tostring(pretty: bool = False, indent: str | int = None, encoding: str = None)` –
179
+ The `tostring()` method supports serializing the current element tree to a string,
180
+ or to a bytes array if a string encoding, such as 'UTF-8' is specified.
181
+
182
+ To create a 'pretty' printed string, set the `pretty` argument to `True` and set an
183
+ optional indent, which by default is set to two spaces per level of indentation. To
184
+ set the indent level to 1 or more spaces, set `indent` to a positive integer value
185
+ of the number of spaces that should be used for the indentation per level of nesting
186
+ or to use a different whitespace character, such as a tab, set the `indent` value to
187
+ a tab character using the escape sequence for a tab, `"\t"`.
188
+
189
+ To have the method return an encoded `bytes` sequence instead of a unicode string,
190
+ set the optional `encoding` argument to a valid string encoding, such as `"UTF-8"`.
191
+
192
+ The `Element` class provides the following properties:
193
+
194
+ * `prefix` (`str`) – The `prefix` property returns the prefix portion of the element's
195
+ tag full name, for example `my` from `my:test`.
196
+
197
+ * `name` (`str`) – The `name` property getter returns the name portion of the element's
198
+ tag full name, for example `test` from `my:test`.
199
+
200
+ * `fullname` (`str`) – The `fullname` property returns the full name of the element's
201
+ tag, for example `my:test`.
202
+
203
+ * `namespace` (`Namespace`) – The `namespace` property returns the namespace associated
204
+ with the element, as either registered before the element was created, or created by
205
+ the process of creating the element if the optional `namespace` property was used.
206
+
207
+ * `depth` (`int`) – The `depth` property returns depth of the element in the tree.
208
+
209
+ * `parent` (`Element` | `None`) – The `parent` property returns the parent, if any, of
210
+ the element; the root node of the tree will not have a parent, while all other
211
+ elements will have an assigned parent, set automatically when a sub-element is made.
212
+
213
+ * `children` (`list[Element]`) – The `children` property returns the list of children
214
+ elements associated with the element, if any have been assigned.
215
+
216
+ * `attributes` (`dict[str, str]`) – The `attributes` property returns a dictionary of
217
+ the attributes associated with the element, if any have been assigned, where the key
218
+ of each entry is the name of the attribute and the value is its value.
219
+
220
+ * `text` (`str` | `None`) – The `text` property returns the text of the element if any
221
+ has been assigned or `None` otherwise.
222
+
223
+ * `mixed` (`bool`) – The `mixed` property returns the mixed-content status of the
224
+ element which determines whether the element can have both text content and children
225
+ or if at most it can only have one or the other. By default each element allows both
226
+ content types, but by setting the `mixed` argument on the `Element` constructor to
227
+ `False`, mixed-content mode will be turned-off.
228
+
229
+ * `root` (`Element`) – The `root` property returns the root element of the tree from
230
+ anywhere else within the tree.
231
+
232
+ * `namespaces` (`set[Namespace]`) – The `namespaces` property returns the full `set` of
233
+ namespaces associated with the element including any inherited from its parents; the
234
+ set can be used to inspect the associated namespaces, but its primary use is to help
235
+ facilitate the serialization of the document.
236
+
237
+ * `namespaced` (`set[Namespace]`) – The `namespaced` property returns the unique `set`
238
+ of namespaces associated with the element that have not already been referenced by
239
+ a parent node, thus ensuring only the newly referenced namespaces are introduced in
240
+ the serialized document rather than potentially repeated references to namespaces
241
+ which have already been referenced previously; the set can be used to inspect the
242
+ associated namespaces, but its primary use is to help facilitate the serialization.
243
+
244
+ #### Namespace Class
245
+
246
+ The `Namespace` class constructor `Namespace(...)` takes the following arguments:
247
+
248
+ * `prefix` (`str`) – The required `prefix` argument sets the namespace prefix.
249
+ * `uri` (`str`) – The required `uri` argument sets the namespace URI.
250
+
251
+ The `Namespace` class provides the following methods:
252
+
253
+ * `copy()` (`Namespace`) – The `copy()` method creates an independent copy of the
254
+ current Namespace instance and returns it.
255
+
256
+ * `promote()` (`Namespace`) – The `promote()` marks the current Namespace instance as
257
+ having been 'promoted' which allows it to be listed before any attributes on the
258
+ Element it is associated with; as this method returns a reference to `self` it may
259
+ be chained with other calls.
260
+
261
+ * `unpromote()` (`Namespace`) – The `unpromote()` marks the current Namespace instance
262
+ as having been 'un-promoted' preventing it from being listed before any attributes
263
+ on the Element it is associated with; as this method returns a reference to `self`
264
+ it may be chained with other calls.
265
+
266
+ The `Namespace` class provides the following properties:
267
+
268
+ * `prefix` (`str`) – The `prefix` property returns the prefix held by the namespace.
269
+ * `uri` (`str`) – The `uri` property returns the URI held by the namespace.
270
+ * `promoted` (`bool`) – The `promoted` property getter returns the promoted state of the
271
+ Namespace instance as set or unset through the `promote()` and `unpromote()` helper
272
+ methods or via the `promoted` property setter.
273
+ * `promoted` (`bool`) – The `promoted` property setter supports setting the `promoted`
274
+ property value via the property accessor.
275
+
276
+
277
+ ### Unit Tests
278
+
279
+ The MaXML library includes a suite of comprehensive unit tests which ensure that the
280
+ library functionality operates as expected. The unit tests were developed with and are
281
+ run via `pytest`.
282
+
283
+ To ensure that the unit tests are run within a predictable runtime environment where all of the necessary dependencies are available, a [Docker](https://www.docker.com) image is created within which the tests are run. To run the unit tests, ensure Docker and Docker Compose is [installed](https://docs.docker.com/engine/install/), and perform the following commands, which will build the Docker image via `docker compose build` and then run the tests via `docker compose run` – the output of running the tests will be displayed:
284
+
285
+ ```shell
286
+ $ docker compose build
287
+ $ docker compose run tests
288
+ ```
289
+
290
+ To run the unit tests with optional command line arguments being passed to `pytest`, append the relevant arguments to the `docker compose run tests` command, as follows, for example passing `-vv` to enable verbose output:
291
+
292
+ ```shell
293
+ $ docker compose run tests -vv
294
+ ```
295
+
296
+ See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding available optional command line arguments.
297
+
298
+ ### Copyright & License Information
299
+
300
+ Copyright © 2025 Daniel Sissman; licensed under the MIT License.