Search code examples
xsltforeachxslt-2.0tokenizesaxon

For-each loop with fn:tokenize


I want to take the value of variable, tokenize it, and loop through the different tokens. My solutions does not work as expected. I must be misunderstanding what tokenize() actually does.

<xsl:variable name="topicCode">1.2.3.4</xsl:variable>
<xsl:variable name="tokenizedTopicCode"><xsl:value-of select="tokenize($topicCode,'\.')"/></xsl:variable>
<mdcomplex name="Topic">
      <xsl:for-each select="distinct-values($tokenizedTopicCode)">
           <xsl:if test="position()=1">
               <md name="chaptercode">
                   <xsl:attribute name="value"><xsl:value-of select="."/></xsl:attribute>
               </md>
           </xsl:if>
          <xsl:if test="position()=2">
              <md name="sectioncode">
              <xsl:attribute name="value"><xsl:value-of select="concat($tokenizedTopicCode[position()=1],'.',.)"/></xsl:attribute>
               </md>
           </xsl:if>
           <xsl:if test="position()=3">
               <md name="subsectioncode">
                   <xsl:attribute name="value"><xsl:value-of select="concat($tokenizedTopicCode[position()=1],'.',$tokenizedTopicCode[position()=2],'.',.)"/></xsl:attribute>
               </md>
           </xsl:if>
           <xsl:if test="position()=4">
               <md name="topiccode">
                   <xsl:attribute name="value"><xsl:value-of select="concat($tokenizedTopicCode[position()=1],'.',$tokenizedTopicCode[position()=2],'.',$tokenizedTopicCode[position()=3],.)"/></xsl:attribute>
               </md>
           </xsl:if>                
       </xsl:for-each>
   </mdcomplex>

Expected:

<mdcomplex name="Topic">
      <md name="chaptercode" value="1"/>
      <md name="sectioncode" value="1.2"/>
      <md name="subsectioncode" value="1.2.3"/>
      <md name="topiccode" value="1.2.3.4"/>
</mdcomplex>

Actual:

<mdcomplex name="Topic">
    <md name="chaptercode" value="1 2 3 4"/>
</mdcomplex>

I also added a <xsl:message> right after the start of the <xsl:for-each> loop:

<xsl:for-each select="distinct-values($tokenizedTopicCode)">
                <xsl:message><xsl:value-of select="."/></xsl:message>

I expected it to output the value of the different tokens (1, 2, 3, 4). Instead, it outputs all tokens in one go: "1 2 3 4".

How can I split the variable into the different tokens and loop through them? I am using Saxon 9.9.1.7 on Oxygen.


Solution

  • You at least need <xsl:variable name="tokenizedTopicCode" select="tokenize($topicCode,'\.')"/> instead of <xsl:variable name="tokenizedTopicCode"><xsl:value-of select="tokenize($topicCode,'\.')"/></xsl:variable>.

    I don't see, however, how you expect to select stuff in e.g. $topicCode with a positional predicate, that variable is not a sequence of items.