Search code examples
xmlloopsmuledataweavedepth

Dataweave - Loop in-depth mapping XML


I have a XML payload that contains the following example:

<Example>
    <Brand>
        <Id>987S</Id>
        <logo>circle</logo>
        <Item>
            <Name>cologne1</Name>
            <Item>
                <Name>Bosque</Name>
            </Item>
        </Item>
        <Item>
            <Name>t-Shirt</Name>
        </Item>
    </Brand>
    <Brand>
        <Id>877823C</Id>
        <logo>circle</logo>
        <Item>
            <Name>t-Shirt2</Name>
            <Item>
                <Name>t-Shirt black</Name>
                <Item>
                    <Name>t-Shirt black with logo</Name>
                </Item>
            </Item>
        </Item>
    </Brand>
</Example>

The XML is divided into:

  • Example as root node
    • Brand Objects
      • Item Objects: Those Items can also contains more Items

I get this structure randomly until 3 levels in-depth per Item.

The output expected is all Items in the same level into a parent node:

<Supermarket>
    <Item>
        <BarValue>cologne1</BarValue>
    </Item>
    <Item>
        <BarValue>Bosque</BarValue>
    </Item>
    <Item>
        <BarValue>t-Shirt</BarValue>
    </Item>
    <Item>
        <BarValue>t-Shirt2</BarValue>
    </Item>
    <Item>
        <BarValue>t-Shirt black</BarValue>
    </Item>
    <Item>
        <BarValue>t-Shirt black with logo</BarValue>
    </Item>
</Supermarket>

Is there a way to loop the XML file dynamically with Dataweave?


Solution

  • Some ways to do this:

    %dw 2.0
    output application/xml
    ---
    {
        Supermarket: {(
            payload..*Item map {
                Item: {
                    BarValue: $.Name
                }
            }
        )}
    }
    

    The descendants selector payload..Item gets all the Items in any level. Then for each Item we generate an object with {Item: {BarValue: $.Name}} and get an Array of item objects.

    The problem is that the XML model in DataWeave represents element tags and values with Objects and Strings, there is no concept of Array (which was our result of items).

    So we use the Dynamic Object feature {(expr)} where expr returns an Array of key value pairs that are expanded into key-value pairs of the object.

    Alternative:

    %dw 2.0
    output application/xml
    ---
    {
        Supermarket: {
            Item: {
                BarValue: payload..*Item.Name
            }
        }
    }
    

    This last one works because in XML when the writer tries to write an Array, it repeats the Key (Item) that contains said Array (payload..Item.Name)