1. | Obtain date and time from a website, |
Excellent suggestions and thank you for making them. I think you'll find the stamp attribute is now compliant for the extended format. I've also added attributes to the root element to include: ntp-stratum, source, and frequency. The retrievd timestamp is (or was when I wrote this up), <utc stamp="2005-01-29T13:12:17+00:00"> <year>2005</year> <month>01</month> <day>29</day> <hour>13</hour> <minute>12</minute> <second>17</second> </utc> So a usage might be <p>The time is now <xsl:variable name="now"> <xsl:copy-of select=" document('http://xobjex.com/service/date.xsl')/date/utc/*"/> </xsl:variable> <xsl:text>Yr </xsl:text> <xsl:value-of select="$now/year"/> <br /> <xsl:text>month </xsl:text> <xsl:value-of select="$now/month"/> <br /> <xsl:text>day </xsl:text> <xsl:value-of select="$now/day"/> <br /> <xsl:text>hour </xsl:text> <xsl:value-of select="$now/hour"/> <br /> <xsl:text>min </xsl:text> <xsl:value-of select="$now/min"/> <br /> <xsl:text>sec </xsl:text> <xsl:value-of select="$now/second"/> <br /> <xsl:text>or in iso format, </xsl:text> <xsl:value-of select="document('http://xobjex.com/service/date.xsl')/date/utc/@stamp"/> </p> | |
2. | Obtaining the date in a stylesheet |
Ednote. Asked so often I decided I'd add this solution from Karl. Note it is Linux specific, but MS programmers can obtain the date and pass it to the stylesheet as a command line parameter in a similar way I was having trouble getting the current date into my xslt Finally I came up with this solution for Linux: xsltproc -o foo.html --stringparam date "`date`" foo.xsl foo.xml Inside foo.xsl: <xsl:param name="date">un-known</xsl:param> . . . <!-- This will give you the date of the last update --> <xsl:template match="last-updated"> <xsl:value-of select="$date"/> </xsl:template> | |
3. | Date formatting |
I have a date which is in the form of "CCYYMMDD.HHMMSS" and I'm formatting this date to look like this: "MM/DD/YYYY HH:MM:SS GMT". XML: <Date>19981003.133045</Date> XSL: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/Date"> <html> <head></head> <body> <p> <xsl:value-of select="substring(.,5,2)"/><xsl:text>/</xsl:text><xsl:value-of select="substring(.,7,2)"/><xsl:text>/</xsl:text><xsl:value-of select="substring(.,1,4)"/><xsl:text> </xsl:text><xsl:value-of select="substring(.,10,2)"/><xsl:text>:</xsl:text><xsl:value-of select="substring(.,12,2)"/><xsl:text>:</xsl:text><xsl:value-of select="substring(.,14)"/><xsl:text> GMT</xsl:text> </p> </body> </html> </xsl:template> </xsl:stylesheet> OUTPUT: <html> <head></head> <body> <p>10/03/1998 01:30:45 GMT</p> </body> </html> Christopher R. Maden adds: the code can be found, with documentation, at my website. The stylesheet (iso8601.xsl) may be of interest to anyone looking for an example of recursive string processing, ISO 8601 date and time strings, and semi-complex sorting problems. The whole package may be of interest to anyone doing XML consulting and billing by the hour. Archive: invoice.zip Length Date Time Name 1229 06-05-00 17:46 invoice.css 14119 06-07-00 09:56 invoice.dtd 41642 06-05-00 17:46 invoice.xsl 2331 08-02-00 12:34 sample.xml 2182 05-17-00 14:36 testinvoice.xml 61503 5 files The XSL file can process either XML file to produce HTML output. The DTD is needed to identify IDs within the XML files; the CSS is included in the HTML output. (I was referencing it from the HTML, but multi-file invoices were a little too complicated for accounting types to deal with.) I'll try to do a little documentation over the weekend, but it might be useful in advance of that. A documented version of the invoice package is now available at my web page. Comments and questions are welcome; I hope the ISO 8601 code proves useful to someone. If you expand its functionality or streamline it, please let me know; I can add modifications back into the published code. | |
4. | Formatting Dates |
Heres three functions for formatting a date of the form "YYYYMMDD" into other formats in XSLT: <xsl:template name="standard_date"> <xsl:param name="date" /> <!-- Day --> <xsl:value-of select="substring($date, 7, 2)" /> <xsl:text>/</xsl:text> <!-- Month --> <xsl:value-of select="substring($date, 5, 2)" /> <xsl:text>/</xsl:text> <!-- Year --> <xsl:value-of select="substring($date, 3, 2)" /> </xsl:template> <xsl:template name="short_date"> <xsl:param name="date" /> <!-- Month --> <xsl:value-of select="substring($date, 5, 2)" /> <xsl:text>/</xsl:text> <!-- Year --> <xsl:value-of select="substring($date, 3, 2)" /> </xsl:template> <xsl:template name="long_date"> <xsl:param name="date" /> <!-- Day --> <xsl:value-of select="number(substring($date, 7, 2))" /> <xsl:text> </xsl:text> <!-- Month --> <xsl:variable name="month" select="number(substring($date, 5, 2))"/> <xsl:choose> <xsl:when test="$month=1">January</xsl:when> <xsl:when test="$month=2">February</xsl:when> <xsl:when test="$month=3">March</xsl:when> <xsl:when test="$month=4">April</xsl:when> <xsl:when test="$month=5">May</xsl:when> <xsl:when test="$month=6">June</xsl:when> <xsl:when test="$month=7">July</xsl:when> <xsl:when test="$month=8">August</xsl:when> <xsl:when test="$month=9">September</xsl:when> <xsl:when test="$month=10">October</xsl:when> <xsl:when test="$month=11">November</xsl:when> <xsl:when test="$month=12">December</xsl:when> <xsl:otherwise>INVALID MONTH</xsl:otherwise> </xsl:choose> <xsl:text> </xsl:text> <!-- Year --> <xsl:value-of select="substring($date, 1, 4)" /> </xsl:template> | |
5. | Calculating days up until today |
Ednote: month and date params added for testing. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:data="urn:data-section" exclude-result-prefixes="data"> <xsl:param name="month" select="Jan"/> <xsl:param name="date" select="1"/> <data:month name="Jan" days="0" /> <data:month name="Feb" days="31" /> <data:month name="Mar" days="59" /> <data:month name="Apr" days="90" /> <data:month name="May" days="120" /> <data:month name="Jun" days="151" /> <data:month name="Jul" days="181" /> <data:month name="Aug" days="212" /> <data:month name="Sep" days="243" /> <data:month name="Oct" days="273" /> <data:month name="Nov" days="304" /> <data:month name="Dec" days="334" /> <xsl:template match="/"> Days since January, 1.: <xsl:value-of select="document('')/*/data:month[@name=$month]/@days + $date /> </xsl:template> </xsl:stylesheet> | |
6. | Sorting by date |
I have an XML file with a list of <content> elements as shown below. I need to be able to sort them by publicationDate and only dipslay the first 20 Does anyone have any ideas?. You might want to consider using an extension function to a language with built in date parsing, but if not.... restricted to outputting first 5 in oorder, and showing the sort key for clarity: <x> <content id="66228-135831" displayText="banjo" publicationDate="Wed Jan 01 00:00:00 GMT 1999" /> <content id="66228-135832" displayText="banjo" publicationDate="Wed Aug 02 00:00:00 GMT 2001" /> <content id="66228-135833" displayText="banjo" publicationDate="Wed Jul 03 00:00:00 GMT 2000" /> <content id="66228-135834" displayText="banjo" publicationDate="Wed Jun 04 00:00:00 GMT 2000" /> <content id="66228-135835" displayText="banjo" publicationDate="Wed May 05 00:00:00 GMT 1999" /> <content id="66228-135836" displayText="banjo" publicationDate="Wed Apr 06 00:00:00 GMT 2000" /> <content id="66228-135840" displayText="banjo" publicationDate="Wed Mar 07 00:00:00 GMT 2001" /> <content id="66228-135889" displayText="banjo" publicationDate="Wed Feb 08 00:00:00 GMT 1998" /> <content id="66228-135890" displayText="banjo" publicationDate="Wed Jan 09 00:00:00 GMT 2000" /> <content id="66228-135618" displayText="lotus" publicationDate="Wed Mar 02 00:00:00 GMT 2000" /> <content id="66228-135713" displayText="nother Test" publicationDate="Wed Dec 13 00:00:00 GMT 2000" /> </x> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:month="data:,month" > <xsl:output method="xml" indent="yes"/> <month:x m="Jan" pos="01" /> <month:x m="Feb" pos="02" /> <month:x m="Mar" pos="03" /> <month:x m="Apr" pos="04" /> <month:x m="May" pos="05" /> <month:x m="Jun" pos="06" /> <month:x m="Jul" pos="07" /> <month:x m="Aug" pos="08" /> <month:x m="Sep" pos="09" /> <month:x m="Oct" pos="10" /> <month:x m="Nov" pos="11" /> <month:x m="Dec" pos="12" /> <xsl:template match="x"> <xsl:for-each select="content"> <xsl:sort select="concat(substring(@publicationDate,25,4), document('')//month:x [@m=substring(current()/@publicationDate,5,3)]/@pos, substring(@publicationDate,9,2))"/> <xsl:if test="position() < 5"> [<xsl:value-of select="concat(substring(@publicationDate,25,4), document('')//month:x [@m=substring(current()/@publicationDate,5,3)]/@pos, substring(@publicationDate,9,2))"/>] <xsl:copy-of select="."/> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet> $ xt date.xml date.xsl <?xml version="1.0" encoding="utf-8"?> [19980208] <content id="66228-135889" displayText="banjo" publicationDate="Wed Feb 08 00:00:00 GMT 1998"/> [19990101] <content id="66228-135831" displayText="banjo" publicationDate="Wed Jan 01 00:00:00 GMT 1999"/> [19990505] <content id="66228-135835" displayText="banjo" publicationDate="Wed May 05 00:00:00 GMT 1999"/> [20000109] <content id="66228-135890" displayText="banjo" publicationDate="Wed Jan 09 00:00:00 GMT 2000"/> | |
7. | Compare Dates |
Try <xsl:if test="number(translate(date1, '-', '')) > number(translate(date2, '-', ''))"> | |
8. | Incorporating the current date time |
one trick i've used a couple of times for this is to use batch files to perform the transform, and to use command line parameters to create an xml file containing the current date. for example, through dos you'd have a start.txt file: <?xml version="1.0" encoding="UTF-8"?> <datetime> <time> and a middle.txt file: </time> <date> and a finish.txt file: </date> </datetime> you'd then have a dos batch file (say, datetime.bat) looking something like this: @echo off type start.txt time /t type middle.txt date /t type finish.txt after putting all of these files in the same folder, you'd call this file as follows: call datetime.bat > datetime.xml what you end up with is a file called datetime.xml that looks like this: <?xml version="1.0" encoding="UTF-8"?> <datetime> <time>10:53 </time> <date>Tue 10/12/2002 </date> </datetime> using the document() function you can then import this file in your xsl, and do whatever you want with the content. of course, this is only useful if you're using batch files, as you'd still have to call the batch file before doing the transform, and if you're doing that then you may as well just pass in a parameter. i've found it useful, though, because i can make batch files that bit more generic using this method, and i can also transform the content of the datetime.xml file very easily. i've only tested this on windows 2000, but i expect that it'd work on any dos version. p.s. if you need to transform this into an xs:datetime format, this might help: <!-- create a timestamp variable from the timestamp.xml file of the form yyyy-mm-ddThh:mm:ss note that the timestamp.xml file was created at the command line using batch files and the 'type' command applied to text files, so the spacing is a little suspect. to counteract this, i've used 'normalize-space' to strip leading and trailing spaces from the file's values before i use them --> <xsl:variable name="timestamp"> <xsl:variable name="date"> <xsl:value-of select="substring-after(normalize-space( document('datetime.xml')/datetime/date), ' ')"/> </xsl:variable> <!-- the batch file produces the date in the format: day dd/mm/yyyy we need it in the form yyyy-mm-dd, so we separate out the components using substrings, and then recombine them in the right order --> <xsl:variable name="day"> <xsl:value-of select="substring-before($date, '/')"/> </xsl:variable> <xsl:variable name="month_and_year"> <xsl:value-of select="substring-after($date, '/')"/> </xsl:variable> <xsl:variable name="month"> <xsl:value-of select="substring-before($month_and_year, '/')"/> </xsl:variable> <xsl:variable name="year"> <xsl:value-of select="substring-after($month_and_year, '/')"/> </xsl:variable> <xsl:value-of select="concat($year, '-', $month, '-', $day)"/> <!-- we need a 'T' before the time itself --> <xsl:text>T</xsl:text> <!-- select the time from the document --> <xsl:value-of select="normalize-space(document('datetime.xml')/datetime/time)"/> <!-- add seconds at end to complete the timestamp format we now have the xs:dateTime format as required: yyyy-mm-ddThh:mm:ss --> <xsl:text>:00</xsl:text> </xsl:variable> | |
9. | Date conversions |
Substring function <W3C>. concat(substring(., 5, 2), ' ', substring('JanFebMarAprMayJunJulAugSepOctNovDec', substring(., 7, 2) * 3 - 2, 3), ' ', substring(., 1, 4)) will give you "12 Jul 2004", but for complete month names concat(substring(., 5, 2), ' ', document('')/*/x:months/month[position() = substring(current(), 7, 2)], ' ', substring(., 1, 4)) with a top level element <x:months> <month>January</month> <month>February</month> <month>March</month> ... </x:months> |