Given the XML:
<root name="value">
<level1>
<level2>Text</level2>
</level1>
</root>
I want the XPath /root/@name
to return value
, and the XPath /root/level1
to return the XML serialisation of the <level1>
node:
<level1>
<level2>Text</level2>
</level1>
I'm using the a9api interface from Saxon 9.6 in Java.
I've found that I can call XdmValue.toString()
to get the XML serialisation of the result of the evaluation of the XPath, which gets me the desired result for selecting an element, but returns name="value"
when selecting an attribute. And I can call XdmItem.getStringValue()
to get the string value, which gets me the right value for the attribute, but returns the textual content of the element.
Michael Kay has previously said "Saxon's s9api interface ... returns XdmValue objects whose type you can interrogate". I can see that I could perform an instanceof
check to determine whether it is an XdmAtomicValue
, XdmExternalObject
, XdmFunctionItem
, or XdmNode
, but elements and attributes are both instances of XdmNode
. How do I distinguish between the two?
(I can't modify the XPaths, as they're provided by the user.)
I discovered the answer just as I finished writing the question, so I'll share it for others.
After casting the XdmItem
to an XdmNode
, you can call XdmNode.getNodeKind()
, which returns a value from the XdmNodeKind
enumeration specifying which type of node it is:
XdmValue matchList = xPathSelector.evaluate();
XdmItem firstItem = matchList.itemAt(0);
if (firstItem instanceof XdmNode) {
XdmNode xdmNode = (XdmNode) firstItem;
XdmNodeKind nodeKind = xdmNode.getNodeKind();
if (nodeKind == XdmNodeKind.ELEMENT) {
return xdmNode.toString();
}
}
return firstItem.getStringValue();