Reputation: 735
I am trying to create an array and append few values to it and output the transformed text by iterating over this array. But the output is ignoring the content of xsl:text.
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
version="3.0">
<xsl:strip-space elements="*" />
<xsl:template name="test" match="/">
<xsl:param name="data" select="data"></xsl:param>
<xsl:variable name="myData" select="$data" />
<xsl:variable name="myArray" as="array(xs:string)">
<xsl:sequence select="array{}" />
</xsl:variable>
<xsl:sequence select="array:append($myArray, 'John')" />
<xsl:sequence select="array:append($myArray, 'Peter')" />
<xsl:for-each select="1 to array:size($myArray)">
<xsl:text>Person name is : </xsl:text>
<xsl:value-of select="array:get($myArray,.)" />
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This output as
["John"]
["Peter"]
While I was expecting
Person name is : John
Person name is : Peter
Upvotes: 1
Views: 117
Reputation: 243579
This pure XPath expression does the wanted processing, regardless of how many items must be put into the resulting array.
Note that in the general case the function may do some processing of each input item and append to the array the result of this processing. Also, using this solution there is no need at all to define any xsl:variable
to hold the array, and thus no shadowing and consuming unnecessary memory:
fold-left(("John", "Peter", "Kevin", "Ryan"), [],
function($accum as array(*), $inputItem)
{
array:append($accum, $inputItem)
}
)
When the expression is evaluated the expected, correct result is produced:
["John","Peter","Kevin","Ryan"]
An example of processing each input item before placing it in the resulting array:
fold-left(("John", "Peter", "Kevin", "Ryan"), [],
function($accum as array(*), $inputItem)
{
array:append($accum, string-length($inputItem))
}
)
When the expression is evaluated the expected, correct result is produced:
[4,5,5,4]
With a long input, that is not suitable for manual array appends, for example, produce the first N
numbers with value 6 * k - 1
, where k
varies from 1
to N
:
fold-left((1 to 50), [],
function($accum as array(*), $inputItem)
{
array:append($accum, $inputItem * 6 -1)
}
)
When the expression is evaluated the expected, correct result is produced:
[5,11,17,23,29,35,41,47,53,59,65,71,77,83,89,95,101,107,113,119,125,131,137,143,149,155,161,167,173,179,185,191,197,203,209,215,221,227,233,239,245,251,257,263,269,275,281,287,293,299]
Upvotes: 0
Reputation: 117140
I believe that the main problem with your attempt is that the instruction:
<xsl:sequence select="array:append($myArray, 'John')" />
does not modify the $myArray
variable. It merely writes to the output the result of appending a member to the (empty) array in $myArray
, while the size of the array itself remains 0.
If instead you use:
<xsl:variable name="myArray" select="array:append($myArray, 'John')" />
and:
<xsl:variable name="myArray" select="array:append($myArray, 'Peter')" />
you should get the result you seek.
BTW, you can shorten:
<xsl:variable name="myArray" as="array(xs:string)">
<xsl:sequence select="array{}" />
</xsl:variable>
to:
<xsl:variable name="myArray" select="array{}"/>
P.S. A purist will tell you that in my suggestion the original $myArray
variable is also not being modified; it is only shadowed by binding another value to the same name.
Upvotes: 2