XML to C Struct Generator
One struct per element, typed from the values in your sample
XML Input
C Header
What this generator gives you
Hand-writing C structs for an XML config or device payload is tedious, and it is easy to miss a field that only shows up in some records. Paste a sample here and you get a header with one struct per element name. Attributes and child elements become members, numbers become int, int64_t or double, true/false becomes bool, and everything else is a char *.
Repeated elements turn into a pointer plus a size_t count (Sensor *sensor; size_t sensor_count;), because C has no built-in list. An element that is missing from some records is still a member, but it is marked optional in a comment, and an optional nested struct becomes a pointer that you can leave NULL. Fixed-width integers come from <stdint.h> and bool from <stdbool.h>, so the header compiles as C99.
What you do not get is a parser. The header only describes the data; filling the structs is up to you, usually with libxml2 on Linux or Expat on small targets. The conversion runs in your browser, so the XML is not uploaded anywhere.
How to use it
Three steps, and the output refreshes as you type.
Paste or upload a representative sample
Paste XML into the XML Input panel or hit Upload. Include at least two copies of anything that repeats, plus the optional bits, so the generator can see which members are arrays and which may be missing. Sample loads a small device config:
<deviceConfig firmware="2.4.1">
<sensor id="1" type="temperature">
<pin>4</pin>
<threshold>72.5</threshold>
</sensor>
<sensor id="2" type="humidity">
<pin>5</pin>
<threshold>60.0</threshold>
</sensor>
</deviceConfig>Not sure the XML is well-formed? Run it through the XML Validator first; parse errors show up in the output panel either way.
Name the root struct and pick the style
Root struct renames the top-level struct (leave it empty to use the root element name). With typedef structs on you get typedef struct Sensor { ... } Sensor;; turn it off for plain struct Sensor declarations if your codebase avoids typedefs.
Copy or download the header
Download saves a .h file named after the root struct, with an include guard already in place. Copy puts it on your clipboard.
Where it helps
Device and firmware configs
Many gateways and PLC tools export settings as XML. Generate the structs once, then write a small loader that copies values from the parsed tree into them.
Reading vendor payloads
When a supplier sends order or telemetry files as XML, the struct layout gives you a checklist of every field your parser needs to handle, including the ones that only appear sometimes.
Starting a libxml2 or Expat loader
The comments next to each member name the XML attribute or element it came from, which maps neatly onto xmlGetProp and child-node lookups.
Documenting a format
A header is a compact way to show teammates what a file contains. It is easier to review than a long sample document.
Common questions
Does the generated C parse the XML for me?
No. It is a header with struct definitions only. Fill the structs with the XML library you already use, for example libxml2 or Expat.
How are repeated elements handled?
Any element that appears more than once inside the same parent becomes a pointer plus a count: Sensor *sensor; and size_t sensor_count;. You allocate the array and set the count when you parse.
How does it decide between int, int64_t, double and char *?
It looks at every value of that field in your sample. Whole numbers that fit in 32 bits become int, bigger ones int64_t, decimals double, true/false become bool. Values with a leading zero (zip codes, part numbers) stay strings, and so does anything that does not fit in 64 bits. If a numeric-looking field is really an ID, change it to char *.
What happens with an element that contains itself?
Recursive structures such as a <category> inside a <category> are emitted as a pointer (struct Category *category;), since a struct cannot contain itself by value.
Which C standard does the header need?
C99 or later. It uses <stdbool.h>, <stdint.h> and <stddef.h>. Member names that clash with C or C++ keywords (default, class) get a trailing underscore, so the header also compiles when included from C++.
Is my XML uploaded?
No. Parsing and code generation happen in your browser with the built-in DOMParser. Inputs over 256 KB are rejected; a few representative records are enough anyway.
Related tools
Other converters and checks that pair well with this one: