.. _xmlio-xpath-composition: XPath and XML Composition ========================= Useful XPath forms ------------------ ``XMLReader`` uses libxml2's full XPath 1.0 implementation. .. list-table:: Common query forms :header-rows: 1 :widths: 38 62 * - Expression - Meaning * - ``/project/title`` - Select from the document root. * - ``tasks/elem`` - Select relative to the current reader context. * - ``.`` - Select the current context element. * - ``item[2]`` - Select the second matching child, using XPath's one-based indexing. * - ``item[@id='B']`` - Select an element by an attribute predicate. * - ``//name`` - Select matching descendants throughout the document. * - ``@version`` - Select an attribute relative to the current context. * - ``m:score`` - 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. Namespaces ---------- XPath does not automatically adopt prefixes declared by the document. Register each prefix used by a query: .. code-block:: cpp xml.registerNamespace("m", "urn:example:metrics"); const double score = xmlio::read(xml, "/inventory/item/m:score"); The complete namespace and predicate example appears at the end of :ref:`xmlio-reading`. Deferred typed groups --------------------- ``GroupXml`` stores three pieces of information: ``id`` A type identifier read from a caller-selected field. ``xml`` The complete serialized subtree. ``path`` The root path to use when reparsing that subtree. ``read_xml_group`` extracts one group. ``read_xml_vector_group`` extracts every ```` 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 :ref:`xmlio-writing` uses fictional ``constant`` and ``linear`` operations to demonstrate this pattern without depending on another package. 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: .. code-block:: cpp 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. XML as metadata --------------- An ``XMLBufferWriter`` can create a small metadata record for storage in a database, archive, or other non-XML container: .. code-block:: cpp 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. 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 :ref:`xmlio-serialization`.