[xquery-talk] Functions for printing path to a node

Michael Kay mhk at mhk.me.uk
Wed Dec 8 09:55:58 PST 2004


> 
> Following are two xquery functions for printing the paths from root to
> nodes returned as answer to xqueries. The argument to getPath is the
> answer from an xquery which has been converted into an xml document
> using hte document node constructor 'document { }'.
> 
> 
> define function getPath($e as document) as xs:string
> {
>         for $n in $e
>                 return fn:string-join(fn:fullpath($n),"")
> 
> }

What do you expect the argument to this function to be? A document node? In
that case, you should declare the argument as "$e as document-node()". But
in that case, $e will be a singleton, and when you apply fn:fullpath() to
it, it won't do anything very useful, because fn:fullpath seems designed to
process nodes deep within a document.

Some other points:
1. user-defined functions must be in a namespace
2. fn:full-path returns a single string, and there is no point calling
fn:string-join on a single string
3. your fullpath function is not in the fn: namespace.

> 
> define function fullpath($n as node) as xs:string
>  {
>         if ($n/..) then concat('<',name($n), '>',
> fullpath($n/..),"</",name($n),'>')
>         else fn:data($n)
>  }

The argument type should be node() rather than node.

I don't know why you're trying to construct serialized XML as text, rather
than using the serializer that comes with the system. This means you have to
be worried about all sorts of detail like escaping special characters and
encoding that the system should take care of. 

I don't know why you're calling some system functions (concat, name) without
a prefix, and other system functions (string-join, data) with one.

I don't know why you're outputting the typed value of the node if it has no
parent. Mmost commonly a parentless node is a document node, and the typed
value of a document node is the concatenation of all the text in the
document. This doesn't seem useful to your purpose.
> 
> However, when I execute the getPath function, it says :

I'm fairly amazed that you got as far as executing this. 
> 
> Exception in thread "main" galapi.GalapiException: Failure("Type
> Error: Type declaration failed.  Type of value:
> <xq:result/>
>  does not match type:
> xsd:string.

I've no idea what this means, since there's nothing called xq:result in your
query.
> 
> I even tried :
> 
> define function getPath($e as document) as document
> {
>         document {
>         for $n in $e
>                 return fn:myPath($n)
>         }
> 
> }
> 
> define function myPath($n as node) as element
>  {
>  if ($n/..) then element fn:name($node){myPath($n/..)}
>  else fn:data($n)
>  };
> 
> But I end up with a parse error.

The syntax is element {fn:name($node)}{myPath($n/..)}

(I don't actually know much about Galax. It may not be implementing the most
up-to-date version of XQuery).

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



More information about the talk mailing list