XML to C++ Struct Generator
C++17 structs with std::vector and std::optional, typed from your sample
XML Input
C++ Header
What you get
Paste an XML document and the generator writes a header with one plain struct per element name. Attributes and child elements become members with sensible defaults (int qty = 0;), text is std::string, and an element that repeats becomes a std::vector.
Fields that are missing from some records can be wrapped in std::optional, so "not present" and "empty" stay different. A type that contains itself, such as nested categories, gets a std::unique_ptr and a forward declaration, since a struct cannot hold itself by value. Structs are ordered so every type is defined before it is used.
The header is data only. Loading the XML into it is your part, typically a few lines per struct with pugixml or tinyxml2. The conversion runs in your browser; nothing is uploaded.
How to use it
Paste, adjust two settings, copy. The output updates as you type.
Paste a sample with the variety you care about
Drop XML into XML Input or use Upload. Include repeated elements at least twice and the optional ones at least once, so the generator can tell vectors and optionals apart. Sample loads a delivery route:
<route id="RT-88" carrier="Northwind Freight">
<stop seq="1"><city>Austin</city><lat>30.2672</lat></stop>
<stop seq="2"><city>San Antonio</city><lat>29.4241</lat><note>Dock 4</note></stop>
</route>Malformed XML is reported in the output panel. The XML Formatter makes a messy file easier to read before you convert it.
Set the namespace and optional handling
Root struct renames the top-level type (empty means the root element name). Namespace accepts nested names like shop::model, which needs C++17. Uncheck std::optional for missing fields if you would rather keep plain members and check for empty values yourself.
Copy or download
Download saves a .hpp with #pragma once and only the standard headers it needs. Copy grabs the same text.
Where it helps
Loading config files
Game settings, CAD exports and test-rig configs are often XML. Generate the structs, then fill them from a pugixml document in a single loader function.
Integrating a partner feed
A struct per element makes it obvious which fields a partner's XML can carry, including the rare ones that only show up in some files.
Replacing ad-hoc maps
If your code passes XML values around as string maps, typed structs catch typos at compile time and make refactors safer.
Code review and docs
A short header is an easy way to agree on a data shape with the team before anyone writes parsing code.
Common questions
Which C++ standard is required?
C++17, for std::optional and nested namespace definitions. With an empty namespace and optionals turned off the output also compiles as C++11.
Does it generate parsing code?
No, only the structs. Reading the XML into them is left to your XML library. With pugixml that is usually node.child("city").text().as_string() per field.
How are types chosen?
From the values in your sample: whole numbers become int or std::int64_t, decimals double, true/false bool, and everything else std::string. A value with a leading zero, such as a zip code, stays a string.
What about attributes and text on the same element?
Both become members. For <price currency="USD">24.99</price> you get a Price struct with currency and value.
Why is one member a std::unique_ptr?
That type contains itself somewhere down the tree, for example a category inside a category. A struct cannot contain itself by value, so the generator uses a pointer and adds a forward declaration.
Is the XML sent anywhere?
No. It is parsed in your browser. Files over 256 KB are rejected to keep the page responsive; a representative sample is enough to infer the types.
Related tools
Other converters and checks that pair well with this one: