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:
  • XPathValue, XPathValueKind, XPathExpression, evaluateXPath (ddn.data.xml.xpath)
  • XPointer:
  • XPointer, XPointerPart, XPointerKind (ddn.data.xml.xpointer)
  • XInclude:
  • processXInclude, XmlXIncludeOptions (ddn.data.xml.xinclude)
  • RelaxNG:
  • parseRelaxNg, validateRelaxNgDocument (ddn.data.xml.relaxng)
  • XSD (native):
  • parseXsd, parseXsdFromFile, validateXsdDocument, XsdSchema, XsdParseOptions (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.
  • XPath namespace axis and processing-instruction() literal argument support.
  • 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("<a><b/>t</a>");
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><a/><a id='2'/></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\"/>") );

No exported symbols.