Search code examples
xmlmuleanypoint-studiodataweave

Split XML based on a child and iterate over a dynamic tag


in my Mule flow i will be invoking a stored procedure which is going to out me XML response something like this

<RESULT xmlns="some_stored_proc:Response">
   <ROOT_TAG>
      <RESULTSET_1>
         <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>1</hasError>
        </ROW>
        <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>1</hasError>
        </ROW>
    </RESULTSET_1>
<RESULTSET_2>
         <ROW>
            <A>0.3</A>
            <B>0.2</B>
            <C>1.1</C>
            <hasError>0</hasError>
        </ROW>
        <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>0</hasError>
        </ROW>
    </RESULTSET_2>  
<RESULTSET_3>
         <ROW>
            <A>1.1</A>
            <B>2.4</B>
            <C>1.8</C>
            <hasError>0</hasError>
        </ROW>
        <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>0</hasError>
        </ROW>
    </RESULTSET_3>  
</ROOT_TAG> 
</RESULT>   

now in my dataweave what i want to do is go through this XML and any which has set to 1 bring them under a root tag called ISSUES

<ISSUES>
     <ROW>
        <A>0.1</A>
        <B>0.4</B>
        <C>1.0</C>
        <hasError>1</hasError>
    </ROW>
    <ROW>
        <A>0.1</A>
        <B>0.4</B>
        <C>1.0</C>
        <hasError>1</hasError>
    </ROW>
</ISSUES>

and the rest of the ROW's goes under DOCUMENT like this

    <DOCUMENT>
         <ROW>
            <A>0.3</A>
            <B>0.2</B>
            <C>1.1</C>
            <hasError>0</hasError>
        </ROW>
        <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>0</hasError>
        </ROW>
         <ROW>
            <A>1.1</A>
            <B>2.4</B>
            <C>1.8</C>
            <hasError>0</hasError>
        </ROW>
        <ROW>
            <A>0.1</A>
            <B>0.4</B>
            <C>1.0</C>
            <hasError>0</hasError>
        </ROW>
    </DOCUMENT> 

i keep hitting one exception or the other.

NOTE: There can be any number of <RESULTSET_n> tags based on the input size and a group size which goes as an input to the database stored proc. So this tag is going to be kind of dynamic.


Solution

  • So basically what I did is use the groupBy function to split your document into valid and invalids the I transform each part into the expected data structure

    %dw 2.0
    output application/xml
    import * from dw::core::Objects
    ---
    { 
        RESULT: {( 
    payload.RESULT.ROOT_TAG 
        groupBy ((value, key) -> (key as String match /RESULTSET_([0-9]+)/)[1] == "1")
        pluck ((value, key, index) -> 
            key as String match {
                case "true" -> 
                    { ISSUES: {(valueSet(value))}}
                case "false" -> 
                    { DOCUMENT: {(valueSet(value))}}
            }
        )
    
        )}
    }