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.
The result type of the method is converted to an XPath value as follows.
If the method returns void, the XPath value is an empty sequence.
If the method returns null, the XPath value is an empty sequence.
If the method is a constructor, the 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.
If the returned value is a Java boolean or Boolean, the XPath result is a boolean.
If the returned value is a Java double or Double, the XPath result is a double.
If the returned value is a Java float or Float, the XPath result is a float.
If the returned value is a Java int, short, long, character, or byte, or one of their object wrapper equivalents, the XPath result is an integer.
If the returned value is a Java String, the XPath result is a string.
If the returned 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 returned value is an instance of javax.xml.transform.Source
(other than a NodeInfo
),
a tree is built from the specified Source
object, and the root node of this tree is returned as
the result of the function.
If the returned value is an instance of the Saxon class net.sf.saxon.value.Value
,
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.List
, or if it is an array,
the XPath value will be the
sequence represented by the contents of this List
or array. The members of the list 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 List
or array object itself may be safely re-used.
If the returned value is a DOM NodeList
, the list of nodes is returned as a Saxon node-set. However,
all the nodes must be instances of class net.sf.saxon.om.NodeInfo
, that is, they must use Saxon's tree
implementation, not some third-party DOM. But any implementation of NodeList
can be used. The nodes
can come from the original source tree, or from a newly-constructed tree, so long as it is constructed
using Saxon.
If the returned value is a DOM Node that is not an instance of class net.sf.saxon.om.NodeInfo
, it is
rejected: the result must use Saxon's DOM implementation, not some third-party DOM.
If the result is any other Java object (including null), it is returned as a "wrapped Java object".
Note that Saxon's two principal tree structures both conform to the DOM Core Level 2 interface. However, they are read-only:
any attempt to modify the tree causes an exception. Saxon's trees can only be built using the Saxon
subclasses of the net.sf.saxon.tree.Builder
class, and they cannot be modified in situ.
(The simplest way for a Java application to build a Saxon tree is by
using the net.sf.saxon.xpath.XPathEvaluator
class.)
In XSLT, the system function function-available(String name)
returns true if there appears
to be a method available with the right name. The function also has an optional second argument to test whether
there is a method with the appropriate
number of arguments. However, it is not possible to test whether the arguments are of appropriate types.
If the function name is "new" it
returns true so long as the class is not an abstract class or interface, and so long as it has at least
one constructor.
There are a number of extension functions supplied with the Saxon product: for details, see
extensions.html. The source code of these methods, which
in most cases is extremely simple, can be used as an example for writing
other user extension functions. It is found in class net.sf.saxon.functions.Extensions
.