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. |
||
|---|---|---|
| .githooks | ||
| .github | ||
| docs/rules | ||
| scripts | ||
| Sources | ||
| Tests | ||
| .gitattributes | ||
| .gitignore | ||
| .swiftformat | ||
| .swiftlint.yml | ||
| AGENTS.md | ||
| ATTRIBUTION.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| Package.swift | ||
| README.md | ||
| SECURITY.md | ||
| SUPPORT.md | ||
PureXML
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):Serializerturns 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.EventReaderis a pull-based event core that consumes input through a character-source closure and emits oneEventat a time, never holding the whole document in memory (it drives chunked input).Parserbuilds aModel.Nodetree 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.