Skip to main content

Python bindings for the Uppsala XML library

Project description

pyuppsala

Python bindings for the Uppsala XML library -- a zero-dependency, pure-Rust implementation of XML 1.0, Namespaces, XPath 1.0, and XSD validation.

pyuppsala gives you a fast, correct, and memory-safe XML toolkit from Python with no C dependencies to compile and no transitive native libraries to audit.

This release is against 0.7.0 of Uppsala library.

Features

  • XML 1.0 parsing with full well-formedness checking
  • Namespace-aware DOM with tree mutation (create, append, insert, remove, detach)
  • XPath 1.0 evaluation (all axes, functions, predicates)
  • XSD validation (structures + datatypes, 40+ built-in types, facets, complex types)
  • XSD regex pattern matching (Unicode categories, blocks, character class subtraction)
  • Imperative XML builder (XmlWriter) for constructing output without a DOM
  • Serialization with pretty-printing, compact output, and streaming to files
  • Automatic encoding detection for UTF-8 and UTF-16 (LE/BE)
  • lxml.etree-compatible API via pyuppsala.etree, a near drop-in for much of lxml.etree backed by Uppsala's secure parser

Read the full documentation

Installation

python3 -m pip install pyuppsala

Or with uv:

uv add pyuppsala

Wheels are compiled from Rust via maturin. Python 3.10+ is required.

Quick start

Parse and query

from pyuppsala import Document, XPathEvaluator

doc = Document("<bookstore><book><title>Moby Dick</title></book></bookstore>")
doc.prepare_xpath()

xpath = XPathEvaluator()
title = xpath.evaluate(doc, "string(//title)")
print(title)  # "Moby Dick"

Build XML

from pyuppsala import XmlWriter

w = XmlWriter()
w.write_declaration()
w.start_element("catalog", [("xmlns", "urn:example")])
w.start_element("item", [("id", "1")])
w.text("Widget")
w.end_element("item")
w.end_element("catalog")
print(w.to_string())

Validate against an XSD schema

from pyuppsala import XsdValidator

schema = """\
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="greeting" type="xs:string"/>
</xs:schema>
"""

validator = XsdValidator(schema)
print(validator.is_valid_str("<greeting>Hello!</greeting>"))  # True
print(validator.is_valid_str("<greeting><bad/></greeting>"))  # False

Mutate the DOM

from pyuppsala import Document

doc = Document("<root><a/></root>")
root = doc.document_element
b = doc.create_element("b")
doc.append_child(root, b)
print(doc.to_xml())  # <root><a/><b/></root>

XSD regex

from pyuppsala import XsdRegex

regex = XsdRegex(r"[0-9]{5}")
print(regex.is_match("12345"))  # True
print(regex.is_match("abcde"))  # False

lxml-compatible etree API

Code written for lxml.etree runs after swapping the import. Elements are live views over the underlying document, with stable identity and the familiar .text/.tail/.attrib model.

from pyuppsala import etree  # instead of: from lxml import etree

root = etree.fromstring("<catalog><book id='1'>Dune</book></catalog>")
print(root.find("book").text)        # Dune
print(root[0].get("id"))             # 1

cat = etree.Element("catalog")
book = etree.SubElement(cat, "book", {"id": "2"})
book.text = "Neuromancer"
print(etree.tostring(cat, encoding="unicode"))
# <catalog><book id="2">Neuromancer</book></catalog>

See the etree documentation for the supported and unsupported feature matrix.

API overview

Class / function Purpose
Document(xml) Parse XML string into a DOM
Document.from_bytes(data) Parse XML bytes (auto-detects UTF-8/UTF-16)
Document.empty() Create an empty document for building from scratch
Node A handle to a node in the document tree
QName A qualified XML name (local name + optional namespace + prefix)
Attribute An XML attribute (name + value)
XPathEvaluator Evaluate XPath 1.0 expressions
XsdValidator(schema) Validate documents against an XSD schema
XmlWriter Imperative XML builder (no DOM needed)
XsdRegex(pattern) XSD regular expression pattern matcher
parse(xml) Module-level shorthand for Document(xml)
parse_bytes(data) Module-level shorthand for Document.from_bytes(data)
pyuppsala.etree lxml.etree-compatible API (Element, SubElement, fromstring, tostring, find/findall, XPath, XMLSchema, ...)

Exceptions

Exception Raised when
XmlParseError XML is syntactically malformed
XmlWellFormednessError XML violates well-formedness constraints
XmlNamespaceError Namespace prefix is undeclared or misused
XPathError XPath expression is invalid
XsdValidationError XSD schema itself is invalid

All exceptions inherit from Exception.

Type stubs

Type stubs (pyuppsala/__init__.pyi and pyuppsala/etree.pyi, marked with py.typed) ship with the package for full IDE auto-completion and type-checking with mypy/pyright.

Development

# Clone the repository
git clone https://github.com/kushaldas/pyuppsala.git
cd pyuppsala

# Set up the environment with uv
uv sync

# Build the native extension in development mode
uv run maturin develop

# Run the test suite
uv run pytest

# Build a release wheel
uv run maturin build --release

License

BSD-2-Clause

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyuppsala-0.7.0.tar.gz (165.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyuppsala-0.7.0-cp310-abi3-win_arm64.whl (769.6 kB view details)

Uploaded CPython 3.10+Windows ARM64

pyuppsala-0.7.0-cp310-abi3-win_amd64.whl (811.1 kB view details)

Uploaded CPython 3.10+Windows x86-64

pyuppsala-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl (846.3 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

pyuppsala-0.7.0-cp310-abi3-macosx_11_0_arm64.whl (780.6 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file pyuppsala-0.7.0.tar.gz.

File metadata

  • Download URL: pyuppsala-0.7.0.tar.gz
  • Upload date:
  • Size: 165.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyuppsala-0.7.0.tar.gz
Algorithm Hash digest
SHA256 bff292425b9229c1f1902f70abc7930c4b3a4419c661b07ad8d0432046bbab0c
MD5 d28f6c3542a618e182d3aff144ea2ae7
BLAKE2b-256 6e12095cdbd5705dff5dd21cdbf4cabf0b205fc23db1ef6983dd7719fdc8ad8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyuppsala-0.7.0.tar.gz:

Publisher: release.yml on kushaldas/pyuppsala

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyuppsala-0.7.0-cp310-abi3-win_arm64.whl.

File metadata

  • Download URL: pyuppsala-0.7.0-cp310-abi3-win_arm64.whl
  • Upload date:
  • Size: 769.6 kB
  • Tags: CPython 3.10+, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyuppsala-0.7.0-cp310-abi3-win_arm64.whl
Algorithm Hash digest
SHA256 a3d473752d9e7a814e51f8f199ca37fe13181f2eefe14acd2ae4814df7e57433
MD5 752ad400d447ceadf6344a8ace1ffca0
BLAKE2b-256 c840dd4f429aec7173bce0c42f25e32eb5c21e5e4abd47de116a10112280034d

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyuppsala-0.7.0-cp310-abi3-win_arm64.whl:

Publisher: release.yml on kushaldas/pyuppsala

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyuppsala-0.7.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: pyuppsala-0.7.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 811.1 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyuppsala-0.7.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f01eab13624e7125ff4e06d778ffb52ce05e825e73105bb118ba8270970b855b
MD5 5c480cefb8e94a9d6ca6f6bdfe4ba2e0
BLAKE2b-256 28d0e472edd69cf1cdf5a87a8542860b369324e3e7ae5bc33ed5130ddc7f4525

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyuppsala-0.7.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on kushaldas/pyuppsala

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyuppsala-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pyuppsala-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 704553caa860543cee72fba8122c50c6ffda444ec65b8fa1b7a310b99031adba
MD5 82f2ba3e06d8485e99da18231d87f0ea
BLAKE2b-256 87ad5a4ac1623dd9ba4ff0cd073ad3e021b6d6ff6e86ecbc0ab484f361730a07

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyuppsala-0.7.0-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on kushaldas/pyuppsala

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyuppsala-0.7.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyuppsala-0.7.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 af0343e175c36d3b97d28dccf93292a4575bb190e15e641788a8dde3980ea35c
MD5 1ef93b9b10e170aa88bba3dd927eeddd
BLAKE2b-256 3491aebeb608b65fdb476ef4a2bbe1746f99ec864f8a1f085fd0c51b9e3fcc82

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyuppsala-0.7.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on kushaldas/pyuppsala

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page