Paul
Paul

Reputation: 3954

More efficient approach to XSLT for-each

I have an XSLT which takes a . delimted string and splits it into two fields for a SQL statement:

<xsl:for-each select="tokenize(Path,'\.')">
  <xsl:choose>
    <xsl:when test="position() = 1 and position() = last()">SITE = '<xsl:value-of select="."/>' AND PATH = ''</xsl:when>
    <xsl:when test="position() = 1 and position() != last()">SITE = '<xsl:value-of select="."/>' </xsl:when>
    <xsl:when test="position() = 2 and position() = last()">AND PATH = '<xsl:value-of select="."/>' </xsl:when>
    <xsl:when test="position() = 2">AND PATH = '<xsl:value-of select="."/></xsl:when>
    <xsl:when test="position() > 2 and position() != last()">.<xsl:value-of select="."/></xsl:when>
    <xsl:when test="position() > 2 and position() = last()">.<xsl:value-of select="."/>' </xsl:when>                            
    <xsl:otherwise>zxyarglfaux</xsl:otherwise>
  </xsl:choose>                 
</xsl:for-each>

The results are as follows:

INPUT: North         OUTPUT: SITE = 'North' AND PATH = ''
INPUT: North.A       OUTPUT: SITE = 'North' AND PATH = 'A'
INPUT: North.A.B     OUTPUT: SITE = 'North' AND PATH = 'A.B'
INPUT: North.A.B.C   OUTPUT: SITE = 'North' AND PATH = 'A.B.C'

This works, but is very lengthy. Can anyone see a more efficient approach?

Thanks!

Upvotes: 1

Views: 150

Answers (3)

Sean B. Durkin
Sean B. Durkin

Reputation: 12729

A late answer, but the simplest correct XSLT 2.0 solution is...

<xsl:value-of select="string-join( 'SITE = ', substring-before(concat(Path,'.'),'.'),
                              ' AND PATH = ', substring-after(Path,'.'), ' '), '''')" />

Upvotes: 0

Jost
Jost

Reputation: 5840

How about this:

<xsl:text>SITE = '</xsl:text>
<xsl:choose>
    <xsl:when test="contains($Path, '.')>
       <xsl:value-of select="substring-before($Path, '.')"/>
    </xsl:when>
    <xsl:otherwise>
       <xsl:value-of select="$Path"/>
    </xsl:otherwise>
</xsl:choose>
<xsl:text>' AND PATH = '</xsl:text>
<xsl:value-of select="substring-after($Path, '.')"/>
<xsl:text>'</xsl:text>

Simply takes the part before the first dot and puts it into the first condition, then puts the part after the first dot into the second condition. If there is no dot in the Path, this has to be handled as special case for the first condition, because then substring-before and -after return an empty string. It has not to be handled specifially for the second condition.

Upvotes: 1

Jeff
Jeff

Reputation: 1558

Do you really need to tokenize? Looks like you are just splitting on the FIRST period. In this case, you could just do...

<xsl:text>Site = '</xsl:text>
<xsl:value-of select="substring-before(Path,'.')"/>
<xsl:text>' AND PATH = '</xsl:text>
<xsl:value-of select="substring-after(Path,'.')"/>
<xsl:text>'</xsl:text>

Upvotes: 2

Related Questions