RE: RE: [xsl] XSLT 2.0/XPath 2.0 Date arithmetic

Subject: RE: RE: [xsl] XSLT 2.0/XPath 2.0 Date arithmetic
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 18 May 2006 15:21:55 +0100
To give stronger type checking, I defined a type representing your yyyymmdd
values, created a declaration of that type, and used the type in the two
conversion functions. If your code isn't schema-aware, then you can
represent the yyyymmdd values simply as xs:string, which means you change
the two function signatures to use xs:string, and you no longer need the
schema, or the xsl:import-schema, to define the new type.

So it's perfectly possible to use the two conversion functions, and to do
the conversion using regular expressions, using a non-schema-aware
processor: the only thing you don't get is the free error checking.

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: cknell@xxxxxxxxxx [mailto:cknell@xxxxxxxxxx] 
> Sent: 18 May 2006 15:12
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: RE: RE: [xsl] XSLT 2.0/XPath 2.0 Date arithmetic
> 
> Permit me to parse your answer and ask additional questions. 
> I've already managed to munge the string into the proper 
> format with concat() and substring(), but this
> 
> <xsl:function name="f:to-iso-date" as="xs:date">
>   <xsl:param name="in" as="my:yyyymmdd-date"/>
>   <xsl:sequence select="xs:date(replace($in, 
> '(\d{4})(\d{2})(\d{2})', '$1-$2-$3'))"/> </xsl:function>
> 
> is appealing because of it's perl-ishness (yes, of course 
> perl incorporated existing concepts from UNIX shell utilities 
> like sed and awk, but I first encountered them when learning 
> perl), and because the function casts the return value to an xs:date.
> 
> In order to use this approach you suggest that I incorporate 
> an xsl:import-schema declaration in my stylesheet and use it 
> with either of the functions.
> 
> On the other hand, I'm using the non-schema-aware version of Saxon.
> 
> In reviewing the section on xsl:import-schema in "XSLT 2.0 
> Programmer's Reference" on page 324 I note that, "This 
> declaration is only available in a schema-aware processor." 
> So, how then would substituting " ... xs:string in place of 
> my:yyyymmdd-date ..." solve that issue?
> 
> I am puzzled by what appears to me as an inconsistency in the 
> answer which I must attribute to my weak grasp of the 
> subject. If I cannot use the suggested approach because my 
> processor is not schema-aware, is there some other native 
> XSLT 2.0 approach, or am I forced to use some extension function?
> 
> 
> --
> Charles Knell
> cknell@xxxxxxxxxx - email
> 
> 
> 
> -----Original Message-----
> From:     Michael Kay <mike@xxxxxxxxxxxx>
> Sent:     Thu, 18 May 2006 08:27:54 +0100
> To:       <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
> Subject:  RE: [xsl] XSLT 2.0/XPath 2.0 Date arithmetic
> 
> > 
> > Given a parameter, let's call it "today" in the form of this 
> > string "20060517", how do I create a variable, let's call it 
> > "tMinus1" such that it represents a day earlier than 
> > "20060517", that would be "20060516". So long as "$today" 
> > isn't the first day of a month, a simple subtraction and 
> > followed by a type cast that I don't grasp would do the trick.
> > 
> > What I'm looking for is guidance on date arithmetic.
> 
> You'd be much better off working with the xs:date type, which uses the
> format 2006-05-17.
> 
> So, two functions to convert between your non-standard dates 
> and standard
> xs:date objects:
> 
> <xsl:import-schema>
>   <xs:schema target-namespace="http://my-date";>
>     <xs:simpleType name="yyyymmdd-date">
>       <xs:restriction base="xs:string">
>         <xs:pattern value="[0-9]{4}[0-1][0-9][0-3][0-9]"/>
>       </
>     </
>   </
> </
>       
> 
> <xsl:function name="f:to-iso-date" as="xs:date">
>   <xsl:param name="in" as="my:yyyymmdd-date"/>
>   <xsl:sequence select="xs:date(replace($in, '(\d{4})(\d{2})(\d{2})',
> '$1-$2-$3'))"/>
> </xsl:function>
> 
> <xsl:function name="f:to-yyyymmdd-date" as="my:yyyymmdd-date">
>   <xsl:param name="in" as="xs:date"/>
>   <xsl:sequence 
> select="my:yyyymmdd-date(translate(string($in, '-', ''))"/>
> </xsl:function>
> 
> then:
>    select="f:to-yyyymmdd-date(f:to-iso-date($input-date) -
> xs:dayTimeDuration('PT1D'))"
> 
> If you're not schema-aware, then use xs:string in place of 
> my:yyyymmdd-date
> - all you lose is type-checking.
> 
> Michael Kay
> http://www.saxonica.com/

Current Thread