Re: [xsl] [XSL] Calculating Length of String Variables

Subject: Re: [xsl] [XSL] Calculating Length of String Variables
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Thu, 13 Sep 2007 15:11:40 +0200
Hi Alice,

While trying to understand what you are after, while trying to interpret your code, it seems that you want a structure like the following:

 if $image_src has a length of 4 or 5, use the whole @url
 if $image_src has a length of 6, use the first 4 characters of @url
 $image_src and @url are the same
 @url is always a number (not sure, but I guess that from your text).

You have a match for the element 'graphic'. Inside it, you construct an img html tag (img element). Instead of writing extensive xsl:when statements, you can easier maintain your code when you place it inside matching templates. In addition, you may want to use attribute value templates, which is a shorthand for writing attributes. It will look something like this.

<!-- generic case -->
<xsl:template match="graphic">
    <img src="images/{@url}.gif" alt="Picture No. {@url}" />
</xsl:template>

<!-- specific case, 6 or more digits -->
<xsl:template match="graphic[number(@url) > 99999]">
<img src="images/{substring(@url, 1, 4)}" alt="Picture No. {substring(@url, 1, 4)}" />
</xsl:template>


In general, when doing XSLT, you decide on the most generic match as a "fits all" and "catch all". Then you create special rules for the exception cases. In the example above: the general rule (your xsl:otherwise in xslt) is the one that matches "graphic", the special rules are the ones that need special treatment. I.e., when the string is too long.

In your code you have three specific cases. If that is necessary, you can replace the above with the following, but you must be certain that your source data is correct. I added the general case as exception: if your rules do not match, you show an error:

<!-- unknown image found -->
<xsl:template match="graphic">
<xsl:message terminate="yes">Illegal picture found with url:<xsl:value-of select="@url" /></xsl:message>
</xsl:template>


<!-- specific case: 4 or 5 digits -->
<xsl:template match="graphic[@url > 999 and @url &lt; 100000]">
    <img src="images/{@url}.gif" alt="Picture No. {@url}" />
</xsl:template>

<!-- specific case, 6 digits -->
<xsl:template match="graphic[string-length(@url) = 6]">
<img src="images/{substring(@url, 1, 4)}" alt="Picture No. {substring(@url, 1, 4)}" />
</xsl:template>



As you see, it is very easy to maintain this code: just add more rules to it. If you need more processing, add the appropriate <xsl:apply-templates /> and/or appropriate matching templates. Whenever you find yourself writing an extension xsl:choose statement based on something that you can do with predicates, in 90% of the situation (debatable of course) it will be more readable and less error prone to do it with matching template.


The difference: in your method, you have to think of every scenario, telling the processor what to do and you are programming as if you are a C/VB/PHP/Java etc programmer (leading to more code), the other method is where xslt shines and you let the processor pick out the correct rules for you based on the input tree (leading to less code). This is called declarative programming and the push vs. pull model (but I never know which one is which, so I decided to use the more familiar "applying templates and matching templates" against "traditional imperative programming style with if/switch/case/when etc").

Good luck with coding in XSLT!

Cheers,
-- Abel Braaksma





Alice Ju-Hsuan Wei wrote:
Thanks to Michael and Jing. This part is now working and prints out the "value of the string length" accurately.

However, when I tried to use the node with the result of "123456," it prints out the "string-length" as a 6 preperly. But when I try to run a "test" of action according to this result, it does not perform any of the actionsth as in <xsl:when test="string-length($image_src_ ='6'">, but performs the actions as in <xsl:when-test="string-length($image_src)='4' or '5'"> as shown below:

<xsl:when test="string-length($image_src) = '4' or '5'">
<img>
<xsl:attribute name="src">images/<xsl:value-of select="./@url"/>.gif</xsl:attribute>
<xsl:attribute name="alt"> Picture No. <xsl:value-of select="./@url"/>
</xsl:attribute>
</img>
</xsl:when>
<xsl:when test="string-length($image_src) = '6' ">
<img>
<xsl:attribute name="src">images/<xsl:value-of select="substring($image_src,1,4)"
/>.gif</xsl:attribute>
<xsl:attribute name="alt"> Picture No. <xsl:value-of select="substring($src,1,4)"/>
</xsl:attribute>
</img>
</xsl:when>


Does anyone know if there is something I should have done that I have not?

Thank again.

Current Thread