Why generate Go structs from an XML sample?
Go's encoding/xml is a tag-driven library: the
struct is the schema, and writing it by hand means
transcribing every element and attribute of a format somebody
else designed — RSS feeds, SOAP responses, SVG-ish exports,
config dialects — into PascalCase fields with exactly the right
xml: tags. That transcription is mechanical, and
the sample document already contains every fact it needs:
which elements repeat, which attributes come and go, which
leaf values look numeric. This converter reads those facts off
the sample and writes the structs, and — because a sample is
evidence, not a contract — it reports every judgement call it
made along the way.
How to use this tool
- Paste the XML, upload an .xml file, or drop one on the panel. The document must be well-formed; malformed input is reported with a line and column, not converted.
- Decide on type inference. Leave it on for samples you trust; turn it off if the values are identifiers that merely look numeric — a product code of 007 would become the integer 7.
- Press Generate Go structs. The root struct comes first.
- Read the notes. Pointer fields, sometimes-absent attributes, mixed content and always-empty elements are all listed there — review them before you rely on the result.
- Copy or download, add
XMLNamefields if you need root-name checking, and letgo vettake it from there.
The mapping rules
Elements. A child element becomes a field
tagged with its element name; one that repeats anywhere becomes
a slice; one that is absent from some parents becomes a pointer
so absence stays visible. Attributes become
fields tagged name,attr in their element's struct.
Text. A leaf element's text types the field —
integer-looking text is int, decimal is
float64, true/false is bool, anything
mixed across instances falls back to string with a
note. Text alongside child elements collects into a
Text field tagged ,chardata.
Shapes. Elements with identical structure
share one struct type. Entities in text and attribute values
are decoded before inference, exactly as a real parser would
hand them to you.
Worked example
Given this catalogue fragment (note the second book has no price):
<catalog count="2">
<book id="bk101">
<title>Go in Practice</title>
<price>39.95</price>
</book>
<book id="bk102">
<title>XML Field Guide</title>
</book>
</catalog> the converter emits (with two notes: price became a pointer, and the count attribute was inferred numeric):
type Catalog struct {
Count int `xml:"count,attr"`
Book []Book `xml:"book"`
}
type Book struct {
Id string `xml:"id,attr"`
Title string `xml:"title"`
Price *float64 `xml:"price"`
} Every judgement in that output is the sample's own evidence: the slice is the second book, the pointer is the missing price, the attribute type is the digit 2.