[xquery-talk] Union types

James A. Robinson jim.robinson at stanford.edu
Fri Jan 12 13:54:02 PST 2007


> However, if I have unions I can not determine what my 'mask' should be.
> As an approach I tried using "instance of" operator to check literal
> values but that does not return the result that I was looking for.  As
> an example I used 1999-12-31T12:00:00 to check if it is xs:dateTime and
> it gave me false.  I am a beginner when it comes to X-Query.  

It may be that I don't understand what you want, my apologies if that is
the case.  My reading of your note made me think you want a way to cast
an unknown xs:string into the proper type for an attribute of element
value which is declared to be a union of the specific types you mention?

So, for example, a function to find the 'best match' for the variables
you listed might be something like:

declare namespace f="uri.local-functions";

declare function f:toMyType($u as xs:string)
{
    if ($u castable as xs:dateTime)
    then xs:dateTime($u)
    else if ($u castable as xs:time)
    then xs:time($u)
    else if ($u castable as xs:date)
    then xs:date($u)
    else if ($u castable as xs:gYearMonth)
    then xs:gYearMonth($u)
    else if ($u castable as xs:gYear)
    then xs:gYear($u)
    else if ($u castable as xs:decimal)
    then xs:decimal($u)
    else if ($u castable as xs:anyURI)
    then xs:anyURI($u)
    else
      error(xs:QName("f:toMyType"), concat("unable to case ", $u))
};

And so calling

for $t in (
  trace(f:toMyType("2006-01-12T00:00:00Z"), "2006-01-12T00:00Z"),
  trace(f:toMyType("10:00:00Z"), "10:00:00Z"),
  trace(f:toMyType("2007-01-12"), "2007-01-12"),
  trace(f:toMyType("2007-01"), "2007-01"),
  trace(f:toMyType("2007"), "2007"),
  trace(f:toMyType("10.1"), "10.1"),
  trace(f:toMyType("http://foo.bar.com/"), "http://foo.bar.com/"))
return
  $t

Yeilds the following trace data:

2006-01-12T00:00Z [1]: xs:dateTime: 2006-01-12T00:00:00Z
10:00:00Z [1]: xs:time: 10:00:00Z
2007-01-12 [1]: xs:date: 2007-01-12
2007-01 [1]: xs:gYearMonth: 2007-01
2007 [1]: xs:gYear: 2007
10.1 [1]: xs:decimal: 10.1
http://foo.bar.com/ [1]: xs:anyURI: http://foo.bar.com/

That kind of return would, I think, allow you to call things
like

  attribute {'pbs:myProp'} {
    f:toMyType($u)
  }

in order to, in this case, get an attribute named pbs:myProp,
assuming it's been declared in a schema as being the simpleType
union you declared.

Is that what you needed?  If not, my apologies for wasting
bandwidth.  I'm new at XQuery so I may be missing something
in the description you gave. :(


Jim
P.S. I'm not sure, is there any danger/overlap between having a
union which can take both xs:GYear and xs:decimal? I think the
technique I outline can give ambigious results if your input
is something like '1000' -- it could be cast to xs:gYear, in
which case you'd need to be performing an additional check
on matches to 'castable as xs:gYear'.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
James A. Robinson                       jim.robinson at stanford.edu
Stanford University HighWire Press      http://highwire.stanford.edu/
+1 650 7237294 (Work)                   +1 650 7259335 (Fax)


More information about the talk mailing list