technocrat
technocrat

Reputation: 735

XSL output array of string as text

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

Answers (2)

Dimitre Novatchev
Dimitre Novatchev

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

michael.hor257k
michael.hor257k

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

Related Questions