Converting Java values to XDM values
This section describes the general rules applied by Saxon for converting Java values to XDM values. These rules are used in a number of places, for example:
Converting the result of a Java extension function to a value that can be used in XPath expressions.
Conversion of the value supplied in a call to
Transformer.setParameter()in the JAXP Transformation API.Conversion of the value returned by a call to
VariableResolver.resolver()in the JAXP XPath API.Conversion of the first argument supplied in a call to
XPathExpression.evaluate()in the JAXP XPath API (this argument supplies the context item. The JAXP documentation is written for XPath 1.0 where the context item is always a node, but Saxon extends it with support for later XPath versions, where this restriction is removed).Conversion of the result of an external function implemented using the
FunctionResolvermechanism in the JAXP XPath API.
In some of these contexts there are additional rules applied; for example the handling of a Java null
varies. These variations are noted in the specific API documentation.
These conventions do not apply to APIs that define their own rules, for example the XQJ API for invoking XQuery. To achieve greater type safety, Saxon's s9api API generally requires explicit conversion of values rather than relying on implicit conversion rules.
Conversion from Saxon-specific classes
If the Java object is an instance of a Saxon-defined class, and the Saxon-defined class is an implementation of an XDM value, then the value will be accepted with no conversion.
This includes the following cases:
-
The Saxon class net.sf.saxon.om.Sequence and its subclasses, including:
- NodeInfo (for nodes)
- AtomicValue and its subclasses such as IntegerValue, BooleanValue, DateTimeValue etc.
- Function representing a function item
- MapItem representing a map
- ArrayItem representing an array
- ZeroOrOne,
ZeroOrMore,
OneOrMore and
One
representing sequences with defined cardinality (these are parameterized by the item type, for example
OneOrMore<IntegerValue>for a sequence of integers)
-
The Saxon class net.sf.saxon.s9api.XdmValue and its subclasses, including:
- net.sf.saxon.s9api.XdmAtomicValue for atomic values
- net.sf.saxon.s9api.XdmNode for nodes
- XdmFunctionItem for function items
- XdmMap for maps
- XdmArray for arrays
- XdmEmptySequence for an empty sequence.
-
The Saxon class net.sf.saxon.om.SequenceIterator (an iterator over a sequence): in this case the XPath value will be the sequence represented by this iterator. The iterator should be positioned at its start position, and it will normally be consumed, unless for some reason the result can be obtained without consuming the iterator.
Converting atomic values
This section describes Java classes that are recognized as equivalents to XDM atomic types.
-
If the Java value is a
booleanorBoolean, the XPath result is anxs:boolean. -
If the Java value is a
doubleorDouble, the XPath result is anxs:double. -
If the Java value is a
floatorFloat, the XPath result is anxs:float. -
If the Java value is an
int,short,long,byte, or one of their object wrapper equivalents, the XPath result is an instance of the corresponding subtype ofxs:integer: for example a Java short produces an instance ofxs:short. -
If the Java value is a
String, the XPath result is anxs:string. Unless otherwise specified, Saxon does not actually check that the characters in the Java string are legal XML characters. -
If the Java value is a
charorCharacter, it is converted to a single-characterxs:string. Again, Saxon does not normally check that the value is a legal XML character. -
Instances of the Java classes
java.net.URIandjava.net.URLare converted to instances ofxs:anyURIby calling thetoString()method on the supplied object. -
An instance of
javax.xml.namespace.QNameis converted to an instance ofxs:QNamehaving the same prefix, namespace URI, and local part. -
An instance of
java.lang.BigIntegeris converted to an instance ofxs:integerwith the same numeric value. -
An instance of
java.lang.BigDecimalis converted to an instance ofxs:decimalwith the same numeric value. Java classes representing dates and times are converted as follows:
java.util.Dateis converted toxs:dateTimeby callinggetTime()to convert to milliseconds since 1 Jan 1970. The resultingxs:dateTimevalue will be UTC.java.time.Instantis converted toxs:dateTimewith nanosecond precision. The resultingxs:dateTimevalue will be UTC.java.time.OffsetDateTimeis converted to anxs:dateTimewith the same timezone offset, with nanosecond precision.java.time.ZonedDateTimeis first converted to anjava.time.OffsetDateTimeby callingtoOffsetDateTime(), and this is then converted as described above.java.time.LocalDateTimeis converted to anxs:dateTimevalue with the same components (year, month, day, etc); the resultingxs:dateTimevalue will have no timezone component.java.time.LocalDateis converted to anxs:dateTimevalue with the same components (year, month, day); the resultingxs:datevalue will have no timezone component.
Converting nodes
This section describes Java classes that are recognized as representing XDM Nodes.
-
If the supplied 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 supplied Java value is an instance of
javax.xml.transform.Source(other than aNodeInfo), a tree is built from the specifiedSourceobject, and the XPath result is the root node of this tree. -
If the supplied Java value is an instance of net.sf.saxon.om.TreeInfo then the root node of this tree is used.
-
If the supplied 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 supplied 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 third party object models such as JDOM2, DOM4J, XOM, or AXIOM have been registered with the Saxon Configuration, then the Java classes representing nodes in these various object models are recognized. The supplied node will be wrapped as an XDM node, which does not involve copying, so relationships among nodes in the same tree are preserved.
Converting sequences
Java collections are converted to XDM sequences:
-
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 thisCollectionor array. The members of the collection or array will each be converted to an XPath value, by applying these rules recursively. 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 originalListor array object itself may be safely re-used. -
There is an exception to this rule where the return type is defined as
byte[]. Partly for historical reasons, and partly to reflect the fact that abyte[]array is often used to represent binary data in the form of a sequence of octets, abyte[]value is converted to a sequence ofxs:unsignedByteitems, each in the range 0..255.
Note that Java maps (instances of java.util.Map are not converted
to XDM maps. Such a conversion can be achieved using the static factory method XdmMap.makeMap().
Wrapped Java objects
If the supplied value is any other Java object, it is returned as a "wrapped
Java object". The required type for a wrapped object of Java class java.util.Map
is written using the QName jt:java.util.Map, where the namespace prefix
jt represents the namespace http://saxon.sf.net/java-type.