6. XPath and XML Composition
6.1. Useful XPath forms
XMLReader uses libxml2’s full XPath 1.0 implementation.
Expression |
Meaning |
|---|---|
|
Select from the document root. |
|
Select relative to the current reader context. |
|
Select the current context element. |
|
Select the second matching child, using XPath’s one-based indexing. |
|
Select an element by an attribute predicate. |
|
Select matching descendants throughout the document. |
|
Select an attribute relative to the current context. |
|
Select a name in a registered namespace. |
Scalar reads require one result. Use count, texts, read_many, or a
structured container when several matches are expected.
6.2. Namespaces
XPath does not automatically adopt prefixes declared by the document. Register each prefix used by a query:
xml.registerNamespace("m", "urn:example:metrics");
const double score = xmlio::read<double>(xml, "/inventory/item/m:score");
The complete namespace and predicate example appears at the end of Reading XML.
6.3. Deferred typed groups
GroupXml stores three pieces of information:
idA type identifier read from a caller-selected field.
xmlThe complete serialized subtree.
pathThe root path to use when reparsing that subtree.
read_xml_group extracts one group. read_xml_vector_group extracts every
<elem> from a container. This is useful when an application must read a type
name before choosing a concrete implementation from a registry.
The composition example in Writing XML uses fictional constant
and linear operations to demonstrate this pattern without depending on
another package.
6.4. Subtree extraction and provenance
context_str serializes a subreader’s context element. xpath_str
serializes every node selected by an expression. Both can be reparsed later or
inserted into a writer with writeXML.
Applications often preserve their resolved input document inside an output file:
xmlio::XMLBufferWriter result("result");
xmlio::write(result, "input", control);
xmlio::write(result, "status", "complete");
This makes an output self-describing without requiring the result schema to know every field in the input schema.
6.5. XML as metadata
An XMLBufferWriter can create a small metadata record for storage in a
database, archive, or other non-XML container:
xmlio::XMLBufferWriter metadata("metadata");
xmlio::write(metadata, "format", "toy-catalog");
xmlio::write(metadata, "version", 1);
const std::string stored = metadata.str();
auto restored = xmlio::XMLReader::from_string(stored);
Use str(false) or printRoot when the surrounding storage requires an
XML fragment without a declaration.
6.6. Combining catalogs
Reading several files into one catalog should make its collision behavior
visible. Deserialize each map normally and combine it in application code, or
use read_map_into with an explicit DuplicateKeyPolicy. The latter is
documented with a complete example in Types and XML Representations.