RE: [xsl] [XSL] Counting Child Nodes?

Subject: RE: [xsl] [XSL] Counting Child Nodes?
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 19 Oct 2007 16:02:20 +0100
>     <xsl:template match="book">
>         <xsl:variable name="rendition">
>             <xsl:value-of select="./@rendition"/>
>         </xsl:variable>

Use <xsl:variable name="rendition" select="@rendition"/>. It's shorter and
much more efficient.

>         <div>
>             <p>
>                <xsl:choose>
> 
>                     <xsl:when test="$rendition!=''">

Avoid !=. Use not($rendition = ''). The difference arises when $rendition is
an empty sequence.

>                         <div>
>                             <xsl:attribute name="class">
>                                 <xsl:value-of select="$rendition"/>
>                             </xsl:attribute>

Use <div class="{$rendition}">, unless you're paid by the number of lines of
code you write.

>                             <xsl:if
> test="string-length(child::text())&lt;'25'">

Don't put numbers in quotes. You can write this as
test="string-length(child::text()) &lt; 25". More importantly, I don't know
what you're trying to test. The context node is a <book> element, so its
first text node is the whitespace before the first <p>. I can't correct this
for you because I simply don't know what you intended. 

>                                 <xsl:attribute name="style"> 
> background-image:url('<xsl:value-of
>                                         
> select="./@rendition"/>.png') </xsl:attribute>
>                             </xsl:if>
>                             <xsl:if test="string-length('25 ' &lt;
> child::text() &lt; '50')">

The construct (25 < $x < 50) is no longer allowed in XSLT 2.0. The reason is
that although it's valid in 1.0, it doesn't mean what you think it means. If
$x is 10, for example, it evaluates (25 < 10) to false, and then evaluates
(false() < 50) which converts to (0 < 50) which is true. Write (25 < $x and
$x < 50).

But it hardly matters: test="string-length(EXPR)" where EXPR is a boolean
expression will always return true in 1.0 (in 2.0 it gives you a type error,
the argument must be a string). You meant

test="25 < string-length($x) and string-length($x) < 50)" 

>                                 <xsl:attribute name="style"> 
> background-image:url('<xsl:value-of
>                                         
> select="./@rendition"/>_med.png') </xsl:attribute>
>                             </xsl:if>
>                              <xsl:if test="count(child::p) &gt; 1">
>                                 <xsl:attribute name="style"> 
> background-image:url('<xsl:value-of
>                                         
> select="./@rendition"/>_large.png') </xsl:attribute>
>                             </xsl:if>

Rather than generating three attributes called style, of which all but the
last will be discarded, I would be inclined to use xsl:choose and only
generate one of them. In fact, I would put the conditional logic up front:

<xsl:variable name="png-suffix">
 <xsl:choose>
   <xsl:when test="..."/>
   <xsl:when test="...">_med</xsl:when>
   <xsl:when test="...">_large</xsl:when>
 </xsl:choose>
</xsl:variable>
<div class="{$rendition}"
style="background-image:url('{$rendition}{$png_suffix}.png')">


Having said all this, I don't know why your code isn't working, but I would
fix the above so you have something slightly more respectable to debug.

Michael Kay
http://www.saxonica.com/


> 
>                             <p>
>                                 <xsl:call-template name="rend"/>
>                                 <xsl:apply-templates/>
>                             </p>
>                         </div>
>                     </xsl:when>
>                     <xsl:otherwise>
>                         <!--Don't display anything-->
>                     </xsl:otherwise>
>                 </xsl:choose>
>             </p>
>         </div>
>     </xsl:template>
> 
> XML:
> 
> <book topic="Technology" rendition="xslt" author="Tennison, Jeni" 
> title="Beginning XSLT">
> 
>     <p>New York: Apress, 2002.</p>
>     <p>The book serves as an introduction to XSLT based on 
> the examples of a television program set. A resourceful book 
> for those new to the technology.</p>
>   </book>
> 
> I want to use the code displayed above (XML) to display the 
> file name with the name of xslt_large, and now in the HTML 
> source it does not display that, even though the code above 
> has two <p> tags. Can anyone please help me out?
> 
> Anything is appreciated.
> 
> Alice

Current Thread