0
votes

When I evaluate this XPath expression: //superhero[n0:name="Superman"]/n1:name on this xml:

<n0:rootElement xmlns:n0='http://example.com' xmlns:n1='http://example.com'>
    <superheroes>
        <superhero>
            <n0:name>Superman</n0:name>
            <n1:name>Clark</n1:name>
        </superhero>
        <superhero>
            <n0:name>Spiderman</n0:name>
            <n1:name>Peter</n1:name>
        </superhero>
    </superheroes>
</n0:rootElement>

using an XPath evaluator, I get the expected result.

But when I send it to an XQuery processor, I get an error message saying that Namespace prefix 'n0' has not been declared. Weird, huh?

It's always the prefix in the brackets (is it called a filter, maybe?) that gets the complaint.

I've used http://www.xpathtester.com to verify the difference between XPath and XQuery interpretations.

It works fine with https://codebeautify.org/Xpath-Tester which is XPath only.

If I replace n0: or n1: with *: it works in for XQuery processors, but not for XPath testers.

This is of course a toy example I've written up to clarify my issue. In production I'm calling an external service which I believe is driven by Saxon-HE. I know it accepts XQuery so I'm guessing it is in "XQuery-mode" for XPath expressions.

There isn't much I can do to the xml file since I receive it from another source. Is there a better XQuery expression I can use?

Is this a bug, or by design?

2

2 Answers

3
votes

Different XPath engines provide different ways of binding the namespace prefixes used in the expression. Some, I believe, pick up the namespace bindings from the source document. So it's not a non-conformance with the standard, it's the fact that the standard leaves it up to the particular processor how the original context is established.

The underlying problem is that you probably want your query to work regardless what namespace prefixes are used in the source document. Picking up the namespace bindings from the source document is handy for ad-hoc queries, but it means that a query that does the right thing with one document will fail with a different one.

1
votes

In XQuery you can declare any namespaces you want to use in your query:

declare namespace n0 = 'http://example.com';
declare namespace n1 = 'http://example.com';

//superhero[n0:name="Superman"]/n1:name

https://xqueryfiddle.liberty-development.net/bdxZ8S

See the spec at https://www.w3.org/TR/xquery-31/#id-namespace-declaration