Search code examples
xmlmappingmuledatamapperdataweave

Is it possible to generate multiple XML from a complex input xml based on line items using Dataweave or Damapper in mule?


I was trying to create multiple flat XML based on line items from the input XML. Is this possible is just using Dataweave or Datamapper in mule?

Thanks

Please see example above

<?xml version="1.0" encoding="utf-8"?>
<XmlInterchange>
     <InterchangeInfo>
       <Payload>
         <WhsDockets>
            <WhsDocket>
               <Identifier>1</Identifier>
                <DocketDetail>
                </DocketDetail>
                 <DocketLines>
                   <Product>7CAGL3G00</Product>
                   <Description>AGL_7C_0</Description>
                   <QuantityFromClientOrder>7.00</QuantityFromClientOrder>
                   <QuantityActuallyOrdered>7.00</QuantityActuallyOrdered>
                   <ProductUQ>SKD</ProductUQ>
                    <Confirmation>
                         <Lines>
                              <Line>
                               <PartAttribute1>4440_100</PartAttribute1>
                               <PartAttribute2>96489</PartAttribute2>
                               <PartAttribute3>700029611    -   700029710  #4</PartAttribute3>
                               <Quantity>100.000</Quantity>
                               <QuantityUQ>UNT</QuantityUQ>
                               </Line>
                               <Line>
                               <PartAttribute1>4440_100</PartAttribute1>
                               <PartAttribute2>96489</PartAttribute2>
                               <PartAttribute3>700029511    -   700029610 #3</PartAttribute3>
                               <Quantity>100.000</Quantity>
                               <QuantityUQ>UNT</QuantityUQ>
                               </Line>
                         </Lines>   
                    </Confirmation>
                  </DocketLines>
            <WhsDocket>
          <WhsDockets>
       <Payload>
     </InterchangeInfo>
</XmlInterchange>

target

<?xml version="1.0"?><p1:StockMovementDataRequest xmlns:p1="urn:ams.com.au:test:3pl:am:SAP_AM_I_005:StockMovement" xmlns:a="http://www.test.com.au/EnterpriseService/">
<Header>
    <From>warehouse</From>
    <To>client</To>
    <DateTimeStamp>2016-04-13T11:55:30.263+10:00</DateTimeStamp>
</Header>
<StockMovementData>
    <Serialised_Material>YES</Serialised_Material>
    <From_Location>warehouse</From_Location>
    <To_Location>client</To_Location>
    <Material>7CAGL3G00</Material>
    <Serial>700029611   -   700029710 #4</>
    <Quantity>7.00</Quantity>
</StockMovementData>
 <StockMovementData>
    <Serialised_Material>YES</Serialised_Material>
    <From_Location>warehouse</From_Location>
    <To_Location>client</To_Location>
    <Material>7CAGL3G00</Material>
    <Serial>700029511   -   700029610 #3</>
    <Quantity>7.00</Quantity>
</StockMovementData>

or create multiple XML with the line items


Solution

  • Single DataWeave transformation can only output one xml file, keep in mind XML can have ONLY ONE ROOT element. DataWeave will also throw error if your transformation is resulting in multiple root elements. So you cannot generate single xml in the format you mentioned in your question. However if you can wrap all that output elements into some root element then you can create that output.

    Adding updates to show, how to iterate and generate elements -

    We would need to take help of global functions to create a dynamic array of length equal to the quantity ordered -

    Add below global function in your mule xml -

    <configuration doc:name="Configuration">
         <expression-language>
             <global-functions>
    
                def getArrayOfLength(value){
                    int i = 0;
                    int[] arrRet = [];
                    while(i &lt; value){
                        arrRet.add(i);
                        i++;
                    }
                    return arrRet;
                }   
    
             </global-functions>
         </expression-language>
     </configuration>
    

    Then we will use this function our dataweave, I am going to use a simple input xml as below and will output name element number of times in -

    <?xml version='1.0' encoding='UTF-8'?>
    <root>
        <name>Manik</name>
        <times>7</times>
    </root>
    

    Then here is the dataweave code -

    %dw 1.0
    %output application/xml
    ---
    {
      root: {
            (getArrayOfLength(payload.root.times) map ((key,index) -> name: payload.root.name))
        }
    }
    

    So what we do is, call our global function by passing in times value eg. 7. This global function will return an array list of number starting from 0 to value-1. Then we use map to loop over this array but we don't have use anything from this array, Instead we can just use our original payload to create the mapping that would be repeated N times in output.

    Here is the output -

    <?xml version='1.0' encoding='windows-1252'?>
    <root>
      <name>Manik</name>
      <name>Manik</name>
      <name>Manik</name>
      <name>Manik</name>
      <name>Manik</name>
      <name>Manik</name>
      <name>Manik</name>
    </root>
    

    Hope this gives you an idea of how to do it and helps you to extend it for your use case.