.. _xmlio-serialization: Types and XML Representations ============================= Representation summary ---------------------- ``xmlio`` deliberately uses a small set of predictable XML shapes. .. list-table:: Built-in serialization forms :header-rows: 1 :widths: 28 28 44 * - C++ value - XML shape - Notes * - String, character, arithmetic value - One scalar element - Booleans are written as ``true`` or ``false``. * - ``std::complex`` - ```` and ```` children - Both components use the scalar representation. * - Arithmetic ``vector``, ``list``, or ``array`` - Whitespace-separated scalar text - Arithmetic vectors also accept ```` input. * - Structured ``vector``, ``list``, or ``array`` - Repeated ```` children - Includes strings and user-defined records. * - ``std::pair`` - ```` and ```` children - Each side may itself be structured. * - ``std::map`` - ``......`` records - Duplicate keys within one document are rejected. * - ``std::optional`` - The normal representation of ``T``, or no element - An empty optional is omitted when writing. * - Repeated scalar siblings - Several elements with the same name - Use ``read_many`` and ``write_many``. Scalar values ------------- Floating-point output uses ``max_digits10`` so values can round trip without precision loss. Scalar conversion is locale independent and rejects trailing characters. Boolean input accepts ``true``, ``false``, their common uppercase forms, and ``1`` or ``0``. Complex numbers --------------- .. code-block:: xml 1.25 -0.5 .. code-block:: cpp const auto offset = xmlio::read>(xml, "/settings/offset"); Sequential containers --------------------- Arithmetic containers are compact: .. code-block:: xml 0.25 0.5 0.25 Strings and records use explicit elements: .. code-block:: xml small portable A fixed-size ``std::array`` additionally checks that the XML contains exactly the required number of values. Pairs and maps -------------- A pair is represented as: .. code-block:: xml 0 10 A map is represented as an array of key-value records: .. code-block:: xml blue1 red2 Ordinary ``read`` replaces the destination map. Catalog workflows that combine several documents should use ``read_map_into`` and choose a collision policy: ``DuplicateKeyPolicy::error`` Reject a collision and leave the destination unchanged. This is the default. ``DuplicateKeyPolicy::keep_existing`` Keep the destination value and ignore an incoming value with the same key. ``DuplicateKeyPolicy::overwrite`` Replace the destination value with the incoming value. Duplicate keys inside one incoming XML map are always errors, independent of the merge policy. .. literalinclude:: examples/catalog_merge.cpp :language: cpp :linenos: Optional values --------------- Writing an empty ``std::optional`` omits the element. Reading into an optional resets it when the path does not exist: .. code-block:: cpp std::optional retries; xmlio::read(xml, "/settings/retries", retries); Use a required field with an explicit default in application code when absence has a documented meaning: .. code-block:: cpp int retries = 3; xmlio::read_optional(xml, "/settings/retries", retries); Repeated siblings ----------------- ``write_many`` emits every range item under the same tag name. ``read_many`` reads scalar or string siblings selected by one XPath expression. Structured collections should normally use the standard ```` container form so a single parent names and owns the collection.