1. libxmlrw
Well, here's one that will never make it to the standard python library collection... :)
libxmlrw, a pythonic high-level XML parser to read and write XML files and structures.
Provides modern, logical XML operations with a focus on real-world use, including intelligent white-space handling and other high-level features.
Supporters and contributors are welcome any day of the week :)
2. Fast track
Install with pip install libxmlrw; import into your project with import libxmlrw; and refer to the documentation section below to know your way around; and/or download, open and run example file /samples/libxmlrw_sample1.py from GitHub.
You can also take a look at the examples section below.
3. Basics
Compatibility in short: any platform on Python 3+.
Here's a list of confirmed options:
| Name | Version | Description |
|---|---|---|
| -- | ||
| Windows 10 | ✅ should work | |
| Windows 11 | 25H2 | ✅ confirmed working |
| RHEL/Rocky Linux | 10 | ✅ confirmed working |
| -- | ||
| Python | 3.14.2 | ✅ confirmed working |
Status: public beta.
The current functions are tested on compatible platforms. There's some features missing here and there (see below) and I'd be glad for feedback on the functions that I plan to never implement (but that might change).
In short, it will be a while before the release of a final version - but rest assured that current releases are tested extensively and therefore, work within their limitations.
Built on W11 25H2 with python 3.14.2, pip 26.2.1, build 1.5.0, twine 7.0.0. Standard settings.
4. Installation
| Type | Details |
|---|---|
| venv highly recommended. Please adapt the commands below to your needs. | |
| Auto install (preferred, easiest) |
run pip install libxmlrw, it will download and install from pypi.org |
| Manual install from source | 1. Download the entire source from GitHub 2. unpack from ZIP 3. run e.g python -m pip install "/path/to/folder/libxmlrw/" --no-cache-dir |
5. Documentation
5.1 Basic usage
Import with import libxmlrw.
Initialize a new instance with e.g. xml = libxmlrw.xml(), where xml is now your new instance of the library, on which you call all user-facing functions e.g. xml.read(*), xml.write(*), ... .
5.2 User-facing functions
-
libxmlrw. xml( debug=False )
parameters
(optional) debug [ BOOL ]: set True if you want debugging; dev use only should not be set by the user
returns <none>
raises <none>
description
The main entry function every user MUST call; initializes an instance of this library. E.g.xml = libxmlrw.xml(). -
userInstance. new_xml_struct( )
parameters <none>
returns
[ templates.xml_struct() ]: a new instance of an xml_struct, a structure that represents XML structures programmatically.
raises <none>
description
Returns an xml_struct for user code.
The new_xml_element(*) and new_xml_attribute(*) functions below are sister functions and are also explained here. -
userInstance. new_xml_element( name="",value="",attributes=[],children=[],is_comment=False,parent=None )
parameters
(optional) name [ STR ]: The XML name of the new element
(optional) value [ STR ]: The XML value of the new element
(optional) attributes [ LIST[userInstance. new_xml_attribute(*)] ]: The attributes of the new element
(optional) children [ LIST[userInstance. new_xml_element(*)] ]: The child elements of the new element
(optional) is_comment [ BOOL ]: Set true if this element is an XML comment
(optional) parent [ userInstance. new_xml_element(*) ]: The parent element
All of the parameters are exported, too and are mutable after instancing: e.g.my_new_xml_element.name="xyz".
returns
[ templates.xml_struct.element()* ]: a new instance of an XML element for an xml_struct
raises <none>
description
Returns a new XML element to be used in an xml_struct -
userInstance. new_xml_attribute( name="",value="",parent=None )
parameters
(optional) name [ STR ]: The XML name of the new attribute
(optional) value [ STR ]: The XML value of the new attribute
(optional) parent [ userInstance. new_xml_element(*) ]: The parent element
All of the parameters are exported, too and are mutable after instancing: e.g.my_new_xml_attrib.name="xyz".
returns
[ templates.xml_struct.element.attribute()* ]: a new instance of an XML attribute for an xml_struct
raises <none>
description
Returns a new XML attribute to be used in an xml_struct -
userInstance. read( path="",data="",encoding=None )
parameters
(optional) path [ STR ]: the path of file to read; is neglected if data non-empty
(optional) data [ STR ]: the optional raw data (instead of a file path); takes priority over path if both are specified; newlines, if provided, MUST be \n
(optional) encoding [ STR ]: the encoding for file path; allowed values: None OR "utf-8" OR "utf-16"; mind capitals; default:None (auto-detect from file's BOM - set this parameter if auto-detect doesn't suit you)
Either path or data is required
returns
[ templates.xml_struct() ]: the return XML structure
raises <none>
description
Read an XML structure from a file or directly from input string. -
userInstance. write( xml_structure,path="",encoding="utf-8",recursionlimit=-1 )
parameters
xml_structure [ templates.xml_struct(*) ]: User structure as input
(optional) path [ STR ]: optional the path of file to write to
(optional) encoding [ STR ]: the encoding of file path; allowed values: "utf-8" OR "utf-16"; mind capitals; default:"utf-8"
(optional) declaration_auto_encoding [ BOOL ]: in [xml_structure] the XML declaration.encoding parameter is automatically adjusted according to the parameter given in [encoding];
True: auto-generate the [xml_structure] declaration.encoding parameter
False: do not overwrite the [xml_structure] declaration.encoding parameter;
default:True
(optional) recursionlimit [ INT ]: raises python's recursion limit if specified;
When using large XML structures (by default, more than 990 XML elements including all children), make sure to set the [recursionlimit] param.
This is because the write() function depends on recursion, and it cannot know the size of your structure beforehand.
Setting the recursionlimit is your responsibility to avoid exceptions.
Should match the amount of XML elements + 10, e.g. 9734.
Not required on smaller structures.
returns
[ STR ]: the raw data output; 1:1 copy of the data that gets written to file; newline character is "\n"
raises <none>
description
Write an XML structure to file and/or return as STR to caller.
5.3 User-facing structures
-
libxmlrw.templates. xml_struct( )
exports
declaration [ templates.xml_struct.declaration(*) ] the XML declaration
rootelement [ templates.xml_struct.element(*) ] the XML root element (the XML rules limit this to max. one)
children [ LIST[templates.xml_struct.element(*)] ] the XML child elements (for comments on XMl root element level)
description
To initialize an instance of this structure, please do so by calling userInstance.new_xml_struct(*) only!
Represents XML structures programmatically.
The user gets such type e.g. from a call to read(*) and new_xml_struct(*) and/or feeds such type e.g. to write(*) functions.
This structure stores the XML declaration in the declaration export and the XML root element in the rootelement export, which may itself store as many children (XML elements, XML attributes) as necessary.
This library handles XML comments as "default" XML elements, meaning that all comments are also of type templates.xml_struct.element(*), but with their is_comment export set TRUE. -
libxmlrw.templates.xml_struct. element( )
exports
parent [ templates.xml_struct.element(*) ] the parent object; does not have to be filled by user (auto-handled by library)
name [ STR ] the XML name
value [ STR ] the XML value
attributes [ LIST[templates.xml_struct.element.attribute(*)] ] the XML attributes
children [ LIST[templates.xml_struct.element(*)] ] the XML children
is_comment [ BOOL ] set TRUE if this element is XML comment
description
To initialize an instance of this structure, please do so by calling userInstance.new_xml_element(*) only!
Represents XML elements programmatically.
Each child element is also of this type, making this structure very versatile.
The name, value, attributes and children exports are self-explainatory;
the is_comment export is to be set TRUE if this element represents an XML comment. -
libxmlrw.templates.xml_struct.element. attribute( )
exports
parent [ templates.xml_struct.element(*) ] the parent object; does not have to be filled by user (auto-handled by library)
name [ STR ] the XML attribute name
value [ STR ] the XML attribute value
description
To initialize an instance of this structure, please do so by calling userInstance.new_xml_attribute(*) only!
Represents XML attributes programmatically. -
libxmlrw.templates.xml_struct. declaration( )
exports
version [ STR ] the XML declaration version value
encoding [ STR ] the XML declaration encoding value
standalone [ STR ] the XML declaration standalone value
description
To initialize an instance of this structure, please use the one provided in function userInstance.new_xml_struct(*).declaration only!
Represents XML declarations programmatically.
5.4 Exception handling
This library itself raises custom exception types only.
any user-facing callable of librxmlrw will raise these exception types:
-
libxmlrw.exceptions. XMLRootElementError
exports <none>
description
Error in XML root element, e.g. duplicate declaration -
libxmlrw.exceptions. XMLDeclarationError
exports <none>
description
Error in XML declaration, e.g. duplicate declaration or unallowed values -
libxmlrw.exceptions. XMLSyntaxError
exports <none>
description
Error in XML syntax, e.g. user provided wrong type for xml_struct -
libxmlrw.exceptions. XMLUnallowedChar
exports <none>
description
Unallowed character in name, value or other field -
libxmlrw.exceptions. XMLMissingName
exports <none>
description
XML name is missing -
libxmlrw.exceptions. InternalException
exports <none>
description
Library-internal exception which you should most likely report -
libxmlrw.exceptions. GeneralException
exports
original [ * ] the original exception
description
Other exception type (i.e. python built-in exception type) occured which is wrapped in this type; User can access the "original" exception via the original export.
5.5 Examples
Import; initialize instance of library; make new xml_struct; define XML declaration:
import libxmlrw
xml = libxmlrw.xml()
my_xml_struct = xml.new_xml_struct()
#in a standard use case (UTF-8 file format), setting the XML declaration is not required, but here's the process:
my_xml_struct.declaration.version = "1.0" #XML standard default value
my_xml_struct.declaration.encoding = "UTF-8" #XML standard default value; MAY be "UTF-8" OR "UTF-16"
my_xml_struct.declaration.standalone = "yes"
Create XML root element in xml_struct; immediately modify (overwrite) name and value:
my_xml_struct.rootelement = xml.new_xml_element(name="My_root_element", value="this is the root elements value")
my_xml_struct.rootelement.name = "My_root_element"
my_xml_struct.rootelement.value = "this is the root element's value"
Add child to XML root element; add attributes to this child:
my_xml_struct.rootelement.children.append( xml.new_xml_element(name="child_element_1", value="child element #1") )
my_xml_struct.rootelement.children[0].attributes.append( xml.new_xml_attribute(name=f"attribute{0}", value=f"attribute{0}") )
my_xml_struct.rootelement.children[0].attributes.append( xml.new_xml_attribute(name=f"attribute{1}", value=f"attribute{1}") )
Add multi-line comment to XML child element; note that comments are handled like "normal" XML elements but with their is_comment parameter set true:
my_xml_struct.rootelement.children[0].children.append( xml.new_xml_element(name="comment") )
my_xml_struct.rootelement.children[0].children[0].is_comment = True
my_xml_struct.rootelement.children[0].children[0].value = "my_comment\nline2\nline3"
write xml-struct to file on disk:
xml.write(xml_structure = my_xml_struct, path = "xml_test.xml")
read XML file and store as read_xml_struct:
read_xml_struct = xml.read(path = "xml_test.xml")
5.6 Quirks, features, ToDo
Quirks and features:
- This library handles XML comments as "default" XML elements in xml_struct, meaning that all comments are also of type templates.xml_struct.element(*), but with their is_comment export set TRUE.
- CDATA is not supported (future release).
- namespaces are not supported (future release).
- special characters &, <, >, ", ':
- NOT ALLOWED in names (element names, attribute names).
- ALLOWED in values ESCAPED-ONLY (element values, attribute values):
- escape with:
- & ... &
- " ... "
- ' ... "
- < ... <
- > ... >
- the standard specifies that some special chars may be allowed even in values, this will never be implemented.
- on read() and write(), ALL ["] are replaced with ["].
- escape with:
- Mixed content is not allowed and will probably never be implemented:
- not allowed:
<a> CAT <b>AND_MOUSE</b> AND_DOG </a>
- not allowed:
- comment within XML element value are not supported, and will probably never be implemented.
- old-school schema mechanism not supported, only XSD.
- multi-line strings:
- for function read():
- multi-line comments are supported
- multi-line element values are supported but newline characters get discarded from output - you won't see them
- multi-line attribute values are supported
- newline character is '\n' on output xml_struct
- for function write():
- newline character is '\n'
- multi-line comments are supported
- multi-line element values are supported but newline characters get discarded from output
- multi-line attribute values are supported
- for function read():
- nested comments are not supported.
ToDo:
- in source code, handle I/O data in chunks because right now, the space used in memory is the same or more as I/O data (file) size
5.7 Source file structure (for contributors and developers):
<root>
/samples -> sample files
/src -> source code: main folder
/P -> source code: python
/libxmlrw ->
/__init__.py -> main source code file (currently the only file)
LICENSE -> LICENSE
README.md -> README
setup.py -> pip installer setup file
5.8 Source code structure (for contributors and developers):
/src/P/libxmlrw/__init__.py is the main entry file which contains all classes and functions.
The universal main entry point is the __init(*)__ function of class xml in the __init__.py source code file.
This is a result from the user importing the library import libxmlrw and initializing a new instance e.g. xml = libxmlrw.xml().
On this instance, the user then calls the relevant functions e.g. xml.read(*), xml.write(*).
On this instance, the user may also request (depending on his needs) a copy of an xml_struct which represents A) either an XML structure generated by user code to be written to file/string or B) an XML structure read from file/string to be represented in user code.
The user may request such an xml_struct by calling the new_xml_struct(*) function on his instance, e.g. my_xml_struct = xml.new_xml_struct().
In the source code, this call then triggers a return copy.copy( templates.xml_struct() ) which is self-explaining.
The new_xml_element(*) and new_xml_attribute(*) are sister functions of new_xml_struct(*) and initialize and return a new XML element or XML attribute respectively in a user-friendly way, e.g. to be used in my_xml_struct.
There's two more first-level classes:
templates, which houses some... templates, would you know it. For backend only.
exceptions, which exposes exception handling both to the user and backend.
6. Official Sources
| Site | URL |
|---|---|
| GitHub | github.com/core2000-eU/libxmlrw |
| pypi.org | pypi.org/project/libxmlrw |
| core2000.com (Website/info only, no release) | core2000.com/software |
Now for the boring part
This library is created and maintained free of cost by a real human being /bla /bla /bla ... You know the deal by now.
But seriously, monetary support a serious subject and without some income, I cannot continue to publish and maintain.
Not that anyone needs my gibberish anyways, but if you find it helpful, please consider the below. Thanks :)
--> buymeacoffee.com/core2000
About
Created on 09.2026 and happily maintained since by core2000 and it's owner, Benjamin Winter.
For more details, you can pay us a visit over on core2000.com.
Metadata
Release files for libxmlrw 0.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| libxmlrw-0.0.1.tar.gz | 24.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| libxmlrw-0.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 43.0 kB
Release files / libxmlrw-0.0.1.tar.gz
| Download URL | libxmlrw-0.0.1.tar.gz |
|---|---|
| Size | 24.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0095b388181d6e82dc4b46cdaab5767de124fa2b5b486c0d662abd597589dac1
|
|
BLAKE2b-256 checksum How to use checksums |
b6636c8f5bec151a85cb5eec9626739c8fe76dbf4de542718eab1caff0ff74a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|
Release files / libxmlrw-0.0.1-py3-none-any.whl
| Download URL | libxmlrw-0.0.1-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3a8e81cbc8165efc4ececa6e692ad8402a053f5704fec7b849e30844bb80ce89
|
|
BLAKE2b-256 checksum How to use checksums |
162d79b603d40b28b1d02ee52cca450403f3cf9244448c76ba65d8f7f56f4b62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.2
|
Security for libxmlrw 0.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.