PureXML
Go to file
Mihaela Mihaljevic 0f3086c8e6 docs(roadmap): add Apple-palette mermaid roadmap and the roadmap gate
Follow the mihaela-agents mermaid rule: add a README roadmap using the TileDown
Apple-color status classes (done/review/epic/todo), legend block first, then a
libxml2-parity roadmap showing shipped vs open work. Add docs/rules/mermaid.md
and scripts/check-roadmap.sh (wired into check-all.sh) so the diagrams stay
mechanically checkable.
2026-06-08 00:58:50 +02:00
.githooks chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
.github chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
docs/rules docs(roadmap): add Apple-palette mermaid roadmap and the roadmap gate 2026-06-08 00:58:50 +02:00
scripts docs(roadmap): add Apple-palette mermaid roadmap and the roadmap gate 2026-06-08 00:58:50 +02:00
Sources feat(parser): accept raw bytes with UTF-8/UTF-16 encoding detection 2026-06-08 00:52:56 +02:00
Tests feat(parser): accept raw bytes with UTF-8/UTF-16 encoding detection 2026-06-08 00:52:56 +02:00
.gitattributes chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
.gitignore chore: extend .gitignore with editor, venv, node, and local-settings entries 2026-06-07 23:35:22 +02:00
.swiftformat chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
.swiftlint.yml feat(parser): accept raw bytes with UTF-8/UTF-16 encoding detection 2026-06-08 00:52:56 +02:00
AGENTS.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
ATTRIBUTION.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
CHANGELOG.md feat(parser): accept raw bytes with UTF-8/UTF-16 encoding detection 2026-06-08 00:52:56 +02:00
CLAUDE.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
CODE_OF_CONDUCT.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
CONTRIBUTING.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
LICENSE chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
Package.swift chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
README.md docs(roadmap): add Apple-palette mermaid roadmap and the roadmap gate 2026-06-08 00:58:50 +02:00
SECURITY.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00
SUPPORT.md chore: scaffold PureXML pure-Swift XML package 2026-06-07 23:20:20 +02:00

PureXML

macOS CI Linux CI WASI CI

PureXML is a dependency-free XML package written entirely in Swift.

The goal is a Linux-, Windows-, and WebAssembly-compatible XML reader/writer that does not pull in libxml2, expat, or Foundation's XMLParser. The package is intentionally strict about portability:

  • no external SwiftPM dependencies
  • no bundled C sources
  • no Foundation requirement in the library target
  • root Swift package layout
  • macOS, Linux, Windows, and WASI build gates

It is a sibling project to PureYAML and follows the same structure, rules, and verification gates.

Roadmap

The roadmap uses the TileDown Mermaid palette: green for shipped work, yellow for review, purple for epic grouping, and gray for open work.

flowchart TB
  classDef done fill:#ddf9e4,stroke:#34c759,color:#111827
  classDef review fill:#fff7d6,stroke:#ffcc00,color:#111827
  classDef epic fill:#f2e5ff,stroke:#af52de,color:#111827
  classDef todo fill:#f2f4f7,stroke:#8e8e93,color:#111827
  LDone["In main now"]:::done
  LReview["PR in review"]:::review
  LEpic["Epic grouping"]:::epic
  LTodo["Open issue, no PR"]:::todo
  LDone --> LReview
  LReview --> LEpic
  LEpic --> LTodo

Capability is being grown toward libxml2 parity in pure Swift, guided by the private PureXML-research analysis. Shipped vs open work:

flowchart TB
  classDef done fill:#ddf9e4,stroke:#34c759,color:#111827
  classDef review fill:#fff7d6,stroke:#ffcc00,color:#111827
  classDef epic fill:#f2e5ff,stroke:#af52de,color:#111827
  classDef todo fill:#f2f4f7,stroke:#8e8e93,color:#111827
  Model["Node model + emitter"]:::done
  Stream["Streaming pull parser"]:::done
  Escape["Iterative emitter + escaping"]:::done
  Limits["Bounded-by-default limits"]:::done
  Bytes["Byte input + encoding detection"]:::done
  Namespaces["Namespace resolution"]:::todo
  ByteStream["Streaming byte decode"]:::todo
  DTD["Optional DTD + entities"]:::todo
  Validation["Schema validation"]:::todo
  XPath["XPath 1.0"]:::todo
  Model --> Stream
  Stream --> Escape
  Escape --> Limits
  Limits --> Bytes
  Bytes --> Namespaces
  Namespaces --> ByteStream
  ByteStream --> DTD
  DTD --> Validation
  Validation --> XPath

Status

The node model, the emitter, and a streaming parser are implemented and usable today.

  • Model (PureXML.Model): Node, Element, Attribute, QualifiedName. Preserves document order and the distinction between text, CDATA, comments, and processing instructions.
  • Emitting (PureXML.Emitting): Serializer turns a node tree into well-formed XML, with pretty-printed and compact options and correct text and attribute escaping.
  • Validation (PureXML.Validation): structural checks such as duplicate attribute names. Schema validation (DTD/XSD/RELAX NG) is out of scope for the library target.
  • Parsing (PureXML.Parsing): a streaming, iterative parser. EventReader is a pull-based event core that consumes input through a character-source closure and emits one Event at a time, never holding the whole document in memory (it drives chunked input). Parser builds a Model.Node tree iteratively over the event core. Handles elements, attributes, text, the five predefined entities and numeric character references, comments, CDATA, and processing instructions. Safe by default: <!DOCTYPE> is rejected, which removes the DTD-based threat classes (XXE, entity-expansion DoS). DTD support, namespaces-as-resolved-URIs, and validation are deliberate future layers.

Usage

import PureXML

// Build a tree and emit it (works today).
let element = PureXML.Model.Element(
    "book",
    attributes: [.init("id", "bk101")],
    children: [.element(.init("title", children: [.text("XML Developer's Guide")]))],
)

let xml = PureXML.serialize(.element(element))
try PureXML.validate(.element(element))

// Parse it back into a tree.
let node = try PureXML.parse(xml)

// Or stream events without building a tree (drives chunked input too).
var reader = PureXML.events(xml)
while let event = try reader.next() {
    // handle .startElement / .characters / .endElement / ...
}

Attribution

PureXML is informed by the behavior of established XML parsers (libxml2, expat, Foundation's XMLParser) and by the W3C XML 1.0 specification, but it does not copy their implementation into Sources/. See ATTRIBUTION.md.

Development Contract

PureXML must stay dependency-free and portable. Before merging changes:

  • Swift tools version: 6.1
  • Package products: PureXML
  • SwiftPM dependencies: none
  • Hosted CI matrix: macOS, Linux, Windows, and WASM
bash scripts/check-all.sh

That command expands to:

bash scripts/check-style.sh
bash scripts/check-namespacing.sh
bash scripts/check-forbidden-patterns.sh
swiftformat . --config .swiftformat --lint
swiftlint --config .swiftlint.yml --strict
swift build
swift test

License

MIT.