1 Reply Latest reply: Jul 2, 2013 7:05 AM by vv*338251*hu RSS

    How to Avoid Nested 'for' Loops

    vv*338251*hu

      Hi,

       

      We were trying with complex transformation where it requires to have nested for loop. To explain in details the source xml is like below

       

      Input:

      <?xml version="1.0"?>
      
      <Items xmlns="http://www.example.org/Item">
      
      <Item cat="ItemBean">
      
      <UniqueId>2</UniqueId>
      
      <ParentId>1</ParentId>
      
      </Item>
      
      <Item cat="ItemBean">
      
      <UniqueId>4</UniqueId>
      
      <ParentId>1</ParentId>
      
      </Item>
      
      <Item cat="ProductBean">
      
      <UniqueId>1</UniqueId>
      
      <Name>Device1</Name>
      
      </Item>
      
      <Item cat="ProductBean">
      
      <UniqueId>3</UniqueId>
      
      <Name>Device2</Name>
      
      </Item> 
      
      </Items>
      

       

      The expected response is like in below

      <Devices xmlns="http://www.example.org/Item">
      
      <Device name="Device1">
      
      <DeviceItem>
      
      <Name>ItemBean</Name>
      
      <UniqueId>2</UniqueId>
      
      <ParentId>1</ParentId>
      
      </DeviceItem>
      
      <DeviceItem>
      
      <Name>ItemBean</Name>
      
      <UniqueId>4</UniqueId>
      
      <ParentId>1</ParentId>
      
      </DeviceItem>
      
      </Device>
      
      <Device name="Device2">
      
      </Device>
      
      </Devices>
      

       

      I was tring something like below transformation, it is working. But looks to be performance cause as i have nested for loops. How can it be imprved by not having nested loops

       

      Mapper:

      declare function xf:nextedLoop($itemPayload as element(ns0:Items)) as element(ns0:Devices) {

      <ns0:Devices>

              {

              for $productId in $itemPayload/ns0:Item[@cat='ProductBean']

              return

              <ns0:Device name="{data($productId/ns0:Name)}">

      {

      for $itemId in $itemPayload/ns0:Item[@cat='ItemBean' and ns0:ParentId = data ($productId/ns0:UniqueId)]

              return

                     <ns0:DeviceItem>

                     <ns0:Name>ItemBean</ns0:Name>

             <ns0:UniqueId>{data ($itemId/ns0:UniqueId)}</ns0:UniqueId>

             <ns0:ParentId>{data ($productId/ns0:UniqueId)}</ns0:ParentId>

               </ns0:DeviceItem>

              }

      </ns0:Device>

      }

              </ns0:Devices>

      };

       

      Here is the Schema

       

      :

      <?xml version="1.0" encoding="UTF-8"?>

      <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/Item" xmlns:tns="http://www.example.org/Item" elementFormDefault="qualified">

       

      <element name="Items" type="tns:items" />

       

      <complexType name="items">

        <sequence>

         <element name="Item" type="tns:item" maxOccurs="unbounded" />

        </sequence>

      </complexType>

       

      <complexType name="item">

        <sequence>

         <element name="UniqueId" type="string"></element>

         <element name="ParentId" type="string" minOccurs="0"></element>

         <element name="Name" type="string" minOccurs="0"></element>

        </sequence>

        <attribute name="cat" type="string"></attribute> 

      </complexType>

       

      <element name="Devices" type="tns:devices" />

       

      <complexType name="devices">

        <sequence>

         <element name="Device" type="tns:device" maxOccurs="unbounded" />

        </sequence>

      </complexType>

       

      <complexType name="device">

        <sequence>

         <element name="DeviceItem" type="tns:deviceItem" maxOccurs="unbounded"></element>  

        </sequence>

        <attribute name="name" type="string"></attribute> 

      </complexType>

       

      <complexType name="deviceItem">

        <sequence>

         <element name="Name" type="string"></element>  

         <element name="UniqueId" type="string"></element>

         <element name="ParentId" type="string"></element>

        </sequence>   

      </complexType>

      </schema>

       

      Thanks

      Venkata Madhu

        • 1. Re: How to Avoid Nested 'for' Loops
          vv*338251*hu

          Hi All,

           

          I was tring using every function, but not able to get the expected results. Any idea?

           

           

          declare function xf:SomeOmniXQ($itemPayload as element(ns0:Items))

              as element(ns0:Devices) {

                  <ns0:Devices>

                  {

                   for $productBean in $itemPayload/ns0:Item[@cat='ProductBean']

                   return

                    <ns0:Device name="{data($productBean/ns0:Name)}">         

                     return

                     {                      

                      if (every $itemBean in $itemPayload/ns0:Item[@cat='ItemBean'] satisfies  $itemBean/ns0:ParentId/text() = $productBean/ns0:UniqueId/text()) then

                     

                       <ns0:Device>

                        <ns0:Name>ItemBean</ns0:Name>

                  <ns0:UniqueId> $itemBean/ns0:UniqueId/text() </ns0:UniqueId>

                  <ns0:ParentId> $productBean/ns0:UniqueId/text() </ns0:ParentId>

                       </ns0:Device>           

                      else ()

                  }         

                    </ns0:Device>       

                  }

                  </ns0:Devices>

          };

           

          Thanks

          Venkata Madhu