Apache Xalan... the Swift Package

Apache Xalan

... is an open-source software library from the Apache Software Foundation that implements the XSLT 1.0 and XPath 1.0 standards. It is primarily used to transform XML documents into HTML, plain text, or other XML types.

Here I'm releasing a free Swift package: XalanSwift that comes with a prebuilt static lib of Xalan-C++ in an XCFramework with a Swift wrapper around it, for Apple Silicon (macOS/iOS). Instructions are included if you may wish to build your own x64 static libs.

Use cases:

XSLT — transform XML with stylesheets

  • Transform an in-memory XML string → string (transform(xml:stylesheet:))
  • Transform raw DataData (any encoding the XML prolog declares)
  • Transform file → file on disk (transformFile(xml:stylesheet:output:))
  • Transform file → string (read from disk, get result in memory)
  • Transform using the document's own <?xml-stylesheet?> PI (no separate stylesheet arg)
  • Render to HTML, XML, or plain text output (driven by xsl:output method=)

Reuse for performance (batch / repeated work)

  • Compile a stylesheet once, apply it to many documents (compileStylesheet)
  • Parse a document once, run many stylesheets against it (parse)
  • Mix-and-match compiled stylesheets × parsed sources for N×M transforms cheaply

Pass data into stylesheets

  • Set top-level xsl:param values as: literal strings (any quotes handled), numbers, or raw XPath expressions
  • Clear/reset parameters between runs

Control the output

  • Toggle DTD/schema validation of the source
  • Set indentation amount (pretty-print)
  • Override the output encoding (UTF-8, ISO-8859-1, …)

XPath — query XML without transforming

  • Parse a document from a string or file into a reusable query tree
  • Evaluate any XPath 1.0 expression and get a typed result: node-set, number, string, or boolean
  • Coerce any result to .string / .number / .boolean (XPath 1.0 rules)
  • Enumerate matched nodes (each with name + string value)
  • Evaluate relative to a context node (context: selects where the expression runs)
  • Convenience one-liners: string(_:), number(_:), boolean(_:), nodes(_:)

XPath/XSLT power features (verified in the stress tests)

  • Namespaces — prefixed lookups, default-namespace handling, namespace shadowing (namespace-uri(), local-name())
  • Aggregationcount(), sum(), with correct NaN/empty handling
  • Sortingxsl:sort numeric vs. lexical
  • Grouping — Muenchian grouping via xsl:key / generate-id()
  • Recursion & deep traversal, attribute selection, predicates, self-referential data
  • Unicode round-trips (Greek/CJK/emoji), CDATA, escaped entities, mixed content

Things you'd realistically build with it

  • Render XML data → HTML pages / reports / emails
  • Format conversion: legacy XML → JSON-ish text, CSV, Markdown, other XML schemas
  • Data extraction / scraping values out of XML feeds, configs, SOAP/RSS/Atom, SVG, Office Open XML parts
  • Validation & assertions ("does this node exist / equal X?") via boolean XPath
  • Config/document pipelines where templates are authored separately and fed parameters at runtime
  • A CLI or service that batch-transforms many files with a cached compiled stylesheet

Operational properties

  • Errors surface as Swift XalanError (message + code); parse/eval failures are catchable
  • Auto-initialized, thread-safe global state; one XSLTProcessor per thread
  • Self-contained: ships a prebuilt XalanCore.xcframework (static Xalan + Xerces) — no Homebrew, no system dylibs, no external paths

Current limits (by design)

  • XSLT 1.0 / XPath 1.0 only (Xalan doesn't do 2.0/3.0)
  • No remote http(s) fetching in document()/includes (Xerces built network-off) — local files + in-memory work fully
2 Likes