3

I have an XML schema that contains the following type :

<xs:simpleType name="valuelist">
  <xs:list itemType="xs:double"/>
</xs:simpleType>

A sample XML fragment would be:

<values>1 2 3.2 5.6</values>

In an XSLT transform, how do I get the number of elements in the list?

How do I iterate over the elements?

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
Abelson
  • 99
  • 1
  • 7
  • An element is The elements you are referring to however will be interpreted as text by your xslt processor. – FailedDev Oct 11 '11 at 11:55

4 Answers4

1

If list is strictly spaced, you can count spaces based on string length.

<values>1 2 3.2 5.6</values>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

    <xsl:template match="/">
        <xsl:value-of select="string-length(values) 
                      - string-length(translate(values, ' ', '')) + 1"/>
    </xsl:template>

</xsl:stylesheet>

To iterate over elements you have to split this string. There a lot of examples at SO.

Kirill Polishchuk
  • 54,804
  • 11
  • 122
  • 125
1

I. XPath 2.0 (XSLT 2.0) solution:

count(tokenize(., ' '))

II. XPath 1.0 (XSLT 1.0) solution:

 string-length()
-
 string-length(translate(normalize-space(), ' ', ''))
+ 1

As for iteration over the items of this list:

  1. In XPath 2.0 / XSLT 2.0 just use the above XPath 2.0 expression as the value of a select attribute:

--

 for $i in tokenize(., ' '),
     $n in number($i)
  return
    yourXPathExpression

--

2. In XSLT 1.0 you need to have some more code for splitting/tokenization. There are several good answers to this question (part of them mine) -- just search for something like "xslt split a string"

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
1

In a schema-aware transformation, use count(data(value)).

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
0

With a little imagination you can write your own split function :

<xsl:stylesheet version = '1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
    <xsl:output method='text'/>

    <xsl:template name="split-list">
    <xsl:param name="list" />
    <xsl:param name="separator"/>
    <xsl:variable name="newlist" select="concat(normalize-space($list), $separator)" /> 
    <xsl:variable name="first" select="substring-before($newlist, $separator)" /> 
    <xsl:variable name="remaining" select="substring-after($newlist, $separator)" />
            <xsl:message terminate="no">
            <xsl:value-of select="$first" />
        </xsl:message>

    <xsl:if test="$remaining">
        <xsl:call-template name="split-list">
          <xsl:with-param name="list" select="$remaining" />
                    <xsl:with-param name="separator" select="$separator"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template match="/">
    <xsl:variable name="myList">
            1 2 3.2 5.6
    </xsl:variable>
        <xsl:call-template name="split-list">
            <xsl:with-param name="list" select="$myList" />
            <xsl:with-param name="separator">
                <xsl:text> </xsl:text>
            </xsl:with-param>
        </xsl:call-template>
</xsl:template>
</xsl:stylesheet>

Output :

[xslt] Loading stylesheet D:\Tools\StackOverFlow\test.xslt
[xslt] 1
[xslt] 2
[xslt] 3.2
[xslt] 5.6
FailedDev
  • 26,680
  • 9
  • 53
  • 73