Re: [xsl] use variable in <xsl:if test=

Subject: Re: [xsl] use variable in <xsl:if test=
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Sat, 2 Mar 2002 07:37:21 +0000
Hi Robert,

> How in the world ;-) can i use a variable in <xsl:if  test=..>
>
> <xsl:variable name="condition" select="*[.//author='C. J. Date']"/>
>
>   <xsl:template match="node()[name()=$entity]">
>  <xsl:if test="boolean(string($condition))">
>    <xsl:copy-of select="*"/>
>  </xsl:if>
>   </xsl:template>

One of the weirder XSLT rules is that you cannot use variables in
match patterns. So the fact that you have a variable reference --
$entity -- in the match attribute of xsl:template is probably the
cause of the stylesheet not working at all.

However, I think that the logic is probably wrong as well. The
$condition variable is set to the document element, provided the
document element has an author descendant element whose value is 'C.
J. Date'.

Then you try to match those nodes whose name is equal to the string
value of the $condition variable. The string value of the document
element (which is what's held in the $condition variable) is going to
be a big long string containing all the text in the document.
Considering that one of the values has to be 'C. J. Date' (which
contains spaces), there is absolutely no way that any element could
have that string as its name!

Is this code related to the code that I gave you for your other
problem? If so, it looks as though I didn't explain it thoroughly
enough. To clarify a little, I was assuming that $type (the name of
the kind of nodes that you're after) would be set to a string using
something like:

<xsl:variable name="type" select="'article'" />

And that $nodes (the nodes that you're after) would be set to a node
set using something like:

<xsl:variable name="nodes"
              select="//article[author = 'C. J. Date']" />

With those variables set up, the $nnodes variable counts the number of
nodes (this is for efficiency, since it's used again and again in the
template):

<xsl:variable name="nnodes" select="count($nodes)" />

The following template matches all elements. Whenever it's applied to
an element, it locates all the descendants of the element whose name
is equal to the string held in the $type variable -- all article
elements in this case. If there aren't any such descendants (which
happens for the article elements themselves, and for other elements
like 'issue' and 'number' which don't contain articles but will have
templates applied to them), then the node gets copied completely. If
there are such descendants *and* those descendants belong to the set
held in $nodes (that's what the [count(.|$nodes) = $nnodes] predicate
is testing), then it does a recursive copy -- it copies the element
that it's on, adds its attributes (if there are any), and then applies
templates to the children. Any child elements are processed by this
template, so it works recursively down the tree.

<xsl:template match="*">
  <xsl:variable name="descendants"
                select="descendant::*[name() = $type]" />
  <xsl:choose>
    <xsl:when test="not($descendants)">
      <xsl:copy-of select="." />
    </xsl:when>
    <xsl:when test="$descendants[count(.|$nodes) = $nnodes)]">
      <xsl:copy>
        <xsl:copy-of select="@*" />
        <xsl:apply-templates />
      </xsl:copy>
    </xsl:when>
    <!-- otherwise the element contains nodes of the specified type,
         but they aren't the ones you're interested in -->
  </xsl:choose>
</xsl:template>

If that wasn't what you were trying to do in the code that you sent,
or the above isn't working in the way that you want it to, then please
post again explaining what you wanted to achieve and what's going
wrong. It's great when people send XSLT code, because it often helps
us tell where misunderstandings are arising, but sometimes it's hard
to work out what's going wrong when we don't know what "right" would
be :)

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread