如何将Python中构建的类实例转换为层级清晰的XML结构?
Python类实例转结构化XML方案
手动构建XML(最灵活可控)
直接用Python内置的xml.etree.ElementTree模块,递归遍历类实例属性,手动构建XML层级结构,标签和内容完全自定义。
步骤示例:
- 定义业务类(已填充随机数据)
import xml.etree.ElementTree as ET import random from datetime import datetime class Customer: def __init__(self): self.id = random.randint(1000, 9999) self.name = f"Customer_{random.randint(1, 100)}" self.email = f"user{random.randint(1, 100)}@example.com" class Item: def __init__(self): self.sku = f"SKU_{random.randint(100, 999)}" self.quantity = random.randint(1, 5) self.price = round(random.uniform(10.0, 100.0), 2) class Order: def __init__(self): self.order_id = f"ORD_{random.randint(10000, 99999)}" self.order_date = datetime.now().strftime("%Y-%m-%d") self.customer = Customer() self.items = [Item() for _ in range(random.randint(1, 3))]
- 递归转换函数:类实例转XML元素
def instance_to_xml(instance, parent=None): # 用类名作为XML标签,也可自定义为小写或别名 tag = instance.__class__.__name__ element = ET.Element(tag) if parent is None else ET.SubElement(parent, tag) for attr_name, attr_value in instance.__dict__.items(): # 基础类型直接生成子元素 if isinstance(attr_value, (str, int, float, bool)): child = ET.SubElement(element, attr_name) child.text = str(attr_value) # 列表类型生成父容器,再递归处理每个元素 elif isinstance(attr_value, list): list_container = ET.SubElement(element, attr_name) for item in attr_value: instance_to_xml(item, list_container) # 自定义类实例,递归嵌套处理 elif hasattr(attr_value, '__dict__'): instance_to_xml(attr_value, element) return element
- 生成并美化XML
# 创建顶层实例 order = Order() # 转换为XML根元素 root = instance_to_xml(order) # 美化XML格式(ElementTree默认无缩进,手动添加) def indent(elem, level=0): i = "\n" + level*" " if len(elem): if not elem.text or not elem.text.strip(): elem.text = i + " " if not elem.tail or not elem.tail.strip(): elem.tail = i for elem in elem: indent(elem, level+1) if not elem.tail or not elem.tail.strip(): elem.tail = i else: if level and (not elem.tail or not elem.tail.strip()): elem.tail = i indent(root) # 输出XML字符串 xml_str = ET.tostring(root, encoding='utf-8', method='xml').decode('utf-8') print(xml_str) # 保存到文件 ET.ElementTree(root).write('output.xml', encoding='utf-8', xml_declaration=True)
基于Dataclass的序列化
如果用dataclasses定义类,代码更简洁规范,且可直接复用上面的转换逻辑(dataclass实例可通过__dict__访问属性):
from dataclasses import dataclass, field @dataclass class Customer: id: int = field(default_factory=lambda: random.randint(1000, 9999)) name: str = field(default_factory=lambda: f"Customer_{random.randint(1, 100)}") email: str = field(default_factory=lambda: f"user{random.randint(1, 100)}@example.com") @dataclass class Item: sku: str = field(default_factory=lambda: f"SKU_{random.randint(100, 999)}") quantity: int = field(default_factory=lambda: random.randint(1, 5)) price: float = field(default_factory=lambda: round(random.uniform(10.0, 100.0), 2)) @dataclass class Order: order_id: str = field(default_factory=lambda: f"ORD_{random.randint(10000, 99999)}") order_date: str = field(default_factory=lambda: datetime.now().strftime("%Y-%m-%d")) customer: Customer = field(default_factory=Customer) items: list[Item] = field(default_factory=lambda: [Item() for _ in range(random.randint(1, 3))]) # 直接复用instance_to_xml和indent函数
第三方库简化流程(可选)
不想写递归逻辑的话,可用dicttoxml库,先把类实例转成字典,再转XML:
from dicttoxml import dicttoxml import xml.dom.minidom # 类实例转字典 def instance_to_dict(instance): if isinstance(instance, list): return [instance_to_dict(item) for item in instance] if hasattr(instance, '__dict__'): return {k: instance_to_dict(v) for k, v in instance.__dict__.items()} return instance # 转换并美化 order = Order() order_dict = instance_to_dict(order) xml_str = dicttoxml(order_dict, root_name='Order', attr_type=False) pretty_xml = xml.dom.minidom.parseString(xml_str).toprettyxml() print(pretty_xml)
关于pickle的说明
pickle是Python专用的对象序列化工具,输出二进制格式,仅用于Python环境内的对象持久化/传输,完全无法生成标准可读XML,不适合你的需求。
内容的提问来源于stack exchange,提问作者kompressor
相关产品推荐
相关产品推荐

