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
FunctionResolver
mechanism 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
boolean
orBoolean
, the XPath result is anxs:boolean
. -
If the Java value is a
double
orDouble
, the XPath result is anxs:double
. -
If the Java value is a
float
orFloat
, 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
char
orCharacter
, 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.URI
andjava.net.URL
are converted to instances ofxs:anyURI
by calling thetoString()
method on the supplied object. -
An instance of
javax.xml.namespace.QName
is converted to an instance ofxs:QName
having the same prefix, namespace URI, and local part. -
An instance of
java.lang.BigInteger
is converted to an instance ofxs:integer
with the same numeric value. -
An instance of
java.lang.BigDecimal
is converted to an instance ofxs:decimal
with the same numeric value. Java classes representing dates and times are converted as follows:
java.util.Date
is converted toxs:dateTime
by callinggetTime()
to convert to milliseconds since 1 Jan 1970. The resultingxs:dateTime
value will be UTC.java.time.Instant
is converted toxs:dateTime
with nanosecond precision. The resultingxs:dateTime
value will be UTC.java.time.OffsetDateTime
is converted to anxs:dateTime
with the same timezone offset, with nanosecond precision.java.time.ZonedDateTime
is first converted to anjava.time.OffsetDateTime
by callingtoOffsetDateTime()
, and this is then converted as described above.java.time.LocalDateTime
is converted to anxs:dateTime
value with the same components (year, month, day, etc); the resultingxs:dateTime
value will have no timezone component.java.time.LocalDate
is converted to anxs:dateTime
value with the same components (year, month, day); the resultingxs:date
value 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 specifiedSource
object, 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 thisCollection
or 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 originalList
or 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:unsignedByte
items, 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
.