Why generate Python dataclasses from an XML sample?
Python programs read a great deal of XML they did not design — RSS and Atom feeds, sitemaps, office-document internals, legacy SOAP and config dialects — and the hand-written half of every such reader is a set of classes that transcribe the format field by field. 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 dataclasses, 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.
- Optionally name the root class; left blank, it takes the root element's name. Decide on type inference — leave it on for samples you trust, off if values are identifiers that merely look numeric.
- Press Generate Python dataclasses. Classes are emitted in dependency order, so the file runs top to bottom.
- Read the notes. Optional fields, moved fields, mixed content and always-empty elements are all listed there — review them before you rely on the result.
- Copy or download, then pair the classes with your parser of choice (
xml.etree,lxml, or a binding library) — the classes describe the shape; the walking is your code's job.
The mapping rules
Elements. A child element becomes a field; one
that repeats anywhere becomes a List[…]; one that
is absent from some parents becomes Optional[…] = None
so absence stays visible, and optional fields move after the
required ones because dataclasses demand it — the move is
noted. Attributes become fields too, declared
before the child fields. Text. A leaf element's
text types the field — integer-looking text is int,
decimal is float, true/false is bool,
anything mixed across instances falls back to str
with a note. Text alongside child elements collects into a
text field. Shapes. Elements with
identical structure share one dataclass. Field names are
snake_case; whenever that differs from the XML name, a trailing
comment keeps the original — nothing is renamed silently.
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:
from dataclasses import dataclass
from typing import List, Optional
@dataclass
class Book:
id: str # attribute
title: str
price: Optional[float] = None
@dataclass
class Catalog:
count: int # attribute
book: List[Book] Every judgement in that output is the sample's own evidence: the list is the second book, the Optional is the missing price, the attribute types are the digits themselves.