Converting Java values to XDM values
This section explains how the value returned by a Java extension function is converted to an
XPath value. The same rules are used in converting a Java object supplied as a parameter to a
stylesheet or query in cases where the API defines no particular rules (for example, these rules
apply to the second argument of the
javax.xml.transform.Transformer.setParameter() method, and to the result of the
javax.xml.xpath.XPathVariableResolver.resolveVariable() method; but not to methods
javax.xml.xquery.XQDataSource.createItemFromObject() where the specification defines
specific conversion rules.)
The Java value is converted to an XPath value as follows.
In the case of a method returning void, then:
- If the option
?void=thiswas present in the namespace URI of the function name, and the method is an instance-level (non-static) method, then the return value is the value of the first argument, that is, the Java object to which the method was applied, wrapped as an external Java object. (This option can help to make execution of extensions with side-effects more predictable, by explicit chaining of such methods in the XPath code.)
- Otherwise, the return value is an empty sequence.
- If the option
If the Java value is null, the XPath value is an empty sequence.
When calling a constructor, the resulting XPath value is of type "wrapped Java object". The only way of using this is by passing it to another external function, or by converting it to one of the standard XPath data types as described above.
Note that calling
ArrayList.new()will result in a wrapped
ArrayListobject. By constrast, calling a method that returns an
ArrayListwill result in an XPath sequence whose items are constructed by converting the members of the returned
If the Java value is a boolean or Boolean, the XPath result is an xs:boolean.
If the Java value is a double or Double, the XPath result is an xs:double.
If the Java value is a float or Float, the XPath result is an xs:float.
If the Java value is an int, short, long, character, or byte, or one of their object wrapper equivalents, the XPath result is an xs:integer.
If the Java value is a String, the XPath result is an xs:string.
If the Java value is an instance of the Saxon class net.sf.saxon.om.NodeInfo (a node in a Saxon tree), the XPath value will be a sequence containing a single node.
If the Java value is an instance of
javax.xml.transform.Source(other than a
NodeInfo), a tree is built from the specified
Sourceobject, and the XPath result is the root node of this tree.
If the Java value is an instance of the Saxon class net.sf.saxon.om.Sequence, the value is used unchanged.
If the Java value is an instance of the Saxon class net.sf.saxon.s9api.XdmValue, (including its subclasses such as net.sf.saxon.s9api.XdmAtomicValue and net.sf.saxon.s9api.XdmNode) the returned value is used unchanged.
If the returned value is is an instance of the Saxon class net.sf.saxon.om.SequenceIterator (an iterator over a sequence), the XPath value will be the sequence represented by this iterator. It is essential that this iterator properly implements the method
getAnother()which returns a new iterator over the same sequence of nodes or values, positioned at the start of the sequence.
If the returned value is an instance of the Java class
java.util.Collection, or if it is an array, the XPath value will be the sequence represented by the contents of this
Collectionor array. The members of the collection or array will each be converted to an XPath value, as if each member was supplied from a separate function call. An error is reported if the result contains a list or array nested within another list or array. The contents of the list or array are copied immediately on return from the function, so the original
Listor array object itself may be safely re-used.
There is an exception to this rule for the Java class
byte. For historic reasons, and also because a byte array is often used to represent a binary value in the form of a sequence of octets, a
bytearray is converted to a sequence of
xs:unsignedByteinstances in the range 0..255.
If the returned value is a DOM Node, and it is recognized as a wrapper around a Saxon node, then the node is unwrapped and the underlying Saxon node is returned. If the returned value is some other kind of DOM Node, then a Saxon wrapper is added. (This is an imperfect solution, since it can lead to problems with node identity and document order.)
If the returned value is a DOM
NodeList, the list of nodes is returned as a Saxon node-set. Each node is handled in the same way as a Node that is returned directly as the result.
If the result is any other Java object (including null), it is returned as a "wrapped Java object". It is also possible to force the result to be returned as a wrapped Java object by making the function call in the initializer of a variable with an appropriate type declaration. The required type for a wrapped object of Java class
java.util.Mapis written using the QName
jt:java.util.Map, where the namespace prefix
jtrepresents the namespace