XML 转 YAML 实战:标签变键、嵌套变缩进,把老配置迁到现代格式
讲清 XML 转 YAML 的规则:标签如何变成键、嵌套层级如何变成缩进、属性怎么处理,以及为什么老配置迁到 YAML 后更好读好改,附一段真实输入输出例子。
XML 转 YAML 实战:标签变键、嵌套变缩进,把老配置迁到现代格式
我去年接手过一个十年前写的 Java 服务,配置全堆在一个一千多行的 app.config XML 里。新平台要 YAML,我盯着满屏尖括号手抄了半小时,缩进还敲错过两次。后来想明白,这种机械活根本不该靠人。XML 到 YAML 的映射有固定规则,搞清楚规则,再用 XML 转 YAML 转换器 跑一遍,几百行十秒搞定。这篇就把规则讲透。
标签怎么变成键,嵌套怎么变成缩进
核心只有一句话:每个 XML 元素名变成一个 YAML 键,父子嵌套关系变成缩进层级。
XML 用一对尖括号包住子节点,YAML 不用括号,改用每层多缩进两个空格来表达从属。一个 <book> 里包着 <title>,在 YAML 里就是 book 这个键下面缩进出一个 title。层级深一层,缩进多一级,读起来像目录树,而不是一堆需要数括号配对的标记。
属性这块要单独说。XML 的属性挂在标签上,YAML 没有属性这个概念,所以工具给属性键加一个前缀,默认是 @,这样它永远不会和子元素名撞车。<book id="b1"> 里的 id 会变成 "@id": b1。因为 @ 是 YAML 的保留指示符,开头不能裸用,所以这个键会被加上引号。如果你下游的解析器认 $ 那套约定,在选项里把前缀换掉即可。
重复标签变列表,混合文本也保留
还有两条规则容易踩坑。
第一,同名的兄弟元素会收成一个 YAML 序列。三个并排的 <item> 会变成一个列表。但只出现一次的元素保持单个值,不会变成只有一项的列表,这样输出更像手写的 YAML。代价是:如果你下游代码总把某个键当数组,而源 XML 恰好只有一个该元素,YAML 里就是个标量。测试时记得至少喂两条。
第二,一个元素既有文本又有子元素时,散落的文本不会被丢掉,而是落到一个文本键下,默认叫 #text。不在乎那段零散文本的话,把混合文本保留关掉就行。
一段真实输入输出
口说无凭,直接看一段。输入这样一份 XML:
<servers>
<server host="10.0.0.1" port="8080">
<name>web-1</name>
</server>
<server host="10.0.0.2" port="8080">
<name>web-2</name>
</server>
</servers>
转出来的 YAML 是这样:
servers:
server:
- "@host": 10.0.0.1
"@port": "8080"
name: web-1
- "@host": 10.0.0.2
"@port": "8080"
name: web-2
注意三个细节:两个同名的 server 收成了列表,host 和 port 属性带上了 @ 前缀并加了引号,8080 这种看着像数字的值被加引号保住了字符串身份。这种自动加引号很关键,像 007、yes 这类值如果裸着写进 YAML,会被悄悄解析成数字 7 或布尔值,工具帮你按住了。
为什么值得迁:YAML 更好读、更好改
迁过一次你就不想回去了。XML 的信息密度被尖括号和闭合标签稀释,一个三层嵌套的结构,光闭合标签就占掉视线一半。YAML 用缩进表达层级,同样的结构竖着一眼扫到底。
改配置时差别更明显。在 git 里 diff 一份 YAML,改一行就只标一行;XML 改一个值经常牵动配对的闭合标签,diff 看着乱。而且 Helm values、Kubernetes 清单、Ansible 变量块、GitHub Actions 工作流这些现代工具链原生就吃 YAML,转过去等于直接对接生态,不用再写一层适配。
老配置迁移的正确姿势
迁移别指望逐字节还原。一旦重新组织过,YAML 就分不清属性和单个子元素的区别,注释也不会带过来。如果你确实需要可逆的往返,把 XML 先转成 JSON 留作源头更稳,可以用 XML 转 JSON 那条路。
实际操作我的流程是:先粘 XML 跑出 YAML 拿到正确的嵌套骨架,再手动整理键名和分组,最后跑一遍校验确认格式合法。整理阶段如果想顺手把缩进和键序统一,可以用 YAML 格式化 过一道。几百行配置,真正费脑的是业务语义梳理,机械的标签到缩进转换交给工具就好,省下的时间和敲错缩进的风险都是实打实的。
Made by Toolora · Updated 2026-06-13