WSO2 BPEL assign to mapping list or collection - wso2

I am using WSO2 BPS 3.2.0 and I have strange problem to assign value to mapping list.
I have message type variable ObjectMappings initialized with
<tns:Message xmlns:tns="http://www.test.sk">
<tns:ObjectMappings>
<tns:ObjectMapping>
<tns:ObjectId/>
<tns:Id/>
</tns:ObjectMapping>
</tns:ObjectMappings>
</tns:Message>
I have another collection in input variable. I iterate through input and process data. At the end I assign new Id for every processed ObjectId into variable above.
<bpel:copy>
<bpel:from part="return" variable="input"><bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[Body/Object[round($Counter)]/#Id]]></bpel:query></bpel:from>
<bpel:to part="parameters" variable="ObjectMappings"><bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[ns4:ObjectMappings/ns4:ObjectMapping[round($Counter)]/ns4:ObjectId]]></bpel:query></bpel:to>
</bpel:copy>
But unfortunately it ends up with fault {http://docs.oasis-open.org/wsbpel/2.0/process/executable}selectionFailure: No results for expression: 'ObjectMappings/ObjectMapping[round($Counter)]/ObjectId' against
<Message xmlns="http://www.test.sk">
<tns:ObjectMappings xmlns="" xmlns:tns="http://www.test.sk">
<tns:ObjectMapping>
<tns:ObjectId/>
<tns:Id/>
</tns:ObjectMapping>
<tns:ObjectMapping>
<tns:ObjectId/>
<tns:Id/>
</tns:ObjectMapping>
</tns:ObjectMappings>
Fault Data No data available.
Fault raises at counter value = 1
When I replace index value round($Counter) with fixed value 1 it works fine. Even when I add logic to handle 2 loops with fixed values it ends up without fault.
So question is: How to assign values into collection?

I found solution in changing order when assigning new element.
Initially I added new element at the end of variable
<tns:ObjectMappings xmlns="" xmlns:tns="http://www.test.sk">
<tns:ObjectMapping>
<tns:ObjectId>1</tns:ObjectId>
<tns:Id>10</tns:Id>
</tns:ObjectMapping>
<tns:ObjectMapping>
<tns:ObjectId/>
<tns:Id/>
</tns:ObjectMapping>
</tns:ObjectMappings>
So I had to assign value using index.
Now I add new element at the start of variable
<tns:ObjectMappings xmlns="" xmlns:tns="http://www.test.sk">
<tns:ObjectMapping>
<tns:ObjectId/>
<tns:Id/>
</tns:ObjectMapping>
<tns:ObjectMapping>
<tns:ObjectId>1</tns:ObjectId>
<tns:Id>10</tns:Id>
</tns:ObjectMapping>
</tns:ObjectMappings>
Now I can assign value by fixed index = 1
I found solution in changing order when assigning new element.
Initially I added new element at the end of variable. So I had to assign value using index.
Now I add new element at the start of variable. So I can assign value by fixed index = 1
<bpel:to part="parameters" variable="ObjectMappings"><bpel:query queryLanguage="urn:oasis:names:tc:wsbpel:2.0:sublang:xpath1.0">
<![CDATA[ns4:ObjectMappings/ns4:ObjectMapping[1]/ns4:ObjectId]]></bpel:query>
</bpel:to>

Related

Xpath Value based on Child Node

From the below xml,i need an xpath to take the id value only when the state is FL.
Please help
<Employee_Details>
<Payroll>
<id>A1</id>
<City>Dallas</City>
<State>TX</State>
</Payroll>
<Payroll>
<id>A2</id>
<City>Orlando</City>
<State>FL</State>
</Payroll>
"i need an xpath to take the id value only when the state is FL"
That can be translated into the following XPath expression :
/Employee_Details/Payroll[State='FL']/id
maybe you want to append /text() at the end to return the text node inside <id> element instead of the element itself.

How to get the value of the parent element from the current element in XSLT?

How to get parent node value using XSLT and XPath, for below xml response : <cartridge name="Standard Grid Wall" type="StandardGridWall"> , I want to get value of type . Please help
Apparently, my comment helped, so here it is, posting it as answer:
How to get the value of the parent node? Use:
<xsl:value-of select="parent::node()" />

How to use contains() with a set of strings in XSLT

I have the following XML snippet:
<figure customer="ABC DEF">
<image customer="ABC"/>
<image customer="XYZ"/>
</figure>
I'd like to check if the figure element's customer attribute contains the customer attributes of the image elements.
<xsl:if test="contains(#customer, image/#customer)">
...
</xsl:if>
I get an error saying:
a sequence of more than one item is not allowed as the second argument of contains
It's important to note that I cannot tell the values of the customer attributes in advance, thus using xsl:choose is not an option here.
Is it possible to solve this without using xsl:for-each?
In XSLT 2.0 you can use:
test="image/#customer/contains(../../#customer, .) = true()"
and you will get a true() result if any of them are true. Actually, that leads me to suggest:
test="some $cust in image/#customer satisfies contains(#customer, $cust)"
but that won't address the situation where the customer string is a subset of another customer string.
Therefore, perhaps this is best:
test="tokenize(#customer,'\s+') = image/#customer"
... as that will do a string-by-string comparison and give you true() if any of the tokenized values of the figure attribute is equal to one of the image attributes.

XSLT - Key() function

I'm a bit confused about this key function:
<xsl:for-each select="article[count(. | key('idkey', #id)[1]) = 1]>
Is there anyone that can briefly explain whats happening in this for-each loop?
The key is: <xsl:key name="idkey" match="/newspapers/newspaper" use="#id"/>
#id is an attribute in newspaper.
Thanks.
The expression key('idkey', #id)[1] selects the first element whose idkey is equal to #id.
The expression count(A|B) = 1 is an insane XSLT 1.0 workaround for testing whether A and B are the same node. (You will also see people using generate-id(A)=generate-id(B) for this.)
Put these together and you are asking whether the current element is the first one in the document that has a particular id value.
This is the basis of the technique called Muenchian Grouping (which becomes redundant in XSLT 2.0).
There is something fishy about the code because the key seems to be matching newspaper id's, not article id's. But perhaps they are related in some way.
In this for-each element
<xsl:for-each select="article[count(. | key('idkey', #id)[1]) = 1]">
The for-each is being applied to the first article element for each #id attribute.
The call key('idkey', #id) is selecting all article elements with the same #id attribute as the current one.
key('idkey', #id)[1] selects the first of all article elements with the same #id.
Because a node cannot appear in a node set more than once, the union . | key('idkey', #id)[1] will contain one node if the current article is the same node as the first article with the same #id. Otherwise it will contain two.
Checking that the value of count() is one selects only the elements that are the first with any #id.
An alternative way of doing this, and the one I prefer, is to use generate-id like this
select="article[generate-id() = generate-id(key('idkey', #id)[1])]"
which checks directly whether the current element is the same one as the first element in the set by comparing their generated IDs.

Sharepoint Designer XSLT count boolean node = true

I have a SharePoint list I converted to XSLT to do some additional grouping and counting and percentages. I need to return the number of items = true within my nodeset, I have:
<xsl:value-of select="count($nodeset/#PartnerArrivedAtCall)"/>
(which returns the count of all the nodes)
I have tried
<xsl:value-of select="count($nodeset/#PartnerArrivedAtCall
[#PartnerArrivedAtCall = 'Yes'])"/>
(returns zero)
and
<xsl:variable name="ArrivedYes"
select="$nodeset/#PartnerArrivedAtCall
[#PartnerArrivedAtCall='Yes']"/>
(also returns zero)
Can you please give me a good example of how to count only the true values (in my XML, true = "Yes")
Thanks!
Try
count($nodeset[#PartnerArrivedAtCall = 'Yes'])
Why don't you use out of the box ddwrt namespace functions to return list property: itemCount
http://msdn.microsoft.com/en-us/library/dd583143(v=office.11).aspx#officesharepointddwrt_listproperty
I have tried xsl:value-of
select="count($nodeset/#PartnerArrivedAtCall[#PartnerArrivedAtCall
= 'Yes')" (returns zero)
Yes, this is correct: an attribute cannot have attributes itself -- in the above you want to count PartnerArrivedAtCall attributes whose PartnerArrivedAtCall attribute has a specific value.
.
.
and xsl:variable name="ArrivedYes"
select=
"$nodeset/#PartnerArrivedAtCall[#PartnerArrivedAtCall='Yes']"
(also returns zero)
This has exactly the same problem as the previous instruction.
Solution:
Use:
$nodeset/#PartnerArrivedAtCall[. ='Yes']