X

The Integration blog covers the latest in product updates, best practices, customer stories, and more.

Data Stitch: Append and Assign for repeating elements

Jorge Herreria
Software Developer 5.

Summary

Data Stitch has ASSIGN, APPEND and REMOVE operations. Some use-cases are easy to grasp; some others require a little thinking... On this blog I‘ll explain behaviors I deem they are not straightforward to derive the outcome for using Data Stitch in a OIC Orchestration:

  • Assigning into unbounded elements (aka - Repeating Elements)
  • Appending instances into an unbounded element and how to complete the data.

I assume you are familiar with XPath Expressions and XSD Schemas, because there is a lot a lingo in this post. I'll try to explain them, but I might miss some

You will not see many screen shots. My goal is to give you the concepts so you become a good data ...“tailor?” ... data Stitcher.

Expect some twisted humor here and there; more often that none.

I love this quote:  Perfection is boring; therefor laugh of your mistakes.

Syntax

For Data Stitch Sentences

(TO XPath expression).OPERATION(FROM XPath expression)

Example:

($v1/ns0:customer/ns0:name).ASSIGN(“Jorge Herreria”)

On explanations you will see step/step/step/… in location paths. I’m going to omit the namespace prefixes, and just put the local-name on each step; looking to make it easy to read… However on actual XPathExpressions you’ll see prefixes.

Prerequisites

Enable following features:

  • oic.ics.console.integration.stitch-action
  • oic.ics.console.integration.complex-variables

To enable feature flags – Refer to Blog Enabling Feature Flags in Oracle Integration

The minimum Oracle Integration version required for the feature is 200113.1400.33493

Use-case 1: Populating more than one instance on an unbounded simple element with attributes.

Oh oh, did I lose you already? If you have understood the use case from its name then I did a good job naming it and you can jump into the Explanation section otherwise keep reading… you are going to kill me!

Explanation

Here’s the schema code snipped. The name element is a simple element with an attribute named lang. The name element is unbounded. Unbounded means it can hold many instances.

<xsd:element name="item" maxOccurs="unbounded" minOccurs="0">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="name" maxOccurs="unbounded" minOccurs="0">
                                <xsd:complexType>
                                    <xsd:simpleContent>
                                        <xsd:extension base="xsd:string">
                                            <xsd:attribute name="lang" type="xsd:string"/>
                                        </xsd:extension>
                                    </xsd:simpleContent>
                                </xsd:complexType>
                            </xsd:element>
                            <xsd:element name="quantity" minOccurs="0">
                                <xsd:complexType>
                                    <xsd:simpleContent>
                                        <xsd:extension base="xsd:float">
                                            <xsd:attribute name="uom" type="xsd:string"/>
                                        </xsd:extension>
                                    </xsd:simpleContent>
                                </xsd:complexType>
                            </xsd:element>
                            <xsd:element name="prices" maxOccurs="1" minOccurs="0" type="PriceType" nillable="true"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>

 

Setup / initial state

Here’s the Schema – almost all of it.

ScreenShot of the Schema Image
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.jorge.herreria.net/cart"
            targetNamespace="http://www.jorge.herreria.net/cart" elementFormDefault="qualified"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="cart">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element ref="customer" maxOccurs="1"/>
                <xsd:element name="addresses" minOccurs="0" maxOccurs="unbounded" type="AddressType"/>
                <xsd:element name="item" maxOccurs="unbounded" minOccurs="0">
                    <xsd:complexType>
                        <xsd:sequence>
                            <xsd:element name="name" maxOccurs="unbounded" minOccurs="0">
                                <xsd:complexType>
                                    <xsd:simpleContent>
                                        <xsd:extension base="xsd:string">
                                            <xsd:attribute name="lang" type="xsd:string"/>
                                        </xsd:extension>
                                    </xsd:simpleContent>
                                </xsd:complexType>
                            </xsd:element>
                            <xsd:element name="quantity" minOccurs="0">
                                <xsd:complexType>
                                    <xsd:simpleContent>
                                        <xsd:extension base="xsd:float">
                                            <xsd:attribute name="uom" type="xsd:string"/>
                                        </xsd:extension>
                                    </xsd:simpleContent>
                                </xsd:complexType>
                            </xsd:element>
                            <xsd:element name="prices" maxOccurs="1" minOccurs="0" type="PriceType"
                                         nillable="true"/>
                        </xsd:sequence>
                    </xsd:complexType>
                </xsd:element>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>
</xsd:schema>

 

 

 

The following global variable has been defined:

  1. vFreeCartItem global variable has been defined based on cart/item element. See Use Global Variables and Data Stitch post for defining global variables.
  2. vFreeCarItem has not data.

Desired Outcome

Populate the $vFreeCartItem/item  with 2 name instances, one in en-us and another in sp-mex. Here’s what should look like:

$vFreeCartItem:

<item xmlns="http://www.jorge.herreria.net/cart">   
    <name lang="en-us">bluetooth keyboard</name>   
    <name lang="sp-mex">teclado bluetooth</name>
</item>

 

Solution

The following stitches will do the job:

  1. ($vFreeCartItem/ns0:item/ns0:name) .APPEND(“bluetooth keyboard”)
  2. ($vFreeCartItem/ns0:item/ns0:name[1]/@lang) .ASSIGN(“en-us”)
  3. ($vFreeCartItem/ns0:item/ns0:name) .APPEND(“teclado bluetooth”)
  4. ($vFreeCartItem/ns0:item/ns0:name[2]/@lang) .ASSIGN(“sp-mex”)

Solution Explanation

Stitch #1 -($vFreeCartItem/ns0:item/ns0:name) .ASSIGN(“bluetooth keyboard”) - will create:

<item xmlns="http://www.jorge.herreria.net/cart">   
    <name>bluetooth keyboard</name>   
</item>

You might ask - Can I use ASSIGN instead of APPEND for Stitch #1?

I’ll respond– Yest with a but! ASSIGN will produce the same output, because the $vFreeCartItem/ns0:item/ns0:name is empty; further down I explain the ASSIGN behavior when the target is not empty.

 

Stitch #2 - ($vFreeCartItem/ns0:item/ns0:name[1]/@lang) .ASSIGN(“en-us”) - will produce:

<item xmlns="http://www.jorge.herreria.net/cart">   
    <name lang="en-us">bluetooth keyboard</name>   
</item>

You might ask – Why [1] predicate? Shouldn’t it be [0]? - I will lift my left eyebrow and say -  Aha, caught you red-handed! You forgot the detail from XML/XPath Expressions is [1] based. – Do not worry, I can’t lift a single eyebrow at the time.

You might ask - Why this time ASSIGN was used and not APPEND?

Me - Because the ns0:name[1] instance already exist. Doing APPEND will add a new instance and then assign "en-us" to that new one.

 

Stitch #3 - ($vFreeCartItem/ns0:item/ns0:name) .APPEND(“teclado bluetooth”)

- will produce:

<item xmlns="http://www.jorge.herreria.net/cart">   
    <name lang="en-us">bluetooth keyboard</name>   
    <name>teclado bluetooth</name>
</item>

 

Stitch 4 will finish the job. ($vFreeCartItem/ns0:item/ns0:name[2]/@lang) .ASSIGN(“sp-mex”) produces:

<item xmlns="http://www.jorge.herreria.net/cart">   
    <name lang="en-us">bluetooth keyboard</name>   
    <name lang="sp-mex">teclado bluetooth</name>
</item>

Bonus

You might say - Hold your horses Jorge! Why make it simple if we can make it complicated? – squinting your eyes you continue  – What happens if I guff it and do the following in Stich 4?

($vFreeCartItem/ns0:item/ns0:name[4]/@lang) .ASSIGN(“sp-mex”)

I will smile knowing that you are now getting it – It will produce the following :

<item xmlns=”http://www.jorge.herreria.net/cart”>
    <name lang="en-us">bluetooth keyboard</name>
    <name></name>
    <name></name>
    <name lang="sp-mex">teclado bluetooth</name>
</item>

Me - This one is a brain chewing gum.... The reasons are irrelevant, knowing what the xpath engine will do is the goal.

 

Use-case 2:  Assign into populated unbounded element

This use case is to respond the question: What happens if an ASSIGN is made into an unbounded element?

There are two sub-use-cases: With or Without indicating which instance of the unbounded element.

Use-case 2 Sub 1:  Assign into populated unbounded element without indicating which instance

Initial State

$vFreeCartItem has

 

<item xmlns="http://www.jorge.herreria.net/cart">
    <name lang="en-us">bluetooth keyboard</name>
    <name lang="sp-mex">teclado bluetooth</name>   
    <quantity uom="ea">1.0</quantity>
</item>

Stitch:

($vFreeCartItem/ns0:item/ns0:name) .ASSIGN(“magic path”)

Output:

$vFreeCartItem gets changed to:

<item xmlns="http://www.jorge.herreria.net/cart">
     <name>magic path</name>
     <quantity uom="ea">1.0</quantity>
</item>

Explanation: No needed… ok ,ok, ok! ASSIGN is a full replacement of the element in the TO xpath expression.  In above example, only name instances are affected; name sibling elements are not affected. Did you noticed the @lang is also gone?​​​​​​​

Use-case 2 Sub 2:  Assign into populated unbounded element indicating which instance with a predicate

Initial State

$vFreeCartItem has

<item xmlns="http://www.jorge.herreria.net/cart">   
    <
name lang="en-us">bluetooth keyboard</name>
    <name lang="sp-mex">teclado bluetooth</name>
    <name lang="fr">clavier bluetooth</name> 
    <
quantity uom="ea">1.0</quantity>  
</
item>

Stitch:

($vFreeCartItem/ns0:item/ns0:name[2]) .ASSIGN(“XXX”)

Output:

$vFreeCartItem gets

<item xmlns="http://www.jorge.herreria.net/cart">   
    <
name lang="en-us">bluetooth keyboard</name>
    <name lang="sp-mex">XXX</name>
    <name lang="fr">clavier bluetooth</name> 
    <
quantity uom="ea">1.0</quantity>  
</
item>

 

Explanation: only the name of the second instance is affected

 

 

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.