PureXML/CHANGELOG.md
Mihaela Mihaljevic e4b2e0127d feat(parser): accept raw bytes with UTF-8/UTF-16 encoding detection
Add PureXML.parse(bytes:) and events(bytes:) for raw [UInt8] input. The encoding
is detected following the XML sniff order (BOM first, then the <? byte pattern,
defaulting to UTF-8) and decoded with the Swift standard library only, so the
package stays Foundation-free and portable. UTF-8 and UTF-16 (both byte orders,
with or without a BOM) are supported, the encoding set the XML spec requires.
Malformed input (odd-length UTF-16) raises ParseError.malformedEncoding.

PureXML.Parsing.InputEncoding.detect(_:) exposes the detector. The lint rule
optional_data_string_conversion is disabled because its suggested fix is a
Foundation API this package cannot use. Reimplemented from the documented XML
byte-detection algorithm; no upstream code copied.
2026-06-08 00:52:56 +02:00

2.7 KiB

Changelog

All notable changes to PureXML are documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • Byte input with encoding detection. PureXML.parse(bytes:) and PureXML.events(bytes:) accept raw [UInt8] and detect the encoding (UTF-8 or UTF-16, with or without a byte-order mark) following the XML sniff order, then decode with the Swift standard library (no Foundation). PureXML.Parsing. InputEncoding.detect(_:) exposes the detector. Malformed input (such as an odd-length UTF-16 stream) raises ParseError.malformedEncoding.
  • Configurable, bounded-by-default parser limits (PureXML.Parsing.Limits): maximum nesting depth (default 256), name length, and content length, enforced during scanning. Protects against pathological input and keeps the recursive node model safe to build and tear down. Threaded through parse/events.
  • Initial package scaffold: root Swift package, namespacing under PureXML, and the portability and verification gates carried over from PureYAML.
  • XML node model (PureXML.Model): Node, Element, Attribute, and QualifiedName, preserving document order and node kinds.
  • XML emitter (PureXML.Emitting.Serializer) with pretty-printed and compact output and correct text and attribute escaping.
  • Structural validation (PureXML.Validation.Validator) for duplicate attribute names.
  • Streaming, iterative XML parser. PureXML.Parsing.EventReader is a pull-based event core that consumes input through a character-source closure and emits one Event at a time, holding only bounded state (an open-element stack and a small lookahead buffer). It never requires the whole document in memory and can drive chunked input. PureXML.Parsing.Parser builds a Model.Node tree iteratively over the event core (no recursion). Handles elements, attributes, text, the five predefined entities and numeric character references, comments, CDATA, and processing instructions. Safe by default: <!DOCTYPE> is rejected (no DTD/XXE).
  • Top-level API: PureXML.parse(_:), PureXML.parse(pulling:), and PureXML.events(_:) / PureXML.events(pulling:) for streaming.

Changed

  • The emitter is now iterative (explicit work stack, not recursion), mirroring libxml2's approach, so deep trees do not overflow the call stack.
  • The emitter escapes tab/newline/CR (and >) in attribute values so attributes round-trip through spec-compliant parsers; mixed content is no longer reformatted (formatting is suppressed for elements with text/CDATA children).