YAML与XML无一一对应关系,映射需人工定义规则;Python中可用pyyaml+ElementTree手动构建XML树,yq仅适用于简单扁平化转换;命名空间、CDATA、属性等语义需额外约定。

YAML 和 XML 的结构差异直接影响映射逻辑
YAML 是以缩进和键值对为核心的序列化格式,天然支持嵌套、锚点、合并等高级特性;XML 则依赖显式标签、属性、文本节点和命名空间。二者没有一一对应关系,强行“转换”必然丢失语义或引入歧义。比如 !!null、!!timestamp、多行字面量(|)在 XML 中无原生等价物;而 XML 的 xmlns、xml:lang、处理指令()在 YAML 中也不存在。
因此,所谓“映射”,实际是按需定义规则:你决定哪个 YAML 键变成 XML 标签名,哪些值转为属性还是子元素,数组如何展开,空值怎么表示( 还是 ),是否保留注释(YAML 注释不进 AST,XML 注释需显式写入)。
用 Python 的 pyyaml + xml.etree.ElementTree 手动构建 XML 树
这是最可控的方式,适合结构固定、需精细控制命名空间或特殊节点的场景。核心思路是:先用 yaml.safe_load() 解析 YAML 为 Python 原生数据(dict/list/str/None),再递归遍历,按规则生成 Element 节点。
常见注意事项:
- YAML 键名含非法 XML 字符(如空格、冒号)时,必须清洗或报错,否则
ElementTree构建失败 -
None值默认转为空标签(),若需,得显式判断并设置.text = "" - 列表项统一转为同名子元素(如
items: [a, b]→),但也可按需改为- a
- b
- 顶层必须是
dict;若 YAML 是纯列表或标量,需包裹一层根节点
import yaml import xml.etree.ElementTree as ETdef yaml_to_xml_element(data, tag_name="root"): elem = ET.Element(tag_name) if isinstance(data, dict): for key, value in data.items():
清洗 key:替换非法字符,避免冒号(除非处理命名空间)
clean_key = key.replace(":", "_").replace(" ", "_") child = yaml_to_xml_element(value, clean_key) elem.append(child) elif isinstance(data, list): for item in data: # 列表项统一用 "item" 标签,可按需改 child = yaml_to_xml_element(item, "item") elem.append(child) else: elem.text = str(data) if data is not None else "" return elem示例 YAML 字符串
yaml_str = """ config: version: "1.2" features:
- auth
- logging timeout: 30 """
data = yaml.safe_load(yaml_str) root = yaml_to_xml_element(data, "config") print(ET.tostring(root, encoding="unicode", method="xml"))
用 yq 命令行工具做简单扁平化转换
当 YAML 结构较浅、且只需快速生成可读 XML(不追求标准兼容性或命名空间),yq(v4+,基于 go-yq)配合内置 XML 输出是最轻量方案。它把 YAML 键当作标签名,值作为文本内容,数组展开为重复标签。
MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录。有需要的朋友可以下载看看
限制明显:
- 不支持自定义根节点名(默认
root) - 无法将 YAML 键映射为 XML 属性(所有数据都进
.text) - 空值转为
,不可控 - 中文或特殊字符可能被转义(取决于终端和版本)
示例命令:
$ echo 'name: Alice\nage: 30\nhobbies: [reading, coding]' | yq -o=xmlAlice 30 reading coding
别忽略命名空间、CDATA 和属性——它们不是“可选增强”
真实 XML 场景中,xmlns、xsi:type、xml:base 等属性常是协议必需项;某些字段(如 HTML 片段、JS 代码)需包裹在 中;而 id、ref 类字段本应是属性而非子元素。这些在 YAML 源中没有任何语法提示,全靠人工约定或额外元数据(如加前缀 @id 表示属性,!cdata 表示需要 CDATA 包裹)。
这意味着:如果 YAML 来自第三方或需长期维护,必须在文档或 schema 中明确定义这些映射规则,否则后续解析方无法还原原始语义。自动工具只负责“结构搬运”,语义对齐永远是人的责任。









