@@ -330,29 +330,69 @@ public final class IndexOptimizeTest extends SandboxTest {
330330 }
331331
332332 /**
333- * Index access with namespaces.
333+ * Index access with namespaces (#1763) .
334334 */
335335 @ Test public void gh1763 () {
336336 final String doc = "<a xmlns:x=\" X\" ><b>B</b></a>" ;
337337 execute (new CreateDB (NAME , doc ));
338+
339+ // explicit text steps: rewritten for index access
338340 check ("/a[.//text() = 'B']" , doc , exists (ValueAccess .class ));
339341 check ("//a[.//text() = 'B']" , doc , exists (ValueAccess .class ));
340342 check ("/a/b[text() = 'B']/.." , doc , exists (ValueAccess .class ));
341343 check ("//b[text() = 'B']/.." , doc , exists (ValueAccess .class ));
342344 check ("//*[text() = 'B']/.." , doc , exists (ValueAccess .class ));
343345
344- // the following queries could be rewritten for index access
346+ // no default namespace is declared anywhere: no-namespace element tests are rewritten
347+ check ("/a[b = 'B']" , doc , exists (ValueAccess .class ));
348+ check ("//a[b = 'B']" , doc , exists (ValueAccess .class ));
349+ check ("/*[b = 'B']" , doc , exists (ValueAccess .class ));
350+ check ("//*[b = 'B']" , doc , exists (ValueAccess .class ));
351+
352+ // local-name wildcard tests are not rewritten (may match names in other namespaces)
345353 check ("/a[*:b = 'B']" , doc , empty (ValueAccess .class ));
346354 check ("//a[*:b = 'B']" , doc , empty (ValueAccess .class ));
347355 check ("/*:a[*:b = 'B']" , doc , empty (ValueAccess .class ));
348356 check ("//*:a[*:b = 'B']" , doc , empty (ValueAccess .class ));
349357 check ("/*[*:b = 'B']" , doc , empty (ValueAccess .class ));
350358 check ("//*[*:b = 'B']" , doc , empty (ValueAccess .class ));
351359
352- check ("/a[b = 'B']" , doc , empty (ValueAccess .class ));
353- check ("//a[b = 'B']" , doc , empty (ValueAccess .class ));
354- check ("/*[b = 'B']" , doc , empty (ValueAccess .class ));
355- check ("//*[b = 'B']" , doc , empty (ValueAccess .class ));
360+ // nonexistent no-namespace names: statically discarded
361+ check ("/a/nonexistent" , "" , empty ());
362+ check ("//nonexistent[. = 'B']" , "" , empty ());
363+
364+ // attribute values are rewritten for index access
365+ execute (new CreateDB (NAME , "<a xmlns:x=\" X\" ><b id=\" 7\" >B</b></a>" ));
366+ check ("//b[@id = '7']" , "<b xmlns:x=\" X\" id=\" 7\" >B</b>" , exists (ValueAccess .class ));
367+ }
368+
369+ /**
370+ * Index access with namespaces: soundness with prefixed same-local names (#1763).
371+ */
372+ @ Test public void gh1763Mixed () {
373+ // no-namespace <b> (leaf) and prefixed <x:b> (non-leaf) share the local name 'b'
374+ execute (new CreateDB (NAME , "<a xmlns:x=\" X\" ><b>B</b><x:b><c>B</c></x:b></a>" ));
375+
376+ // full no-namespace test is rewritten and matches only the no-namespace element
377+ check ("count(/a[b = 'B'])" , "1" , exists (ValueAccess .class ));
378+ check ("count(//b[. = 'B'])" , "1" , exists (ValueAccess .class ));
379+ // local-name wildcard is evaluated sequentially and matches both elements
380+ check ("count(//*:b[. = 'B'])" , "2" , empty (ValueAccess .class ));
381+
382+ // 'B' only occurs below the prefixed element: no-namespace test must not match
383+ execute (new CreateDB (NAME , "<a xmlns:x=\" X\" ><b>b</b><x:b><c>B</c></x:b></a>" ));
384+ check ("count(/a[b = 'B'])" , "0" , exists (ValueAccess .class ));
385+ }
386+
387+ /**
388+ * Index access on databases with a default namespace (#1763).
389+ */
390+ @ Test public void gh1763DefaultNs () {
391+ // single default namespace: a no-namespace element test never matches and is discarded
392+ execute (new CreateDB (NAME , "<a xmlns=\" Y\" ><b>B</b></a>" ));
393+ check ("/a[b = 'B']" , "" , empty ());
394+ // query default namespace matches the database default namespace: correct result
395+ check ("declare default element namespace 'Y'; count(/a[b = 'B'])" , "1" );
356396 }
357397
358398 /** Index access for integer comparisons (issue #2069). */
0 commit comments