ddn.data.xml

ddn.data.xml is an idiomatic XML library for the D programming language.

This umbrella module is intended as the primary import for users. The public API is split into focused entrypoints (e.g. ddn.data.xml.parse, ddn.data.xml.dom, ddn.data.xml.write). This module re-exports the commonly used parts.

Public surface (v1)

The initial v1 public API is defined by the stable entrypoint modules below.

Currently available (implemented in this repository):

  • DOM:
  • XmlDocument, XmlElement, XmlNode and core node types (ddn.data.xml.dom)
  • Parsing:
  • parseDocument, parseFragment, XmlParseOptions (ddn.data.xml.parse)
  • Serialization:
  • writeXml, toXmlString, writeXmlTo, XmlWriteOptions (ddn.data.xml.write)
  • Streaming:
  • XmlReader, XmlEvent, XmlEventType (ddn.data.xml.stream)
  • Streaming (incremental):
  • XmlIncrementalReader, XmlIncrementalReaderOptions, XmlStreamStatus (ddn.data.xml.stream)
  • SAX (push parsing):
  • XmlSaxHandler, parseSax, XmlSaxOptions (ddn.data.xml.sax)
  • SAX (incremental):
  • XmlIncrementalSaxParser (ddn.data.xml.sax)
  • Querying:
  • XmlPath (ddn.data.xml.query)
  • XPath (phased):
  • XPathValue, XPathValueKind (ddn.data.xml.xpath)
  • XPointer (phased):
  • XPointer (ddn.data.xml.xpointer)
  • XInclude (phased):
  • processXInclude, XmlXIncludeOptions (ddn.data.xml.xinclude)
  • RelaxNG (native, phased):
  • parseRelaxNg, validateRelaxNgDocument (ddn.data.xml.relaxng)
  • XSD (native, phased):
  • parseXsd, validateXsdDocument (ddn.data.xml.xsd)
  • Validation (CLI-backed for now):
  • validateXsdFile, validateRelaxNgFile (ddn.data.xml.validate)
  • Canonicalization:
  • canonicalize (ddn.data.xml.c14n)

Planned (to be implemented/expanded in subsequent tasks, keeping these names stable):

  • Full XML 1.0 name/character support (beyond the current ASCII-focused subset).
  • Full entity and DTD parsing (internal/external subsets), with robust safety limits.
  • Richer querying surface area (more XPath features).
  • Additional validation modes (DTD validation, richer schema APIs, non-CLI implementations).

Stability rules

  • Stable modules:
  • ddn.data.xml and the public entrypoints it re-exports.
  • ddn.data.xml.dom.*.
  • Unstable modules (not part of the public API):
  • ddn.data.xml.internal.*.
  • Test helpers (package-only by convention):
  • ddn.data.xml.testing.*.

Examples

Parse a document

--- import ddn.data.xml.parse : parseDocument;

auto doc = parseDocument("<root><child>t</child></root>"); assert(doc.documentElement.lexicalName == "root"); ---

Build a document (DOM)

--- import ddn.data.xml.dom.document : XmlDocument;

auto doc = new XmlDocument(); auto root = doc.createRootElement("root"); root.addChildElement("child").withAttribute("id", "1").addText("t"); ---

Serialize a document

--- import ddn.data.xml.write : writeXml;

string xml = writeXml(doc); ---

Streaming reader (pull)

--- import ddn.data.xml.stream : XmlEventType, XmlReader;

auto r = new XmlReader("t"); while (!r.empty) { // Consume events. if (r.front.type == XmlEventType.TEXT) assert(r.front.text == "t"); r.popFront(); } ---

Incremental streaming reader (chunked input)

--- import ddn.data.xml.stream : XmlIncrementalReader, XmlStreamStatus, XmlEventType;

auto reader = new XmlIncrementalReader(); reader.feed("<root><child/>"); reader.feed("</root>"); reader.markEndOfStream(); while (reader.advance() == XmlStreamStatus.READY) { if (reader.front().type == XmlEventType.START_ELEMENT) import std.stdio : writeln; // process reader.front() ... } ---

Incremental SAX (chunked input)

--- import ddn.data.xml.sax : XmlSaxHandler, XmlIncrementalSaxParser, XmlSaxOptions, XmlSaxAttribute; import ddn.data.xml.stream : XmlStreamStatus; import ddn.data.xml.errors : XmlLocation;

class MyHandler : XmlSaxHandler { override void startElement(string name, const(XmlSaxAttribute)[] attrs, XmlLocation loc) @safe { } override void endElement(string name, XmlLocation loc) @safe { } override void text(string value, XmlLocation loc) @safe { } override void comment(string value, XmlLocation loc) @safe { } override void processingInstruction(string target, string data, XmlLocation loc) @safe { } override void cdata(string value, XmlLocation loc) @safe { } override void doctype(string raw, XmlLocation loc) @safe { } }

auto parser = new XmlIncrementalSaxParser(new MyHandler()); parser.feed("<root><child/></root>"); parser.markEndOfStream(); parser.pump(); ---

Query elements (XPath-like)

--- import ddn.data.xml.query : XmlPath; import ddn.data.xml.parse : parseDocument;

auto doc = parseDocument("<root></root>"); auto path = XmlPath.parse("a[@id='2']"); auto result = path.select(doc.documentElement); assert(result.length == 1); ---

Canonicalize for stable comparisons

--- import ddn.data.xml.c14n : canonicalize; import ddn.data.xml.parse : parseDocument;

auto doc = parseDocument("<root b='2' a='1'/>" ); assert(canonicalize(doc).canFind("<root a=\"1\" b=\"2\"/>") ); ---