RE: [xsl] Slow XSLT

Subject: RE: [xsl] Slow XSLT
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 7 Mar 2008 11:59:35 -0000
> I am reading one of the articles that Manfred has suggested 
> (Michael Kay: What kind of language is
> XSLT?) so that I can learn more about using node sets, apply 
> templates and recursion but I do not fully understand some of 
> the XPATH expressions.

Please note, that article was written in 2001 and relates to XSLT 1.0.
> 
> 
> These are the expressions used to compute the teams
> standings:
> 
> 1 - <xsl:variable name="teams" select="//team[not(.=preceding::team)]"/>
> 
> I know that this expression is getting a node set of all the 
> unique team elements.

Yes. In XSLT 2.0 you would use <xsl:for-each-group> here.
> 
> I am confused about the "." (dot) in this expression and the 
> comparisson with the preceding::team.
> 
> For the first team, does the "." (dot) match the value of the 
> node - 'Brazil' - and preceding::team match the value as well?

The expressions "." and "preceding::team" both evaluate to node-sets. ("."
is a node-set with one member). When you compare two node-sets using "=" the
result is true if there is any node in the first set whose string value is
equal to the string value of a node in the second node-set. The string value
of an element such as <team score="1">Scotland</team> is "Scotland".

> 
> 2 - Here we are inside a loop
> <xsl:template match="results">
>   <xsl:for-each select="$teams">
>     <xsl:variable name="this" select="."/>
> 
> Again does "." match the value of each team or the whole team element?

There's no "matching" going on here. "." is an expression whose value is a
(singleton) node-set, in this case one of the nodes in the node-set $teams:
presumably a <team> element.
> 
> count($matches[team=$this])
> 
> When you use this predicate [team=$this] are we comparing the 
> value of the element or the team elements ? 

"team" is short for "child::team". So you are selecting all the nodes in
$matches that have a child whose name is "team" and whose string-value is
equal to [the string value of] $this.


> 
> 4 - <xsl:variable name="won"
> select="count($matches[team[.=$this]/@score &gt; 
> team[.!=$this]/@score])"/>
> 
> I know that this expression is computing the victories of a 
> particular team. However, I do not understand the logic of 
> the expression. We have an extra predicate:
>  
> [team[.=$this]/@score 
> 
> Why cant we just use [team=$this]/@score ?

Because the @score is an attribute of the team, not of the match. The
predicate [team=$this] is fine for selecting matches in which this team
participated, but we want to select one of the teams in the match, not just
the match.
> 
> 5 - <xsl:variable name="for"
> select="sum($matches/team[.=current()]/@score)"/>
> 
> What does current() mean in here? Is it the same as the $this 
> variable? 

Yes, in this context. I don't know why I wrote some of the expressions using
$this and some using current() - either would work.
> 
> In this case we are not using a predicate for the $matches 
> variable. why? 

We don't need to. To find out how many goals Scotland scored, we need to
select all the <team> elements equal to Scotland, across all the matches,
and then sum their @score attributes. Matches in which Scotland didn't play
will contribute nothing to the result.

To put it another way, asking "how many goals did Scotland score in all
matches where they played?" gives the same answer as "how many goals did
Scotland score in all matches?"

Michael Kay

Current Thread