XML to Python dataclasses
Python's standard library parses XML with xml.etree.ElementTree, but the result is a tree of generic Element objects accessed through find() and get() calls. This XML to Python generator derives typed dataclasses from a sample document, so you can load the data once and work with attributes like config.database.port afterwards, with editor completion and type checking.
Example: a configuration file
<config env="production">
<database host="db.internal" port="5432">
<name>shop</name>
<pool>20</pool>
</database>
<feature enabled="true">search</feature>
<feature enabled="false">beta-checkout</feature>
</config>
@dataclass
class Database:
name: str
pool: int
host: str
port: int
@dataclass
class Feature:
value: str
enabled: bool
@dataclass
class Config:
database: Database
feature: List[Feature]
env: str
The <feature> elements have both an attribute and text, so Feature gets an enabled field for the attribute and a value field for the text. Attribute values such as port="5432" are typed from their content, here int.
How the XML is mapped
The root element (<config>) names the top-level class, unless you enter your own name. Attributes and child elements are merged into the same class, so a field could come from either; check the XML when you write parsing code. Namespace prefixes are dropped, the XML declaration is ignored, and an empty element such as <notes/> becomes an empty string. Because an element that appears in some records but not others becomes Optional, pasting a document with several varied records gives the most accurate classes.
Filling the dataclasses from ElementTree
import xml.etree.ElementTree as ET
root = ET.fromstring(xml_text)
db = root.find("database")
config = Config(
database=Database(name=db.findtext("name"), pool=int(db.findtext("pool")),
host=db.get("host"), port=int(db.get("port"))),
feature=[Feature(value=f.text, enabled=f.get("enabled") == "true")
for f in root.findall("feature")],
env=root.get("env"),
)
ElementTree returns every value as a string, so conversions like int() and the boolean comparison are needed. The from_dict helpers generated in full mode expect a dictionary shaped like the tool's own XML-to-object mapping (attributes as plain keys, element text under value); libraries such as xmltodict use different conventions (@attr and #text), so rename keys if you use them.
Security and accuracy notes
- For XML from untrusted sources, parse with
defusedxml, which protects the standard parsers against entity-expansion attacks. - Repeated elements are only detected as lists if the sample contains at least two of them.
- Numeric-looking text such as ZIP codes loses leading zeros when typed as
int; switch those fields tostr.
Format the generated module with the Python Formatter. To inspect the XML's structure first, use the XML Viewer, or convert it with XML to JSON. Everything runs in your browser.