XML文件转Yaml脚本 Python实现XML到YAML的自动化转换

2次阅读

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

XML文件转Yaml脚本 Python实现XML到YAML的自动化转换

xml.etree.ElementTree 解析 XML 更稳,别碰 minidom

python 自带的 xml.etree.ElementTree 是处理 XML 的首选——轻量、标准、兼容性好。而 minidom 容易在嵌套文本、空白符、命名空间上出问题,尤其遇到带 CDATA 或注释的 XML 时,texttail 处理逻辑混乱,后续转 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=Falseyaml.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.textNone,别直接 .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.textelem[0].tail 分开存,不合并就转 YAML,会丢文字。这事得手动连起来,或者干脆限定只处理“纯数据型”XML(无内联标签),不然逻辑会迅速失控。

text=ZqhQzanResources