data() returns an empty value for an element only because the type of the node() argument sounds like an error to me. Which XQuery processor are you using?
It sounds like you need to calm the static type check you can do using the treat as expression. I do not think that a dynamic test using instance of will be sufficient.
Try the following:
let $parameter := someNamespace:functionX() treat as element() return local:myFunction($parameter)
Quote from the 4th edition of Michael Kay magnum opus: "The treat as statement essentially tells the system that you know what type of runtime will be, and you want some kind of check to be delayed until the runtime because you are" sure that your code is correct. "(p. 679)
UPDATE: I think this is actually not true, since treat as is just a statement. It does not change the annotation type node() , which also means an incorrect statement and does not help you. Hmm ... I really need cast as , but this only works for atomic types. Iβm probably at a dead end. Maybe you should change the XQuery engines. :-) I will report if I think about something else. Also, I'm curious to see if the Dimitre solution works for you.
UPDATE # 2: I came back here before. Can I back off again? ;-) Now my theory is that treat as will work based on the fact that node() interpreted as a union of various specific annotations of type node, and not as a runtime type annotation itself (see Note "in the " Element Types " section of XQuery formal semantics .) At run time, the annotation of the type will be element() . Use treat as to ensure that this is true. Now I wait with bated breath: will this work for you?
EXPLANATORY APP: Assuming this works, thatβs why. node() - type of union. Actual elements at run time are never annotated with node() . "An element type is an atomic type, an element type, an attribute type, a document type node, a text type node, a comment type node, or a type of processing instruction." 1 Note that node() not in this list. Thus, your XQuery engine does not complain that the element is of type node() ; rather, he complains that he does not know what type will be ( node() means that it may turn out to be attribute() , element() , text() , comment() , processing-instruction() or document-node() ) . Why should he know? Because you are saying elsewhere that it is an element (in your function signature). This is not enough to narrow it down to one of six possibilities. Checking a static type means that at compile time you must ensure that the types will match (element with element, in this case). treat as used to narrow a static type from a generic type ( node() ) to a more specific type ( element() ). It does not change the dynamic type. cast as , on the other hand, is used to convert an element from one type to another, changing both static and dynamic types (for example, xs: string to xs: boolean). Does it make sense that cast as can only be used with atomic values ββ(and not with nodes), because for this you need to convert the attribute to an element (etc.)? And there is no such thing as converting a node() element to an element() , because there is no such thing as a node() element. node() exists only as a static union type. The moral of the story? Avoid XQuery processors that use static type checking. (Sorry for the bold conclusion, I feel that I deserve the right. :-))
NEW ANSWER BASED ON UPDATE INFORMATION : it looks like static type checking is a red herring (big thick). I believe that you are not actually dealing with an element, but a document node , which is the invisible root of a node that contains a top-level element (document element) in the XPath data model view of a well-formed XML document.
Thus, the tree is modeled as follows:
[document-node] | <docElement> | <subelement>
and not so:
<docElement> | <subelement>
I assumed that you were passing the <docElement> node. But if I'm right, you actually passed the node document (its parent). Since the node document is invisible, its serialization (what you copied and pasted) is indistinguishable from the node element, and this difference was lost when you pasted what is now interpreted as the bare element constructor in your XQuery. (To create a node document in XQuery, you must wrap the constructor of the document{ ... } element document{ ... } .)
The instance of test fails because the node is not an element, but a node document. (This is not node() as such because there is no such thing, see explanation above.)
Also, this explains why data() returns empty when you tried to get the child <subelement> node document (after weakening the type of the function argument to node() ). The first view of the tree above shows that <subelement> not a child of the node document; so it returns an empty sequence.
Now for the solution. Before passing the (document node) parameter, get its child (document element) by adding /* (or /element() , which is equivalent) as follows:
let $parameter := someNamespace:functionX()/* return local:myFunction($parameter)
Alternatively, let your function take a node document and update the argument you pass to data ():
declare function local:myFunction($arg1 as document-node()) as element() { let $value := data($arg1
Finally, it looks like a description of an eXist request: the get-data () function is fully consistent with this explanation. It says: "If this is not a binary document, we try to parse it as XML and return the node () document." (highlighted by me)
Thanks for the adventure. This turned out to be a common XPath gotcha (document node awareness), but I learned a few things from our tour of static type checking.