You might noticed some times Data Stitch ASSIGN will volunteer or remove attributes from the targeted element...
On this post I explain the behavior of ASSIGN operation for elements that have attributes and give some ideas for manage it.
There's heavy XML, XSD, XPath lingo in this post. I'll try to explain the lingo w/o going deep into it. I use the lingo with the intent that in case you search over the internet, you get more accurate hits ;-)
Expect twisted humor and a two way conversation.
A quote I like: "What if it works?" ~ me
If ASSIGN is copying the attributes along with the value of the element and you do not want the attributes, the use text() function.
If ASSIGN is removing the existing attributes in the TO element, then you need to save off the attributes and then reassign them back.
(TO XPath Expression).OPERATION(FROM XPath Expression)
Example:
($v1/ns0:customer/ns0:name).ASSIGN(“Jorge Herreria”)
Explanation: The "Jorge Herreria" Literal will be ASSIGNED into the name element of the $v1 variable under the /ns0:customer/ns0:name location path.
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
The ASSING operator works based on the result of FROM XPath Expression. Generally speaking the Result of an XPath Expression can be classified as:
Within the Node classification there can be a Complex Type Simple Content Element (aka Leaf element with attributes for short) or a Complex Type Complex Content Element (aka Complex element for short)
You might say with rolling eyes - Jorge, you are killing me! - I, opening my eyes wide open, respond - I know! I'm about to loose you on the lingo and word play. Here's the post it note, or a napkin explanation. See this XML
Notice /ns0:cart/ns0:item/ns0:name/ element has "Hobitt" as value (simple) and has lang as attribute. This is a Leaf element with Attribute. For /ns0:cart/ns0:inventory notice <ns0:inventory> has a child Element: <ns0:part>. An element that has 1 or more children makes it Complex Element. |
Assigning into Complex Type Simple Content Element is the one I explain in this post.
Me- By the way, I'm not making up these word-play. Those are real XSD concepts. I am making up "Leaf Element with Attribute" and "Complex Element" terms.
So back again to ASSIGN: If the xpath expression results in a Leaf Element with Attributes, then the ASSIGN won't do what you and your private investigator might think!
The ASSIGN will assign the whole enchilada (the whole "data") except the name of the element!
You - Give me an example, now that you made me hungry!
Me - Of course!
Let's say X variable hols the XML |
and Y variable holds the XML |
Stitch | Will resolve |
---|---|
($X/ns0:item/ns0:prices/ns0:price[2].ASSIGN($Y/nso:part/ns0:cost | <ns0:prices> <ns0:price currency="usd">78.90</ns0:price> <ns0:price>321</ns0:price> </ns0:prices> |
($Y.ns0:part/ns0:cost) .ASIGN($X/ns0:item/ns0:prices/ns0:price[1]) |
<ns0:part> <ns0:name>Elf</ns0:name> <ns0:quantity>3</ns0:quantity> <ns0:cost currency="usd">78.90</ns0:cost> </ns0:part> |
You - I'm firing my private investigator! - me - Yup! I did the same with mine...-
Me - Use the text() function. Tell runtime to only pull/fetch/get the text. Here's how
($Y.ns0:part/ns0:cost).ASIGN($X/ns0:item/ns0:prices/ns0:price[1]/text()) |
<ns0:part> <ns0:name>Elf</ns0:name> <ns0:quantity>3</ns0:quantity> <ns0:cost>78.90</ns0:cost> </ns0:part> |
Me - So, what if it works? {mental chewing gum}... You will notice once the /text() is added and comitted, the warning goes away.
You - You gotta be kidding me! Why do I need to put text() function?
Me - I hear you. The important thing is to know how it works and how to make it work for you... The XPath engine has been like that for years. Weird, right?
Me, swallowing hard - Oh oh. You are not going to like it! You are going to ____________.
It cannot not be in 1 sentence. You will need to save off the attribute and re-assign it after setting the new element value. -
You - Be glad you are the messenger!
Both - LOL!
Here's a way to do it:
($mySimpleStringVar).ASSIGN($X/ns0:item/ns0:prices/ns0:price[2]/@currency) | cad |
($X/ns0:item/ns0:prices/ns0:price[2]).ASSIGN($Y/nso:part/ns0:cost) |
<ns0:prices> <ns0:price currency="usd">78.90</ns0:price> <ns0:price>321</ns0:price> </ns0:prices> |
($X/ns0:item/ns0:prices/ns0:price[2]/@currency).ASSIGN($mySimpleStringVar) |
<ns0:prices> <ns0:price currency="usd">78.90</ns0:price> <ns0:price currency='cad'>321</ns0:price> </ns0:prices> |
For you to know, I already try placing the text() function after ns0:price[2]. It blow up at runtime. And then thinking it after the fact, it makes no sense: Assigning a value to a function does not exists in xpath expression language...
The good news are: Many systems do not care when the payload comes with extra attributes; so for those systems we can get away having the extra attribute; but other systems are ore picky.
All right! message delivered and I still alive. Hope knowing how it works give you less surprises.
Cheers