InsertFalsePrecision2.xsl
Jump to navigation
Jump to search
TEI datatypes permit times on the value= attribute of the various date & time elements to be expressed to any precision (year, month, day, hour, minute, second, or decimal fraction of a second). However, because the W3C XML Schema datatypes for times do not permit precision to the hour or minute, there exists software that does not handle these values. E.g., such software will reject "13:30" but accept "13:30:00". This stylesheet (as well as a less powerful version that works with XSLT 1 processors) converts times that are precise to only the minute or hour to times that are precise to the second.
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:tei="http://www.tei-c.org/ns/1.0"> <!-- add_false_time_precision_4v2.xslt This style-sheet reads in an XML file (presumably a TEI P5 one, but any other that has similar when= attributes of <date> and <time> elements would work) and writes out the same file with any right- truncated times padded with zeroes. I don't claim for a moment that the method I've used here is the best in any sense of the word "best", only that it is the one this novice XSLTer thought of. Known limitations: * The "00" should probably be a parameter, so users could use some other value (e.g., "30") if they wanted. * Obviously, the file cannot be converted back, as there would be no way for a stylesheet to know whether any particular ":00" was added by this stylesheet or actually represents a time precise to the minute or second. Written 2005-09-26 by Syd Bauman copyleft 2005 by Syd Bauman and the Text Encoding Initiative Consortium --> <!-- Generic copy-everything template --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- match <date> or <time>, whether namespace defaulted or explicit --> <xsl:template match="time[@when]|tei:time[@when]|date[@when]|tei:date[@when]"> <!-- strip any leading or trailing whitespace --> <xsl:variable name="when" select="normalize-space(@when)"/> <xsl:variable name="intermediateValue"> <!-- Replace times that have only 2 digits with the same --> <!-- two digits followed by ":00:00", whether or not there --> <!-- was a time designator ("T") or a time zone designator. --> <!-- Note, though, that even if the time designator and --> <!-- time zone designator or not present, the fact that we --> <!-- look for them prevents us from matching any set of --> <!-- two digits, e.g in "2005-09-28". --> <xsl:value-of select="replace($when,'^(.*T)?(\d\d)(Z|[-+]\d\d:\d\d)?$','$1$2:00:00$3')"/> </xsl:variable> <xsl:variable name="newValue"> <!-- Now, looking at the result of the above replace(), --> <!-- replace times that have only 5 characters (2 digits, --> <!-- a colon, and 2 digits) to the same characters fol- --> <!-- lowed by ":00", whether or not there was a time --> <!-- designator ("T") or a time zone designator. --> <xsl:value-of select="replace($intermediateValue,'^(.*T)?(\d\d:\d\d)(Z|[-+]\d\d:\d\d)?$','$1$2:00$3')"/> </xsl:variable> <xsl:element name="{name(.)}"> <!-- create new element, with all the original attributes ... --> <xsl:copy-of select="@*"/> <!-- ... but then copy over a new when= attribute, using --> <xsl:attribute name="when"> <!-- ... our new value for it ... --> <xsl:value-of select="$newValue"/> <!-- ... replacing the original when= --> </xsl:attribute> <!-- ... don't forget all text and element children --> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet>