2

I have json array of objects as below retrieved from database

[
    { "Projectid":"A1234","ProjectLvl":1,"desc":"A1234-desc"},
    { "Projectid":"A1234.1","ProjectLvl":2,"desc":"A1234.1-desc"},
    { "Projectid":"A1234.1.1","ProjectLvl":3,"desc":"A1234.1.1-desc"},
    { "Projectid":"A1234.1.1.1","ProjectLvl":4,"desc":"A1234.1.1.1-desc"},
    { "Projectid":"A1234.2","ProjectLvl":2,"desc":"A1234.2-desc"}, 
    { "Projectid":"A1234.2.1","ProjectLvl":3,"desc":"A1234.2.1-desc"}
]

I have to create following xml. Can you help with dataweave function to use within mule transform component.

<projects>
    <project level="1">
        <desc>A1234-desc</desc>
        <project level="2">
            <desc>A1234.1-desc</desc>
            <project level="3">
                <desc>A1234.1.1-desc</desc>
                <project level="4">
                    <desc>A1234.1.1.1-desc</desc>
                </project>
            </project>
        </project>
        <project level="2">
            <desc>A1234.2-desc
            </desc>
            <project level="3">
                <desc>A1234.2.1-desc
                </desc>
            </project>
        </project>
    </project>
</projects> 
machaval
  • 4,969
  • 14
  • 20
ciba
  • 21
  • 2

2 Answers2

6

Hi nice problem My solution tries to update the nodes with the path from the ids using a reduce and a recursive update on the tree

%dw 2.0
output application/xml

fun updateTree(tree, path: Array<Number>, treeNode: {}) = do {
    if(sizeOf(path) == 1)
        tree ++ treeNode
    else    
        tree mapObject ((value, key, index) -> 
            if(index + 1 == path[0] and key ~= "project")
                {
                    (key): updateTree(value, path[1 to -1], treeNode)
                }
            else
            {
                (key):value
            }
        )        
}
---
projects: {
    (
        payload reduce ((project, accumulator = {}) -> do {
            var path = project.Projectid[sizeOf("A1234") to -1] default "" splitBy  "." filter !isEmpty($) map $ as Number
            ---
                updateTree(accumulator,path,{
                    project @(level: project.ProjectLvl): {
                        desc: project.desc    
                    }
                })
            }
        )
    )
}
machaval
  • 4,969
  • 14
  • 20
  • This would give a tree that is nested two levels deep.. Tweak it to `project.Projectid[sizeOf("A123") to 1]` maybe ? – Salim Khan Aug 21 '20 at 09:30
  • Hi machaval. Thank you for providing a solution. when i tried. i am not getting the level 1 and level 4 xml. can you please see what could be wrong. Thanks – ciba Aug 21 '20 at 15:22
  • try update the path variable to this: `var path = [1] ++ (project.Projectid[sizeOf("A1234") to -1] default "" splitBy "." filter !isEmpty($) map ($ as Number + 1))` – short stack stevens Aug 21 '20 at 18:48
0

Try with the path var being

project.Projectid[sizeOf("A123") to 1] default "" splitBy  "." filter !isEmpty($) map $ as Number
Salim Khan
  • 4,233
  • 11
  • 15
  • Hi Salim, That does not give the structure i am need of. It gives. A1234-desc A1234.1-desc A1234.1.1-desc A1234.1.1.1-desc A1234.2-desc A1234.2.1-desc – ciba Aug 21 '20 at 16:50