[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: Read ,Compare the value and do something


Subject: Re: Read ,Compare the value and do something
From: Jeni Tennison <Jeni.Tennison@xxxxxxxxxxxxxxxx>
Date: Tue, 23 May 2000 11:27:42 +0100

Cheun,

A stylesheet that does what I think you want is at the end of this email,
but I'll just answer your questions individually first.

>	1. Pass in a value to the XSL, eg. the current date.

Yes, you can pass in parameters to the stylesheet.  How you do it depends
on the XSLT processor you're using.  For example, in SAXON, you can add
them by appending param=value to the command line.  So, to pass in the
current date, I'm using the command line:

saxon -o out.xml -t test.xml test.xsl today="23 May 2000"

Within the stylesheet, you need to declare the parameters that you'll be
using:

<xsl:param name="today" />

>	2. Compare the current date to the <BESTBEFORE> tag value.

This is date manipulation stuff that would be easier if the dates were in
an easily-comparable format.  So, first you need to convert them into a
format like YYYYMMDD format, so that later dates always have higher
numbers.  To do that, you have to parse the dates that you have, both the
'today' value and the 'BESTBEFORE' value, using a sequence of variable
assignments and some internal definitions of the equivalence of months and
(or you could do it all in one go, it's just easier to read this way):

<!-- make sure the day has a leading zero -->
<xsl:variable name="day"
select="format-number(number(substring-before(dateString, ' ')), '00')" />
<xsl:variable name="monthString"
select="substring-before(substring-after(dateString, ' '), ' ')" />
<xsl:variable name="month" select="document('')//foo:month[@name =
$monthString]/@num" />
<xsl:variable name="year"
select="substring-after(substring-after(dateString, ' '), ' ')" />
<xsl:variable name="date" select="number(concat($year, $month, $day))" />

The months are specified within the stylesheet itself in the form:

<foo:month name="January" abbr="Jan" num="01" />

I just added the abbr for reusability; it's never used in the stylesheet.

Comparing the dates to work out what to do is then as simple as $today > $bb.

>	3. Change the <CONDITION> value if it is expired, if not preserve
>	   the value. 

As another reply to your message pointed out, you're not really *changing*
the CONDITION value, you're creating a new output document that is exactly
the same as the existing one, but has different CONDITION values.  You can
create copies of elements using xsl:copy or xsl:copy-of, or by simply
including them within templates that match them.  xsl:copy just copies the
selected node (and not its attributes and children, if it's an element),
whereas xsl:copy-of copies the selected node and all its attributes and
children.

So, you want to create a copy of the product element, and then have a copy
of the BESTBEFORE element within it, and either a copy of the CONDITION
element (if it's not expired) or a CONDITION element with a value of
'expired' if it is.  With the context node being the product element (e.g.
MILK):

<xsl:element name="{name()}">
  <xsl:copy-of select="BESTBEFORE" />
  <CONDITION>
    <xsl:choose>
      <xsl:when test="$today &gt; $bb">
        <xsl:text>expired</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="CONDITION" />
      </xsl:otherwise>
    </xsl:choose>
  </CONDITION>
</xsl:element>

>	Can XSL do "reading the value of <BESTBEFORE> set it to a
>variable" (I have tried to use <xsl:param> and <xsl:variable>) and pass it
>to another template, eg. pass the <BESTBEFORE> value of <MILK> to the
><BESTBEFORE> of <PORK>?

You *can* set the value of a particular BESTBEFORE to a variable, if you
want.  What you have to be careful about is the scope of the variable.  If
you want it to be accessible within a template, you can:

a. set it at the highest level, e.g.:
  <xsl:variable name="bbMilk" select="/STUFF/MILK/BESTBEFORE" />

b. set it within the PORK template, e.g.:
  <xsl:template match="PORK">
    <xsl:variable name="bbMilk" select="../MILK/BESTBEFORE" />
  </xsl:template>

c. pass it into the PORT template as a parameter, e.g.:
  <xsl:template match="STUFF">
    <xsl:apply-templates>
      <xsl:with-param name="bbMilk" select="MILK/BESTBEFORE" />
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="PORK">
    <xsl:param name="bbMilk" />
  </xsl:template>

I hope that helps.  The complete stylesheet is below.

Cheers,

Jeni

----
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:foo="http://www.epistemics.co.uk/XML/test">

<xsl:param name="today" />

<xsl:template match="STUFF">
  <xsl:variable name="todayDay"
select="format-number(number(substring-before($today, ' ')), '00')" />
  <xsl:variable name="todayMonth"
   select="document('')//foo:month[@name =
substring-before(substring-after($today, ' '), ' ')]/@num" />
  <xsl:variable name="todayYear"
select="substring-after(substring-after($today, ' '), ' ')" />
  <STUFF>
    <xsl:apply-templates>
      <xsl:with-param name="today" select="number(concat($todayYear,
$todayMonth, $todayDay))" />
    </xsl:apply-templates>
  </STUFF>
</xsl:template>

<xsl:template match="STUFF/*">
  <xsl:param name="today" />
  <xsl:variable name="bbDay"
select="format-number(number(substring-before(BESTBEFORE, ' ')), '00')" />
  <xsl:variable name="bbMonthString"
select="substring-before(substring-after(BESTBEFORE, ' '), ' ')" />
  <xsl:variable name="bbMonth" select="document('')//foo:month[@name =
$bbMonthString]/@num" />
  <xsl:variable name="bbYear"
select="substring-after(substring-after(BESTBEFORE, ' '), ' ')" />
  <xsl:variable name="bb" select="number(concat($bbYear, $bbMonth,
$bbDay))" />
  <xsl:element name="{name()}">
    <xsl:copy-of select="BESTBEFORE" />
    <CONDITION>
      <xsl:choose>
        <xsl:when test="$today &gt; $bb">
          <xsl:text>expired</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="CONDITION" />
        </xsl:otherwise>
      </xsl:choose>
    </CONDITION>
  </xsl:element>
</xsl:template>

<foo:months>
  <foo:month name="January" abbr="Jan" num="01" />
  <foo:month name="February" abbr="Feb" num="02" />
  <foo:month name="March" abbr="Mar" num="03" />
  <foo:month name="April" abbr="Apr" num="04" />
  <foo:month name="May" abbr="May" num="05" />
  <foo:month name="June" abbr="Jun" num="06" />
  <foo:month name="July" abbr="Jul" num="07" />
  <foo:month name="August" abbr="Aug" num="08" />
  <foo:month name="September" abbr="Sep" num="09" />
  <foo:month name="October" abbr="Oct" num="10" />
  <foo:month name="November" abbr="Nov" num="11" />
  <foo:month name="December" abbr="Dec" num="12" />
</foo:months>

</xsl:stylesheet>
----
Dr Jeni Tennison
Epistemics Ltd, Strelley Hall, Nottingham, NG8 6PE
Telephone 0115 9061301 ? Fax 0115 9061304 ? Email
jeni.tennison@xxxxxxxxxxxxxxxx



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



Current Thread
Keywords