1

I have a xml file with rows like this :

<Data>
    <a>something</a>
    <b>20120601</b>
    <c>something else</c>
</Data>

the value in is a date formatted YYYYMMDD

I have a small template that processes each row, and which is working fine (for it doesn't do much)

Now my question : How can I process a row only if the date in B is greater (later) than 60 days before today (current date) ? So if the date is recent -> process the row, else don't.

Filburt
  • 17,626
  • 12
  • 64
  • 115
FabriceN
  • 11
  • 1
  • 2
  • There is no way to access the current date in standard XSLT / XPaths, you'll need some kind of extension function. Which XSLT processor are you using? – MiMo Jun 08 '12 at 14:27

3 Answers3

2

Here is a complete, short and simple XSLT 2.0 solution:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:param name="pPeriod" select="'P60D'"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match=
 "Data
   [current-date()
   -
    xs:date(concat(substring(b,1,4),
                   '-',
                   substring(b,5,2),
                   '-',
                   substring(b,7)
                   )
            )
    gt xs:dayTimeDuration($pPeriod)
   ]"/>
</xsl:stylesheet>

When applied on this XML document:

<t>
    <Data>
        <a>something</a>
        <b>20120601</b>
        <c>something else</c>
    </Data>
    <Data>
        <a>something</a>
        <b>20120420</b>
        <c>something else</c>
    </Data>
    <Data>
        <a>something</a>
        <b>20120301</b>
        <c>something else</c>
    </Data>
</t>

the wanted, correct result (last Data element "deleted") is produced:

<t>
      <Data>
            <a>something</a>
            <b>20120601</b>
            <c>something else</c>
      </Data>
      <Data>
            <a>something</a>
            <b>20120420</b>
            <c>something else</c>
      </Data>
</t>
Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
0

As the commenter said, XSL cannot do this by itself. You would need to first work out what the date was 60 days ago, and pass this in to your XSL as a parameter.

In PHP, you could work out the day in the following way:

$date_60_days_ago = date('Y-m-d H:m:s', strtotime("-60 days"));

As for the XSL, see this XMLPlayground session (I pass the date in manually for the purpose of this demo)

http://www.xmlplayground.com/sK82Q4

Mitya
  • 33,629
  • 9
  • 60
  • 107
0

As MiMo already stated there's no built in function to get the current date in xslt 1.0. You can pass params into your xslt stylesheet but this depends on the xslt processor you use.

If you pass the back date (curret date minus 60 days) as a param, your test can be as simple as that:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="backdate" />

    <xsl:template match="Data">
        <xsl:if test="(./b &gt;= $backdate)">
            <xsl:apply-templates />
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

In xslt 2.0 you can use the built in current-date() function

<xsl:variable name="backdate" select="current-date() -60*xs:dayTimeDuration('P1D')" />

... but you'll need to cast your <b> date value to accordingly - or format the backdate variable to fit your date value.

Adopted from Dimitre's answer on subtracting days.

Community
  • 1
  • 1
Filburt
  • 17,626
  • 12
  • 64
  • 115