In Java 17 I'm using XPath to extract data from XML by joining all the <bar>s under <foo>. I'm using Saxon 12, but I'm doing it through the JAXP API. I create an XPathExpression and then invoke it like this:
(String)xpathExpression.evaluate(context, XPathConstants.STRING)
I was hoping that this would give me a null if there was no match. But apparently this is not the case. Let's start with this XPath expression (simplified from what I'm using)
/foo/string-join(bar, codepoints-to-string(10))
I wanted this to join all the /foo/bar strings together, separated by newlines, which it does if there is a /foo. But if there is no /foo, then instead of returning null it seems to return an empty string.
My first question would be how to detect that this XPath expression did not match /foo/. I had assumed that XPathExpression.evaluate() would return null if there was no match. (Reading the API now I guess that was just an assumption I made.)
But let's say that I'm OK with returning an empty string, and I can detect if the returned string is empty and consider that a non-match (even though semantically that is not ideal). The problem is that I want the value to end with a newline as well, so my expression looks like this:
concat(/foo/string-join(bar, codepoints-to-string(10)), codepoints-to-string(10))
This is worse—now if there is no /foo, it returns a string with a single newline \n, because it appends the newline to the thing-that-did-not-match which it considered the empty string.
I would prefer to find a way for this expression to return null in JAXP if /foo does not exist. But if that can't easily be done, I'd prefer to still at least get an empty string if /foo does not exist, i.e. concat() only appends text if the inner match is successful. I have a feeling I'll have to construct some elaborate work around, but maybe an XPath expert knows a trick or two.