3

I am writing an XQuery that needs to check what version of XQuery is being run (eXist, Saxon, etc.). Is there a standard function that will return the system properties of an XQuery such as version, vendor etc?

I know there are some system specific calls such as eXist's

system:get-version()

but I am trying to find a standard function that would run on all platforms.

For example in XSLT we have:

Version:
<xsl:value-of select="system-property('xsl:version')" />
<br />
Vendor:
<xsl:value-of select="system-property('xsl:vendor')" />
<br />
Vendor URL:
<xsl:value-of select="system-property('xsl:vendor-url')" />

Are their similar functions for XQuery?

grtjn
  • 20,254
  • 1
  • 24
  • 35
Dan McCreary
  • 411
  • 3
  • 13
  • There's nothing in the XQuery spec to support that, but there may be implementation-specific functions. What XQuery processor are you using? – wst Dec 30 '13 at 23:31
  • I am using both eXist and some Saxon HE. – Dan McCreary Dec 30 '13 at 23:34
  • xquery version "3.0"; let $properties := ('vendor', 'vendor-url', 'product-name', 'product-version', 'product-build') return {for $property in $properties return } returns – Dan McCreary Dec 30 '13 at 23:35

4 Answers4

2

You can use the XQuery 3.0 function function-lookup to check the existence of implementation-specific functions to check for the processors. All XQuery 3.0 supporting processors should be able to process this.

declare function local:exist() as xs:boolean {
  try {
    if (not(empty(function-lookup(xs:QName('system:get-version'), 0))))
    then true()
    else false()
  } catch * {
    false()
  }
};

(: works only on Saxon PE and EE, fails in HE since HE does not support XQuery 3.0. It would be nice if saxon had a version function. :)
declare function local:saxon() as xs:boolean {
  try {
    if (not(empty(function-lookup(xs:QName('saxon:parse'), 1))))
    then true()
    else false()
  } catch * {
    false()
  }
};

declare function local:marklogic() as xs:boolean {
  try {
    if (not(empty(function-lookup(xs:QName('xdmp:xquery-version'), 0))))
    then true()
    else false()
  } catch * {
    false()
  }
};

declare function local:basex() as xs:boolean {
  try {
    if (not(empty(function-lookup(xs:QName('prof:time'), 1))))
    then true()
    else false()
  } catch * {
    false()
  }
};

declare function local:get-processor() as xs:string {
  if (local:exist()) then "eXist"
  else if (local:saxon()) then "Saxon"
  else if (local:marklogic()) then "MarkLogic"
  else if (local:basex()) then "BaseX"
  else "Unknown"
};

local:get-processor()

Unfortunately, I was not able to make this more elegant using Higher-Order functions, as the implementation-specific functions were executed before the function is actually called. But I am sure this could also be written more elegant.

dirkk
  • 6,160
  • 5
  • 33
  • 51
  • Thanks for the sample code! This works perfectly everywhere we have XQuery 3.0. Unfortunately some of my projects are still on XQuery 1.0. Saxon HE does not support XQuery 3.0. :-( I think this is a good reason to migrate to XQuery 3.0! – Dan McCreary Dec 31 '13 at 16:47
  • I added the test for Saxon and put it in a GIST here: https://gist.github.com/dmccreary/8201987 – Dan McCreary Dec 31 '13 at 20:39
  • @DanMcCreary I editet my answer, so it is also saved and accessible from SO. – dirkk Jan 02 '14 at 09:16
2

Tricky in the case of Saxon-HE because Saxon-HE only supports XQuery 1.0 and provides no vendor extensions. It does however provide a mechanism for creating user-defined extension functions, and you could use that to implement an interrogative function of your own design.

Or you could define an external global variable and initialize that from the application that runs the query, assuming the application is under your control.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164
0

There doesn't appear to be a function in Saxon, but eXist has system:get-version():

http://exist-db.org/exist/apps/fundocs/view.html?uri=http://exist-db.org/xquery/system&location=java:org.exist.xquery.functions.system.SystemModule

Also, although you're not using it, other SO readers may be interested to know that MarkLogic has xdmp:xquery-version():

http://docs.marklogic.com/7.0/xdmp:xquery-version

wst
  • 11,681
  • 1
  • 24
  • 39
  • I can not find any function in Saxon HE that will indicate what version is running. I did figure out that you can look for a saxon specific function like this: declare function local:saxon() as xs:boolean { try { if (not(empty(function-lookup(xs:QName('saxon:parse'), 1)))) then true() else false() } catch * { false() } }; – Dan McCreary Dec 31 '13 at 20:20
0

There is an inherent problem here that different versions of xquery simply wont complile if run by an incompatible version. You cant generally do a
#if version > 1
new stuff #else old stuff #endif

Some vendor extensions supply version information and you can use an "eval()" type epression to get around this, but in pure XQuery there is no point I can think of that can used to do conditional logic that is compilation time valid on the current version yet use some feature on a different version.

DALDEI
  • 3,722
  • 13
  • 9