RE: [xsl] Are variables allowed in XPATHs?

Subject: RE: [xsl] Are variables allowed in XPATHs?
From: "Roger Glover" <glover_roger@xxxxxxxxx>
Date: Mon, 3 Feb 2003 01:51:41 -0600
Harry Ohlsen wrote:

> Ivan Pedruzzi wrote:
> > http://www.w3.org/TR/xslt#section-Defining-Template-Rules
> > It is an error for the value of the match attribute to contain a
> > VariableReference.
>
> Thanks.  So, XMLSpy is telling me the true story
> and Xalan is kindly accepting my naive XSL!
>
> I must say, I find this restriction somewhat
> amazing.  I assume it's intended to reduce the
> complexity of writing XSL processors?
>
> How do people normally write generic XSLT without
> using variables?

XSLT XPath expressions use variables quite frequently, and they are quite
useful there (see below).  But XSLT XPath match attribute patterns do not
use them at all.


> The only way I can see is to generate the XSLT on
> the fly, via an intermediate template, or code in
> another language, like Java.

I don't think that will be necessary in this case, although there are
certainly cases when XSLT is not the right answer.


> Any suggestions as to the "right way" to do this
> sort of thing would be gratefully received.  Feel
> free to point me to a book or website that
> discusses such things.
>
> I'm loathe to use a non-standard feature, but
> since Xalan seems to be a very well-supported
> processor, I may just live with it, unless there's
> a standard approach that's vaguely clean to code.

Okay here is your original template:

    <xsl:template
        name="delete-section"
        match="/main/document/item[property[(name='report') and
(value=$sectionToDelete)]]"
    >
    </xsl:template>

In your original template the match was suppose to check if the candidate
current node (the "item" element) has a property subelement that has the
right values in its name and value subelements, in which case the template
does nothing.  Presumably this template is used to preempt a template of
lower priority that would otherwise match the same item and do something.

As an aside:  I do not know what the 'name="delete-section"' attribute might
be for except perhaps documentation.  It would seem useless to me to execute
call-template on a template that does nothing.

=======================================
Thus, with a significant amount of guesswork and reading between the lines I
offer this reformulation:

    <xsl:template
        mode="check-delete-section"
        match="/main/document/item[property/name='report']"
    >
        <xsl:if test="not(property/value=$sectionToDelete)"/>
            <xsl:apply-templates/>
        </xsl:if>
    </xsl:template>

I don't have much hope that it matches your actual usage, but it might be a
starting point.

Here is my reasoning in any case:  In this reformulation the pattern match
for item is made only on the basis of the item's property's name being
"report".  Then we specifically check with an <xsl:if> conditional to see if
this item's property's value is the one to delete.  If so, we do nothing,
just like the original template.  If not, we pass the item on to another
template that would match the item, one with no mode setting.

Note also that I changed the 'name="delete-section"' attribute here to a
'mode="check-delete-section"' attribute.  There are two reasons for this
change.  First, the mode attribute gives you a functional distiction rather
than a priority distinction for selecting between this template and the
supposed other template.  Second, instead of preselecting this template by
priority, you can now select it by choice (put a
'mode="check-delete-section"' attribute on the <xsl:apply-templates> element
that invokes this template) and use it to filter the items, ignoring those
that meet the delete criterion, and passing on those that do to that
supposed other template.


In any case, I hope this is helpful in some way or another.

-- Roger Glover
   glover_roger@xxxxxxxxx



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


Current Thread