You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将带@属性与__text的JSON转回XML并恢复属性?(数组问题)

问题:将通过writeAttributes=true转换的JSON转回XML并恢复所有属性

背景:XML转JSON的过程

使用DataWeave的writeAttributes=true属性可将XML转换为保留属性的JSON,规则为:用@key表示XML属性,__text表示元素的文本值。具体示例如下:

原始XML

<family surname="Simpsons">
  <father age="42">Homer</father>
  <mother age="41">Marge</mother>
  <children>
    <child age="9">Bart</child>
    <child age="8">Lisa</child>
    <child age="1">Maggie</child>
  </children>
</family>

转换用DataWeave代码

%dw 2.0
output application/json 
   writeAttributes=true, 
   duplicateKeyAsArray=true
---
payload

转换后的JSON

{
  "family": {
    "@surname": "Simpsons",
    "father": {
      "@age": "42",
      "__text": "Homer"
    },
    "mother": {
      "@age": "41",
      "__text": "Marge"
    },
    "children": {
      "child": [
        {
          "@age": "9",
          "__text": "Bart"
        },
        {
          "@age": "8",
          "__text": "Lisa"
        },
        {
          "@age": "1",
          "__text": "Maggie"
        }
      ]
    }
  }
}

反向转换遇到的问题

将上述JSON转回XML时,尝试使用以下DataWeave代码,发现数组中的<child>元素的age属性未能恢复:

尝试的DataWeave代码

%dw 2.0
output application/xml
fun getAttributes(x) =
   x match {
      case is Object -> x filterObject ($$ as String startsWith "@") 
         mapObject ((value, key, index) -> (key[1 to -1] ): value)
      else -> $
   }
fun convertToAttributes(x) =
   x match  {
      case is Object -> x filterObject !($$ as String startsWith "@")
         mapObject ($$) @((getAttributes($))): convertToAttributes($)
      case is Array -> x map convertToAttributes($)
      else -> $
   }
---
convertToAttributes(payload)

转换后的XML(属性缺失)

<?xml version='1.0' encoding='UTF-8'?>
<family surname="Simpsons">
  <father age="42">Homer</father>
  <mother age="41">Marge</mother>
  <children>
    <child>Bart</child>
    <child>Lisa</child>
    <child>Maggie</child>
  </children>
</family>

正确的解决方案

原代码问题在于处理数组元素时,未正确提取每个数组元素对象中的属性。修正后的代码需确保数组中的每个对象都能正确解析属性:

修正后的DataWeave代码

%dw 2.0
output application/xml
fun extractAttributes(obj) =
    obj filterObject ((value, key) -> (key as String startsWith "@"))
        mapObject ((value, key) -> (key[1 to -1]): value)

fun convertNode(node) =
    node match {
        case is Object -> 
            // 分离属性、文本值和子节点
            nonAttrNodes = node filterObject ((value, key) -> !(key as String startsWith "@") and key != "__text")
            textValue = node."__text" default null
            attributes = extractAttributes(node)
            // 处理非属性节点
            nonAttrNodes mapObject ((value, key) -> 
                (key) @(attributes): convertNode(value)
            ) 
            // 无节点但有文本值时,直接返回文本
            ++ (if (isEmpty(nonAttrNodes) and textValue != null) textValue else {})
        case is Array -> node map convertNode($)
        else -> node
    }
---
convertNode(payload)

转换后的正确XML

<?xml version='1.0' encoding='UTF-8'?>
<family surname="Simpsons">
  <father age="42">Homer</father>
  <mother age="41">Marge</mother>
  <children>
    <child age="9">Bart</child>
    <child age="8">Lisa</child>
    <child age="1">Maggie</child>
  </children>
</family>

代码说明

  • extractAttributes函数:从对象中提取以@开头的属性,去掉前缀后转为XML属性格式。
  • convertNode函数:递归处理每个节点:
    • 处理对象时,分离属性、文本值与子节点,将属性附加到对应XML元素上;
    • 处理数组时,遍历每个元素并递归解析,确保数组元素的属性被正确识别;
    • 处理__text值,当元素无任何子节点时,直接将其作为元素文本。

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:52:12