Skip to main content
Announcements
See what Drew Clarke has to say about the Qlik Talend Cloud launch! READ THE BLOG
cancel
Showing results for 
Search instead for 
Did you mean: 
_AnonymousUser
Creator III
Creator III

Distinguishing null values, empty values and elements not present

Hello,
we are building an webservice that will be updating data. For simplicity, lets assume that there are 3 elements that can be updated (A as xs:string, B as xs:date and C as xs:integer).
We need to be able to distinguish whether element was ommited in the request (means - do not update), was present and was set to null value (empty string or xsi:nil, means - update and set to null), was present and was set to not null value (means - update to given value).
What is the best approach to accomplish this in Talend ESB? It seems like ommited elements and elements with empty/null value are both treated as "null" in tXMLMap.
Any advice appreciated.
Few examples:
<A>val1</A><B>2015-01-01Z</B><C>1</C> <!-- update all -->
<A>val1</A><C>1</C> <!-- update A and C, leave B unchanged -->
<A>val1</A><C xsi:nil="true" /> <!-- update A, leave B unchanged, set C to null -->
Labels (3)
10 Replies
Anonymous
Not applicable

Use an XPath to test to see if the element actually exists combined with the null check. So if it is null and doesn't exist it means one thing, if it is null and does exist it means the other thing.
_AnonymousUser
Creator III
Creator III
Author

hello,
could you be please a little more specific?
I tried to create an XPATH expression in TXMLMap to test if this node is present however it failed to compile (    boolean ()) , seems like these expressions do not support xpath.
How do I create an xpath expression in tXMLMap?
Thanks,
Adam
Anonymous
Not applicable

Use a tExtractXMLField component to test the XPath. Use that component to return the full XML and the result of the XPath. Then send that to a tMap and use conditional logic based on the result of the XPath to decide where to send the XML for further processing.
Anonymous
Not applicable

                                                                           
Thanks, this got me going, however still not there...
I configured the tExtractXMLField as (I think) you suggested. The payload gets extracted properly. However population of fi_string fails - in the error log I can see either - seems like the result must be a node:

Exception occurred evaluting XPath: The result of the XPath expression is not a Node. It was: false of type: java.lang.Boolean
or
Exception occurred evaluting XPath: The result of the XPath expression is not a Node. It was: true of type: java.lang.Boolean
depending of whether the element was or was not there.
Screenshot:
0683p000009MAfX.png
Anonymous
Not applicable

It's a bit difficult to debug this without seeing it, but it sounds like you do not have the correct type set for your column. I'm guessing you have it set as a String but the data is returning a Boolean. The response type must match the column type. I'm guessing that changing the column type to a Boolean will fix this.
Anonymous
Not applicable

Are you able to see the attached screenshot in my previous post? On the bottom side there is a partial screenshot from the schema. The column I am populating it to is defined as "Boolean" and "Get Nodes" property on this column is unchecked.
Anonymous
Not applicable

Sorry I missed that. What you are doing looks OK. It must be something to do with the XPath. XPaths are notoriously tricky with Talend and I tend to try them out on test sites online before plugging them into Talend......and still have trouble getting some of them to work. I'm afraid I can't give you the answer on this one. I think you will need to play around with it until you get it right.
Anonymous
Not applicable

I believe the problem is in how the code is generated.
In my case:
row2.payload = ParserUtils
.parseTo_Document(str_tExtractXMLField_1);
org.dom4j.XPath xTmp1_tExtractXMLField_1 = temp_tExtractXMLField_1
.createXPath(nsTool_tExtractXMLField_1
.addDefaultNSPrefix(
"boolean(cbs:validateRequest/cbs:msgDataReq/tns:t_ulica)",
loopQuery_tExtractXMLField_1));
xTmp1_tExtractXMLField_1
.setNamespaceURIs(xmlNameSpaceMap_tExtractXMLField_1);
xTmp1_tExtractXMLField_1
.setNamespaceContext(namespaceContext_tExtractXMLField_1);
Object obj1_tExtractXMLField_1 = xTmp1_tExtractXMLField_1
.evaluate(temp_tExtractXMLField_1);
if (obj1_tExtractXMLField_1 instanceof String
|| obj1_tExtractXMLField_1 instanceof Number) {
resultIsNode_tExtractXMLField_1 = false;
str_tExtractXMLField_1 = String
.valueOf(obj1_tExtractXMLField_1);
} else {
resultIsNode_tExtractXMLField_1 = true;
node_tExtractXMLField_1 = xTmp1_tExtractXMLField_1
.selectSingleNode(temp_tExtractXMLField_1);
str_tExtractXMLField_1 = xTmp1_tExtractXMLField_1
.valueOf(temp_tExtractXMLField_1);
}
And the problem is that obj1_tExtractXMLField_1 is created as "Boolean" (which is correct), however the subsequent test checks it only agains String or Number, anything else is considered a Node.
I believe this might actually be a bug that the generated code does not check for Boolean.
Anonymous
Not applicable

Yep, after changing the Xpath expression from boolean(..) to count(..), it started working.