
本文详解如何在 dataweave 2.0 中基于含 `gp`/`parent`/`child` 及对应 `_eye_colour`、`_name` 字段的扁平数组,动态构建嵌套的 xml 家族谱系结构,并正确处理“同名但不同属性需保留”、“同名同属性则跳过父层”等关键业务逻辑。
在 MuleSoft 集成场景中,常需将扁平化的亲属关系数据(如祖辈-父辈-子辈三元组)转换为嵌套的树形结构(如 XML 或 JSON)。本教程聚焦一个典型增强需求:不仅需按 gp → parent → child 层级分组,还需依据 复合键匹配(如 gp == parent AND gp_eye_colour == parent_eye_colour)决定是否跳过中间层级,并确保每个节点的 name 与 eye_colour 准确、无重复地提取自对应层级字段。
✅ 核心设计思路
- 层级定义显式化:使用字符串数组 ["gp", "parent", "child"] 明确层次顺序,便于扩展(如新增 grandchild);
- 层级索引驱动递归:通过 level 参数控制当前处理层级,避免硬编码嵌套逻辑;
- 复合相等判断:跳过父层的条件是 gp === parent && gp_eye_colour === parent_eye_colour,而非仅比对 ID;
- 单值安全提取:因 groupBy 结果中每个分组是数组,必须取 children[0] 获取首个元素以避免字段重复(原问题中 eye_colour 和 name 出现多次的根本原因)。
? 正确实现(DataWeave 2.0)
%dw 2.0
output application/xml
var hierarchy = ["gp", "parent", "child"]
fun getDirectGenealogies(records, level) = do {
var currentKey = hierarchy[level]
var nextLevel = level + 1
---
records groupBy $[currentKey]
mapObject ((children, code) ->
genealogy: {
code: code,
// ✅ 安全提取:取分组内首个元素,避免数组导致字段重复
eye_colour: children[0][currentKey ++ "_eye_colour"],
name: children[0][currentKey ++ "_name"],
hierarchy:
if (level == sizeOf(hierarchy) - 1) {}
else do {
// 按下一层级字段分组
var groupedByNext = children groupBy $[hierarchy[nextLevel]]
---
groupedByNext mapObject ((nextChildren, nextCode) ->
if (nextLevel == 1 && nextCode == code &&
// ? 复合判断:当处理 parent 层且 nextCode(即 parent 值)等于当前 gp 值时,
// 还需校验 eye_colour 是否一致,才跳过 parent 层,直连 child
children[0].gp == nextCode and
children[0].gp_eye_colour == nextChildren[0].parent_eye_colour)
// 跳过 parent:递归调用时 level + 2,直接进入 child 层
getDirectGenealogies(nextChildren, nextLevel + 1)
else
// 正常递进:进入 parent 或 child 层
getDirectGenealogies(nextChildren, nextLevel)
)
}
}
)
}
---
list: getDirectGenealogies(payload, 0)⚠️ 关键注意事项
-
children[0] 不可省略:groupBy 返回的是 { key: Array } 结构,直接访问 children.gp_eye_colour 会返回整个数组,导致 XML 中生成多个
标签。务必使用 children[0] 提取代表值。 - 跳过逻辑仅作用于 gp → parent 层:示例中仅在 level == 1(即当前处理 parent 层)且满足 gp == parent && gp_eye_colour == parent_eye_colour 时触发跳过。若需支持 parent → child 的类似逻辑,可扩展条件判断。
- 字段命名强约定:代码依赖 X、X_eye_colour、X_name 的命名模式(如 gp → gp_eye_colour)。实际使用前请统一源数据字段命名。
-
XML 输出限制:DataWeave 的 application/xml 不支持空标签内容(如
),若需严格匹配示例中的空 ,可改用 output text/xml 并手动拼接;但通常 语义等价且更健壮。
✅ 示例验证
输入含两条记录:
[
{ "gp": "T1", "gp_eye_colour": "blue", "gp_name": "John",
"parent": "T1", "parent_eye_colour": "black", "parent_name": "Sam",
"child": "C1", "child_eye_colour": "brown", "child_name": "C1" },
{ "gp": "T1", "gp_eye_colour": "blue", "gp_name": "John",
"parent": "T1", "parent_eye_colour": "blue", "parent_name": "Don",
"child": "C1", "child_eye_colour": "brown", "child_name": "C1" }
]输出将正确呈现:
- 第一支:T1(John, blue)→ T1(Sam, black)→ C1(C1, brown)
- 第二支:T1(John, blue)→ C1(C1, brown)【因 Don 与 John 眼色相同,跳过 parent 层】
最终 XML 层级清晰、字段唯一、逻辑可配置,满足生产级集成需求。










