xml.etree.elementtree 是解析 xml 的首选,比 minidom 更稳定;需注意命名空间注册、重复节点转列表、空节点判空、属性与 cdata 显式处理,并用 yaml.dump(…, default_flow_style=false, allow_unicode=true, sort_keys=false) 保证 yaml 可读性与兼容性。

用 xml.etree.ElementTree 解析 XML 更稳,别碰 minidom
python 自带的 xml.etree.ElementTree 是处理 XML 的首选——轻量、标准、兼容性好。而 minidom 容易在嵌套文本、空白符、命名空间上出问题,尤其遇到带 CDATA 或注释的 XML 时,text 和 tail 处理逻辑混乱,后续转 YAML 会多出空字段或丢内容。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 统一用
ET.parse()加载文件,或ET.fromstring()加载字符串 - 避免手动拼接节点名和文本,改用递归遍历 +
elem.tag/elem.attrib/elem.text.strip() - 如果 XML 有命名空间,提前用
ET.register_namespace()注册,否则find()可能查不到节点
YAML 输出必须控制 default_flow_style=False
不设这个参数,小结构(比如单层字典)会被压成一行,比如 {name: alice, age: 25},可读性差,且不符合多数配置文件习惯;更麻烦的是,PyYAML 默认把 None 序列化成 NULL(首字母大写),而很多 YAML 解析器只认小写的 null,导致下游解析失败。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 始终传参
default_flow_style=False给yaml.dump() - 加
allow_unicode=True防止中文被转成u4f60这类编码 - 用
sort_keys=False保留原始 XML 节点顺序(XML 本身有序,YAML 字典默认重排)
XML 中重复子节点要转成列表,不是覆盖
常见错误是把同名子节点当成单个值处理,比如:<items><item>a</item><item>b</item></items>,若直接用 dict[item.tag] = value,后一个 item 会覆盖前一个,最终只剩 b。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 遇到重复标签,先检查父节点下同名子节点数量:用
len(parent.findall(child_tag)) > 1 - 是列表就统一转成 Python
list,哪怕只有一个元素也包一层(保持结构一致,避免下游判断分支) - 注意空节点:如
<price></price>,elem.text是None,别直接.strip(),先判空
特殊字符和属性要显式处理,不能依赖默认行为
XML 属性(attr="value")不会自动进 elem.text,容易漏掉;CDATA 内容里的换行、缩进会被原样保留,直接塞进 YAML 字符串会导致格式错乱;还有 &、 这类实体,在解析后已转义为 <code>&、,但若中间经过字符串拼接又没转回,可能触发 YAML 解析错误。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 属性统一收进
attrib字段,例如加前缀@:生成{"@id": "123", "text": "hello"} - 对含换行/大量空白的文本,用 YAML 的
|块样式:需在yaml.dump()前给该值打标记,比如用yaml.scalarstring.LiteralScalarString(text) - 不用
xml.sax或正则预处理 XML——太容易破坏结构,交给ElementTree解析后再规整更可靠
最常被忽略的是混合内容(mixed content):比如 <p>Hello <em>world</em>!</p>,elem.text 和 elem[0].tail 分开存,不合并就转 YAML,会丢文字。这事得手动连起来,或者干脆限定只处理“纯数据型”XML(无内联标签),不然逻辑会迅速失控。