【问题标题】:Dataweave 2.0 - XML to JSON Array: grouping by id across different XML structuresDataweave 2.0 - XML 到 JSON 数组:在不同 XML 结构中按 id 分组
【发布时间】:2021-02-12 18:36:06
【问题描述】:

我正在尝试从数据结构 A 实现类似数据结构 B 的东西。

不确定如何遍历 XML 结构,然后按 对结果进行分组,并提取根元素,即 作为“类型”和“消息”。

任何帮助/建议将不胜感激。

注意:预期为空元素,即

谢谢

结构 A:

<root>
   <TYPE_A>
      <row id="0">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>123</ORDER_NUMBER>
      </row>
   </TYPE_A>
   <TYPE_B/>
   <TYPE_C>
      <row id="0">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>123</ORDER_NUMBER>
      </row>
      <row id="1">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>789</ORDER_NUMBER>
      </row>
      <row id="2">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>555</ORDER_NUMBER>
      </row>
   </TYPE_C>
   <TYPE_D>
      <row id="0">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>555</ORDER_NUMBER>
      </row>
      <row id="1">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>123</ORDER_NUMBER>
      </row>
      <row id="2">
         <MESSAGE>Unique Message</MESSAGE>
         <ORDER_NUMBER>789</ORDER_NUMBER>
      </row>
   </TYPE_D>
</root>

结构 B:

[  
  {
    "orderNumber": "123",
    "type": "A",
    "message": "Unique Message"
  },
  {
    "orderNumber": "123",
    "type": "C",
    "message": "Unique Message"
  },
  {
    "orderNumber": "789",
    "type": "C",
    "message": "Unique Message"
  },
  {
    "orderNumber": "555",
    "type": "C",
    "message": "Unique Message"
  },
  {
    "orderNumber": "555",
    "type": "D",
    "message": "Unique Message"
  },
  {
    "orderNumber": "123",
    "type": "D",
    "message": "Unique Message"
  },
  {
    "orderNumber": "789",
    "type": "D",
    "message": "Unique Message"
  }
]

【问题讨论】:

  • 如果您正确缩进您的示例数据,这将需要很长时间。此外,您的输出样本数据似乎不完整。我在输入中看到三个TYPE_Cs 和三个TYPE_Ds,但在相应的输出中只有两个和一个。请修正您的样本数据,以便消除猜测的元素;)。
  • 我很抱歉,当我问最初的问题时,我有点匆忙。我更新了,谢谢!
  • 如果您的问题得到解答,请接受答案。

标签: json xml transformation dataweave mulesoft


【解决方案1】:

这是一个动态解决方案。首先过滤掉空对象(在这种情况下为TYPE_B),获取根对象的键并通过它们进行映射。对于每种类型,在rootData 中获取valuesOf 对应的对象,这将返回这些对象的数组。最后映射该集合并执行您的转换。

%dw 2.0
output application/json
var rootData = payload.root filterObject not isEmpty($)
---
keysOf(rootData) flatMap ((messageType, index) -> 
    valuesOf(rootData[messageType]) map ((order) -> 
        {
            orderNumber: order."ORDER_NUMBER",
            "type": upper(messageType[-1]),
            message: order."MESSAGE"
        }
    )      
)

【讨论】:

    【解决方案2】:

    这是另一个“动态”解决方案,选择性能最好的一个并使用它:

    %dw 2.0
    output application/json
    var xml = '<root>
        <TYPE_A>
          <row id="0">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>123</ORDER_NUMBER>
          </row>
        </TYPE_A>
        <EMPTY_TYPE_B/>
        <TYPE_C>
          <row id="0">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>123</ORDER_NUMBER>
          </row>
          <row id="1">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>789</ORDER_NUMBER>
          </row>
          <row id="2">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>555</ORDER_NUMBER>
          </row>
        </TYPE_C>
        <TYPE_D>
          <row id="0">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>555</ORDER_NUMBER>
          </row>
          <row id="1">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>123</ORDER_NUMBER>
          </row>
          <row id="2">
            <MESSAGE>Unique Message</MESSAGE>
            <ORDER_NUMBER>789</ORDER_NUMBER>
          </row>
        </TYPE_D>
    </root>'
    
    var data = read(xml,"application/xml")
    ---
    orders: data.root filterObject (not isEmpty($)) 
    mapObject do {
        var tp = ($$ as String splitBy "_")[-1]
        var rs = $.*row
        ---
        (tp): rs map (r) -> {
            orderNumber: r.ORDER_NUMBER,
            "type": tp,
            message: r.MESSAGE
        }
    }
    pluck $
    reduce (e,acc=[]) -> acc ++ e
    

    【讨论】:

    • 你有反对动态这个词的东西吗?大声笑
    • 大声笑不,我会使用灵活的,但自从我看到您的回复后,我选择保持一致;)
    【解决方案3】:

    此解决方案适用于您,但前提是您了解所有类型

    %dw 2.0
    output application/json
    ---
    
    orders: (if (payload.root.TYPE_A != null) 
        (payload.root.*TYPE_A map (object, index) -> {
        orderNumber: object.row.ORDER_NUMBER,
        "type": "A",
        message: object.row.MESSAGE
    }) else ([])) ++
    (if (payload.root.TYPE_B != null) 
        (payload.root.*TYPE_B map (objectB, indexB) -> {
        orderNumber: objectB.row.ORDER_NUMBER,
        "type": "B",
        message: objectB.row.MESSAGE
    }
    ) else ([])) ++
    (if (payload.root.TYPE_C != null) 
        (payload.root.*TYPE_C map (objectC, indexC) -> {
        orderNumber: objectC.row.ORDER_NUMBER,
        "type": "C",
        message: objectC.row.MESSAGE
    }
    ) else ([]))
    

    【讨论】:

    • 非常感谢,这很有道理。为了获得每个 TYPE 元素的每个子元素,我似乎必须做一个非常小的修改,见下文: if (payload.root.TYPE_C != null) (payload.root.TYPE_C.*row map (objectC, index) -> { orderNumber: objectC.ORDER_NUMBER, "type": "C", message: objectC.MESSAGE }) else ([])
    • 您至少可以创建一个函数来执行此操作,并将您正在寻找的 TYPE_# 传递给该函数,而不是为每个订单重复它。这是非常多余的
    【解决方案4】:

    这是另一个动态解决方案

    %dw 2.0
    output application/json skipNullOn="everywhere"
    
    fun mapRows(key, rows) =
        rows map
            {
                "type": key[-1],
                "orderNumber":$.ORDER_NUMBER,
                "message": $.MESSAGE
            }
    
    ---
    
    flatten(payload.root pluck mapRows($$, $.*row))
    

    【讨论】:

      猜你喜欢
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-12
      相关资源
      最近更新 更多