RE: [xsl] Using variables to determine nodesets with conditions

Subject: RE: [xsl] Using variables to determine nodesets with conditions
From: "Paulo Gleich" <pgleich@xxxxxxxx>
Date: Tue, 23 Sep 2003 20:33:57 +0200
Thank you again, Jeni!

Sorry guys for the "netiquette faux pas", I'm new to the list! Won't happen
again ;)

Regards,
Paulo Gleich



-----Original Message-----
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx
[mailto:owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx]On Behalf Of Jeni Tennison
Sent: martes, 23 de septiembre de 2003 19:34
To: Paulo Gleich
Cc: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Using variables to determine nodesets with conditions


Hi Paulo,

> Thanks, Jeni! That's EXACTLY what I was looking for!

Just so others here know what you're talking about - offlist, in reply
to more details to you, we had the exchange:

>> I get an $id passed into the XSL stylesheet by the XSL processor,
>> and for each $id the template uses a different condition to
>> generate the result tree. I could do it like this,
>>
>> <xsl:choose>
>>         <xsl:if test="$id = '1'">
>>                 <xsl:for-each select="PEOPLE/PERSON[NAME != 'Carlos']">
>>                 <xsl:sort select="NAME">
>>                         <xsl:call-template name=""/>
>>                 <xsl:for-each>
>>         </xsl:if>
>>         <xsl:if test="$id = '2'">
>>                 <xsl:for-each select="PEOPLE/PERSON[NAME != 'Maria' and
SURNAME =
>> 'Perez']">
>>                 <xsl:sort select="NAME">
>>                         <xsl:call-template name=""/>
>>                 <xsl:for-each>
>>         </xsl:if>
>>         ...
>> </xsl:choose>
>
> You could do something like:
>
>   <xsl:for-each
>     select="PEOPLE/PERSON[($id = 1 and NAME != 'Carlos') or
>                           ($id = 2 and NAME != 'Maria' and
>                                        SURNAME = 'Perez') or
>                           ...]">
>     <xsl:sort select="NAME" />
>     <xsl:call-template name="" />
>   </xsl:for-each>
>
> If $id = 1 then the PERSON elements that will be selected are those
> whose NAME child doesn't have the value 'Carlos'; if $id = 2 then
> the PERSON elements that will be selected are those whose NAME child
> doesn't have the value 'Maria' and whose SURNAME child has the value
> 'Perez' and so on.
>
> [Personally, I'd apply templates to those PERSON elements rather than
> iterating over them with <xsl:for-each> and then calling a template on
> each one, but that's just a matter of style.]

...

> The thing is, the solution has created another problem, since I was
> using the same concept as before to determine sorting criteria in
> xsl:sort :
>
> <xsl:sort select="*[local-name() = $criteria]"/>
>
> It does work if I have $criteria = 'NAME', but not if $criteria =
> 'NAME/MIDDLENAME'. Is there a way of getting around this, or should
> I better change my XMLs to have all nodes used as sort keys on the
> same level?

You can use a similar kind of trick here:

  <xsl:sort select="NAME[$criteria = 'NAME'] |
                    NAME/MIDDLENAME[$criteria = 'NAME/MIDDLENAME'] |
                    ..." />

This selects the <NAME> element if the $criteria variable has the
value 'NAME', the <MIDDLENAME> element if the $criteria variable has
the value 'NAME/MIDDLENAME' and so on.

This approach (essentially choosing which node to select based on the
$criteria variable) is somewhat easier/more obvious in XPath 2.0,
where you can use:

  <xsl:sort select="if ($criteria = 'NAME') then
                      NAME
                    else if ($criteria = 'NAME/MIDDLENAME') then
                      NAME/MIDDLENAME
                    ..." />

If you want to allow complete flexibility in your $criteria variable,
then there are two routes open to you. One is to use an dyn:evaluate()
extension function (as in EXSLT):

  <xsl:sort select="dyn:evaluate($criteria)" />

Some processors support such a function, so it's worth looking at the
documentation of the processor you're using to see if it does.

Another route is to generate the stylesheet that you use dynamically,
so you actually generate the element:

  <xsl:sort select="NAME/MIDDLENAME" />

when the $criteria variable has the value 'NAME/MIDDLENAME'. If you
want to pursue that route let us know and we'll be able to offer you
more advice.

Cheers,

Jeni

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


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


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


Current Thread