如何编写yq递归表达式强制XML转JSON时统一节点为数组?
问题分析与解决方案
原递归表达式的问题
你使用的(... | select(key == "member")) |= [] + .存在两个核心问题:
- 递归运算符误用:
...是递归下降到所有叶子节点(比如one、two这类字符串值),而叶子节点没有key属性,导致select(key == "member")无法正确匹配到member键对应的节点,进而让yq处理逻辑混乱,输出异常格式。 - 处理逻辑不严谨:即使匹配到目标节点,
[] + .仅能实现单个值转数组,但没有考虑节点本身已是数组的场景(虽然当前案例中可以运行,但扩展性差)。
正确的递归表达式
使用..(遍历所有层级的节点,包括映射节点)选中所有键为member的节点,再通过类型判断统一转为数组:
yq --input-format xml '(.. | select(key == "member")) |= if type == "array" then . else [.] end' data.xml
执行效果
针对你的data.xml,执行后输出:
root: heading: - member: - one - member: - two - three
适配任意层级的原理
..会递归遍历XML转YAML后的所有节点,无论层级深浅,只要键名为member就会被选中;- 条件判断
if type == "array" then . else [.] end确保:- 原本就是数组的
member保持结构不变; - 单个值的
member被包裹为数组,实现全层级格式统一。
- 原本就是数组的
额外优化:批量处理多节点
如果需要同时处理多个类似节点(比如member、item),可修改选择器:
yq --input-format xml '(.. | select(key == "member" or key == "item")) |= if type == "array" then . else [.] end' data.xml
内容的提问来源于stack exchange,提问作者Kim T
相关产品推荐
相关产品推荐

