4. Types and XML Representations
4.1. Representation summary
xmlio deliberately uses a small set of predictable XML shapes.
C++ value |
XML shape |
Notes |
|---|---|---|
String, character, arithmetic value |
One scalar element |
Booleans are written as |
|
|
Both components use the scalar representation. |
Arithmetic |
Whitespace-separated scalar text |
Arithmetic vectors also accept |
Structured |
Repeated |
Includes strings and user-defined records. |
|
|
Each side may itself be structured. |
|
|
Duplicate keys within one document are rejected. |
|
The normal representation of |
An empty optional is omitted when writing. |
Repeated scalar siblings |
Several elements with the same name |
Use |
4.2. 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.
4.3. Complex numbers
<offset>
<re>1.25</re>
<im>-0.5</im>
</offset>
const auto offset =
xmlio::read<std::complex<double>>(xml, "/settings/offset");
4.4. Sequential containers
Arithmetic containers are compact:
<weights>0.25 0.5 0.25</weights>
Strings and records use explicit elements:
<labels>
<elem>small</elem>
<elem>portable</elem>
</labels>
A fixed-size std::array additionally checks that the XML contains exactly
the required number of values.
4.5. Pairs and maps
A pair is represented as:
<range>
<First>0</First>
<Second>10</Second>
</range>
A map is represented as an array of key-value records:
<catalog>
<elem><Key>blue</Key><Val>1</Val></elem>
<elem><Key>red</Key><Val>2</Val></elem>
</catalog>
Ordinary read replaces the destination map. Catalog workflows that combine
several documents should use read_map_into and choose a collision policy:
DuplicateKeyPolicy::errorReject a collision and leave the destination unchanged. This is the default.
DuplicateKeyPolicy::keep_existingKeep the destination value and ignore an incoming value with the same key.
DuplicateKeyPolicy::overwriteReplace the destination value with the incoming value.
Duplicate keys inside one incoming XML map are always errors, independent of the merge policy.
1/**
2 * @file catalog_merge.cpp
3 * @brief Merge map-shaped XML catalogs with an explicit collision policy.
4 */
5
6#include <xmlio/xmlio.hpp>
7
8#include <iostream>
9#include <map>
10#include <string>
11
12int main() {
13 auto update = xmlio::XMLReader::from_string(R"xml(
14<root>
15 <catalog>
16 <elem><Key>blue</Key><Val>7</Val></elem>
17 <elem><Key>green</Key><Val>3</Val></elem>
18 </catalog>
19</root>
20)xml");
21
22 std::map<std::string, int> catalog{{"blue", 1}, {"red", 2}};
23 xmlio::read_map_into(update, "/root/catalog", catalog,
24 xmlio::DuplicateKeyPolicy::overwrite);
25
26 for (const auto& [name, value] : catalog) {
27 std::cout << name << " = " << value << '\n';
28 }
29}
4.6. Optional values
Writing an empty std::optional omits the element. Reading into an optional
resets it when the path does not exist:
std::optional<int> retries;
xmlio::read(xml, "/settings/retries", retries);
Use a required field with an explicit default in application code when absence has a documented meaning:
int retries = 3;
xmlio::read_optional(xml, "/settings/retries", retries);
4.7. 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 <elem> container form so a
single parent names and owns the collection.