Re: [xsl] How to simplify the xslt expression for multiple conditions

Subject: Re: [xsl] How to simplify the xslt expression for multiple conditions
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Date: Fri, 18 May 2001 09:36:45 +0100
Hi Yang,

Hmm... that is horrible, isn't it.

I think that you might be best off moving to a two-pass solution,
where the first pass does the filtering of your z:row elements to only
include the rows that you're actually interested in, and the second
pass does the processing of those rows to get the output.

You can do this within a single stylesheet if you're happy using one
of the node-set() extension functions to convert from a result tree
fragment to a node set.  Have a top-level controlling template to
manage the process.  Within that, first copy all the z:row elements
that you're actually interested in into a variable, and then apply
templates to the result of converting that (RTF) variable into a node
set:

<xsl:template match="/">
   <!-- first pass: filter -->
   <xsl:variable name="rows-rtf">
      <z:rowset>
         <xsl:copy-of select="z:row

[substring(@SalesOrderNo[string($month)], 10, 2) = $month]
[substring(@SalesOrderNo[string($dayID)], 12, 2) = $dayID]
[substring(substring-after(@CreateDate[string($timeID)],'T'),1,2) = $timeID]
[normalize-space(@SalesCode[string($salesID)])=$salesID]
[normalize-space(@CustomerCode[string($customerID)])=$customerID]
[normalize-space(@StoreCode[string($storeID)])=$storeID]
[normalize-space(@SalesOrderNo[string($salesID)])=$salenoID]

          " />
      </z:rowset>
   </xsl:variable>

   <!-- second pass: transform -->
   <xsl:apply-templates select="exsl:node-set($rows-rtf)/z:rowset" />

</xsl:template>

[Note: I've simplified the expressions just a little bit by taking
advantage of the fact that you're always selecting a node to test.
If, for example, string($month) is '' then it will evaluate to boolean
false, so @SalesOrderNo[string($month)] will be an empty node set, and
a substring on its string value will be an empty string, which will
equal the empty string of $month.  If it's true, then you'll get the
value of the substring of the @SalesOrderNo node compared with the
$month. You can get rid of the calls to the string() function if
$month etc. are strings anyway (which they probably are if they're
parameters?)]

Now you can make your code a lot simpler - you already know that all
the z:row elements that you're getting are the ones you're interested
in.  The keys can stay the same.

Even better would be if the first pass could be done earlier in the
process, so that the XSLT stylesheet only gets the information that it
actually needs to process, and not loads of extra stuff that it isn't
interested in.

Another approach, if you're using a processor that supports EXSLT -
Functions, would be to create a function that returns boolean true if
the context node matches the predicates.  So you could define a
function like:

<func:function name="my:filter">
   <xsl:choose>
      <xsl:when test="

substring(@SalesOrderNo[string($month)], 10, 2) = $month and
substring(@SalesOrderNo[string($dayID)], 12, 2) = $dayID and
substring(substring-after(@CreateDate[string($timeID)],'T'),1,2) =
$timeID and
normalize-space(@SalesCode[string($salesID)])=$salesID and
normalize-space(@CustomerCode[string($customerID)])=$customerID and
normalize-space(@StoreCode[string($storeID)])=$storeID and
normalize-space(@SalesOrderNo[string($salesID)])=$salenoID">

         <func:result select="true()" />
       </xsl:when>
       <xsl:otherwise><func:result select="false()" /></xsl:otherwise>
   </xsl:choose>
</func:function>

Then you can filter the results from your keys by calling the
function:

  key('dailySales', substring(@SalesOrderNo, 12, 2))[my:filter()]

In fact you could use a similar function within the match pattern for
the keys:

<xsl:key name="dailySales" match="z:row[my:filter()]"
         use="substring(@SalesOrderNo, 12, 2)" />

I hope that helps,

Jeni

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



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


Current Thread