The High-Performance, Polyglot XML Data-Binding Engine
PolyXML is a universal native XML engine engineered in Rust for ultra-fast, streaming XML serialization and deserialization. It bridges raw XML directly to strongly-typed data structures across modern language runtimes with zero unnecessary allocations.
While modern web ecosystems shifted to JSON and Protocol Buffers, mission-critical industries—including defense & aerospace (UCI), finance (ISO 20022, FIXML), and healthcare (HL7)—continue to rely on XML. PolyXML eliminates the single-language silos and performance penalties of legacy XML data-binding tools by providing one optimized, native Rust core for all stacks.
┌─────────────────────────────────────┐
│ Raw XML Stream │
└──────────────────┬──────────────────┘
│
▼
┌─────────────────────────────────────┐
│ polyxml-core │
│ - quick-xml event reader/writer │
│ - lexical-core scalar parser │
│ - Language-agnostic Schema IR │
│ - Zero-copy streaming state │
└─────────┬───────────────┬───────────┘
│ │
┌────────────────┼───────────────┼────────────────┐
▼ ▼ ▼ ▼
┌──────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Rust / Core │ │ Python │ │ C++ & Go │ │ Node / Wasm │
│ Direct Crate │ │ (PyO3 abi3) │ │(C-ABI / Cgo)│ │ (napi-rs) │
└──────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
-
⚡ Blazing Fast: Powered by
quick-xmlstreaming event loop andlexical-corebyte-slice parsing. Zero DOM intermediate allocations. -
🌊 Streaming Iterator: Parse multi-gigabyte XML documents with
$O(1)$ constant memory (<5 MB RAM) viapolyxml.iterparse(). -
🔄 Bidirectional: Full support for both deserialization (XML
$\to$ typed models) and serialization (typed models$\to$ XML). -
📦 Native Binary Serialization: Ultra-fast MessagePack binary encoding/decoding via
polyxml.dumps_binary()andpolyxml.loads_binary()for key-value stores (MDBX, LMDB, Redis) and IPC (up to 350,000+ objs/s). - 🌐 Polyglot by Design: The core engine is 100% pure Rust with zero Python or language runtime dependencies, ready to be embedded anywhere.
-
🎯 Full Schema Support: Namespaces, attributes vs. elements, text nodes,
xsi:nil, choice, lists, and ISO-8601 date/time scalar types.
PolyXML is benchmarked against the Python and native XML ecosystems on standard, reproducible workloads (full methodology & data).
| Engine | Paradigm / Category | Implementation | Deserialization Latency | Deserialization Throughput | Serialization Latency | Peak RAM |
|---|---|---|---|---|---|---|
| PolyXML | Typed Dataclass | Rust + PyO3 | 13.9 ms | 51.0 MB/s | 7.30 ms | 2.0 MB |
lxml.etree |
Untyped DOM | C / Cython (libxml2) |
10.0 ms | 70.5 MB/s | — | <0.1 MB |
ElementTree |
Untyped DOM | Python Stdlib C/Python | 12.3 ms | 57.5 MB/s | — | 7.1 MB |
defusedxml |
Secure DOM | Python Defused | 27.2 ms | 26.0 MB/s | — | 7.1 MB |
xmltodict |
Untyped Dict | C (pyexpat) |
56.6 ms | 12.5 MB/s | 79.0 ms | 4.8 MB |
xsdata |
Typed Dataclass | Pure Python | 222.5 ms | 3.2 MB/s | 282.6 ms | 3.3 MB |
- 16.0x faster deserialization & 38.7x faster serialization than
xsdata(standard typed dataclasses).- 4.1x faster than
xmltodictwhile returning genuine typed dataclasses instead of untyped string dicts.- 3.5x lower RAM than Python's standard library
xml.etree.ElementTree.
| Engine | Category | Deserialization Latency | Serialization Latency | Speedup vs Pure Python |
|---|---|---|---|---|
| PolyXML | Typed Dataclass | 2.5 μs | 1.4 μs | 17.1x |
| PolyXML (Pydantic) | Typed Pydantic v2 | 3.1 μs | 1.5 μs | 13.7x |
lxml.etree |
Untyped DOM | 3.1 μs | — | 13.7x |
ElementTree |
Untyped DOM | 4.9 μs | — | 8.7x |
xmltodict |
Untyped Dict | 10.3 μs | 14.9 μs | 4.2x |
xsdata |
Typed Dataclass | 43.0 μs | 45.0 μs | 1.0x (Ref) |
Critical telemetry commands and sensor packets deserialize in 2.5 microseconds, beating even C-based DOM parsers (lxml at 3.1 μs).
When caching parsed models in transactional key-value databases (libmdbx, LMDB, RocksDB) or transferring entity batches across multiprocessing workers, polyxml.dumps_binary() and polyxml.loads_binary() eliminate Python's single-threaded pickle bottlenecks:
| Storage Pipeline | Dumps Throughput | Dumps Latency | Loads Throughput | Payload Size | MDBX Write Speed |
|---|---|---|---|---|---|
CloudPickle + LZ4 (Legacy) |
20,609 ops/s | 48.5 μs | 49,322 ops/s | 547 B | 18,287 ops/s |
Pickle 5 + LZ4 (Stdlib C) |
71,954 ops/s | 13.9 μs | 50,092 ops/s | 539 B | — |
PolyXML Binary + LZ4 |
163,192 ops/s | 6.1 μs | 64,781 ops/s | 252 B | 58,781 ops/s |
PolyXML Binary (Direct, No LZ4) |
213,003 ops/s | 4.7 μs | 84,673 ops/s | 327 B | 63,236 ops/s |
- 7.9x faster serialization and 3.2x faster transactional writes into real MDBX.
- 53.9% smaller storage footprint (252 B vs 547 B per entity).
- Zero Loss XML Fidelity: Losslessly preserves
XmlDate,XmlDateTime,XmlDuration,XmlTime,Decimal,QName,Enum,Path, and Pydantic v2 models.
| Ecosystem / Language | Package / Registry | Installation | Interop Tech | Status |
|---|---|---|---|---|
| Rust (Core) | cargo add polyxml |
Native Zero-Copy | 🟢 Stable | |
| Rust (C-ABI) | cargo add polyxml-c |
C-ABI Shared Lib | 🟢 Stable | |
| Python | pip install polyxml |
PyO3 (abi3-py312) |
🟢 Stable | |
| TypeScript / Node | npm install polyxml |
napi-rs Native Addon |
🟢 Stable | |
| Java | <artifactId>polyxml</artifactId> |
Java 22+ Panama FFI | 🟢 Stable | |
| Go | go get github.com/nth-bailey/PolyXML/bindings/go |
Cgo (polyxml.h) |
🟢 Stable | |
| Modern C++20 / C | Conan / vcpkg (polyxml) |
conan install / vcpkg install polyxml |
Header-Only C++20 & Native Lib | 🟢 Stable |
| macOS & Linux | Homebrew Tap | brew install nth-bailey/polyxml/polyxml |
Native Headers & Dynamic Lib | 🟢 Stable |
use std::sync::Arc;
use polyxml::schema::{ModelSchema, FieldSchema, FieldKind, ScalarType, ValueType};
use polyxml::deserialize;
let schema = ModelSchema::builder("User")
.field(FieldSchema::new("id", b"id", FieldKind::Attribute, ValueType::Scalar(ScalarType::Int)))
.field(FieldSchema::new("name", b"name", FieldKind::Element, ValueType::Scalar(ScalarType::String)))
.build();
let xml = br#"<User id="42"><name>Alice</name></User>"#;
let value = deserialize(xml, Arc::clone(&schema))?;👉 Read the Full Rust Guide & Advanced Examples →
from dataclasses import dataclass, field
import polyxml
@dataclass
class Item:
id: int = field(metadata={"type": "Attribute"})
name: str = field(metadata={"type": "Element"})
price: float = field(metadata={"type": "Element"})
# 1. Deserialize full XML into a typed Python dataclass
item = polyxml.deserialize(b'<Item id="1"><name>Turbine</name><price>99.5</price></Item>', Item)
# 2. Stream huge XML documents with O(1) constant memory (<5 MB RAM)
for item in polyxml.iterparse(open("large_catalog.xml", "rb").read(), Item, tag="Item"):
print(item.name, item.price)
# 3. Serialize model back to XML
xml_bytes = polyxml.serialize(item, indent=2)
# 4. Zero-GIL binary serialization for key-value databases & IPC
bin_bytes = polyxml.dumps_binary(item)
restored = polyxml.loads_binary(bin_bytes, Item)👉 Read the Full Python (Dataclasses & Pydantic) Guide →
#include "polyxml.hpp"
auto schema = polyxml::SchemaBuilder("Sensor")
.add_attribute("id", "id", POLYXML_SCALAR_INT)
.add_element("name", "name", POLYXML_SCALAR_STRING)
.build();
auto val = polyxml::deserialize(R"(<Sensor id="101"><name>Gyro</name></Sensor>)", schema);
std::string name = val.get("name")->as_string().value();👉 Read the Full Modern C++20 Guide & Examples →
import "github.com/nth-bailey/PolyXML/bindings/go"
builder, _ := polyxml.NewSchemaBuilder("Device")
builder.AddField("id", "id", polyxml.FieldAttribute, polyxml.ScalarInt)
builder.AddField("name", "name", polyxml.FieldElement, polyxml.ScalarString)
schema, _ := builder.Build()
val, err := polyxml.Deserialize(xmlBytes, schema)
name, _ := val.GetField("name").GetString()👉 Read the Full Go Guide & Struct Adapters →
import { deserialize, serialize } from 'polyxml';
const schema = {
name: 'Item',
fields: [
{ name: 'id', xmlName: 'id', kind: 'attribute', scalarType: 'int' },
{ name: 'name', xmlName: 'name', kind: 'element', scalarType: 'string' }
]
};
const obj = deserialize('<Item id="7"><name>Motor</name></Item>', schema);👉 Read the Full TypeScript & Node.js Guide →
import io.polyxml.PolyXML;
try (var schema = new PolyXML.SchemaBuilder("Sensor")
.addField("id", "id", PolyXML.FieldKind.ATTRIBUTE, PolyXML.ScalarType.INT)
.addField("name", "name", PolyXML.FieldKind.ELEMENT, PolyXML.ScalarType.STRING)
.build()) {
System.out.println("PolyXML Native Version: " + PolyXML.version());
}👉 Read the Full Java 22 Panama Guide →
PolyXML/
├── Cargo.toml # Workspace manifest
├── crates/
│ ├── polyxml-core/ # Pure Rust core streaming engine
│ ├── polyxml-python/ # Python bindings (PyO3 + Maturin)
│ ├── polyxml-c/ # Universal C-ABI shared library + polyxml.h
│ └── polyxml-js/ # Node.js & TypeScript bindings (napi-rs)
├── bindings/
│ ├── cpp/ # Header-only modern C++20 wrapper (polyxml.hpp)
│ ├── go/ # Go package using Cgo (polyxml.go)
│ └── java/ # Java 22+ Project Panama FFI (PolyXML.java)
Licensed under the MIT License.