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:
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 I laugh of my 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:
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.
![]() |
<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:
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:
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
Also read the blog "Data Stitch: Append for Complex Content Elements". It explains other cases not covered in this blog
https://blogs.oracle.com/integration/data-stitch-append-for-complex-content-elements
To append a complex type complex content element (aka parent element) the way to do it is to create in a variable the instance and then using the variable append the instance into the unbounded element. I will write a blog for that use case, but for now I wanted to let you know