diff --git a/src/main/java/eu/europa/ted/eforms/xpath/XPathProcessor.java b/src/main/java/eu/europa/ted/eforms/xpath/XPathProcessor.java index 1667f2e..e6e92be 100644 --- a/src/main/java/eu/europa/ted/eforms/xpath/XPathProcessor.java +++ b/src/main/java/eu/europa/ted/eforms/xpath/XPathProcessor.java @@ -72,10 +72,10 @@ private static String getContextualizedXpath(Queue contextQueue, // At this point there are no more matching nodes in the two queues. // We look at the first of the remaining steps in both queues and look if - // the context is more restrictive than the path. In this case we want to use a dot step - // with the predicate of the path. + // the context is the same as or less restrictive than the path. In this case + // we want to use a dot step with the predicate of the path. if (!contextQueue.isEmpty() && !pathQueue.isEmpty() - && pathQueue.peek().isSimilarTo(contextQueue.peek())) { + && pathQueue.peek().isSameAsOrNarrowerThan(contextQueue.peek())) { contextQueue.poll(); // consume the same step from the contextQueue if (contextQueue.isEmpty()) { // Since there are no more steps in the contextQueue, the relative xpath should diff --git a/src/main/java/eu/europa/ted/eforms/xpath/XPathStep.java b/src/main/java/eu/europa/ted/eforms/xpath/XPathStep.java index c016f74..8d1061b 100644 --- a/src/main/java/eu/europa/ted/eforms/xpath/XPathStep.java +++ b/src/main/java/eu/europa/ted/eforms/xpath/XPathStep.java @@ -116,7 +116,7 @@ public boolean isTheSameAs(final XPathStep other) { return pathPredicates.equals(contextPredicates); } - public boolean isSimilarTo(final XPathStep other) { + public boolean isSameAsOrNarrowerThan(final XPathStep other) { // First check the step texts are different. if (!Objects.equals(other.stepText, this.stepText)) { @@ -125,13 +125,15 @@ public boolean isSimilarTo(final XPathStep other) { // If one of the two steps has more predicates that the other, if (this.predicates.size() != other.predicates.size()) { - // then the steps are similar if either of them has no predicates - // or all the predicates of this step are also found in the specific step. - return this.predicates.isEmpty() || other.predicates.isEmpty() - || other.predicates.containsAll(this.predicates); + // then this step is same as or narrower that the other, if either of them has + // no predicates or all the predicates of the other step are also found in this + // step. In this case this step has the same predicates as the other one, plus + // some more, which means it selects a subset of the nodes selected by the other + // step and therefore it is "narrower". + return other.predicates.isEmpty() || this.predicates.containsAll(other.predicates); } - assert !this.isTheSameAs(other) : "You should not be calling isSimilarTo() without first checking isTheSameAs()"; + assert !this.isTheSameAs(other) : "You should not be calling isSameAsOrNarrowerThan() without first checking isTheSameAs()"; return false; } diff --git a/src/test/java/eu/europa/ted/eforms/xpath/XPathProcessorTest.java b/src/test/java/eu/europa/ted/eforms/xpath/XPathProcessorTest.java index 456e241..0ea12c1 100644 --- a/src/test/java/eu/europa/ted/eforms/xpath/XPathProcessorTest.java +++ b/src/test/java/eu/europa/ted/eforms/xpath/XPathProcessorTest.java @@ -63,6 +63,11 @@ void testIdentical() { assertEquals(".", contextualize("/a/b/c", "/a/b/c")); } + @Test + void testIdentical_WithPredicates() { + assertEquals(".[d = e][f = g]", contextualize("/a/b/c[d = e]", "/a/b/c[d = e][f = g]")); + } + @Test void testContextEmpty() { assertEquals("/a/b/c", contextualize("", "/a/b/c")); @@ -176,7 +181,7 @@ void testPredicateDifferent() { @Test void testPredicateMoreInXpath() { - assertEquals("../../b[e][f]/c/d", contextualize("/a/b[e]/c", "/a/b[e][f]/c/d")); + assertEquals("..[e][f]/c/d", contextualize("/a/b[e]/c", "/a/b[e][f]/c/d")); } @Test diff --git a/src/test/java/eu/europa/ted/eforms/xpath/XPathStepTest.java b/src/test/java/eu/europa/ted/eforms/xpath/XPathStepTest.java index 60a9385..28f17d6 100644 --- a/src/test/java/eu/europa/ted/eforms/xpath/XPathStepTest.java +++ b/src/test/java/eu/europa/ted/eforms/xpath/XPathStepTest.java @@ -33,7 +33,7 @@ void testComparison_DifferentElement() { assertFalse(a.isTheSameAs(b)); - assertFalse(a.isSimilarTo(b)); + assertFalse(a.isSameAsOrNarrowerThan(b)); } @Test @@ -43,7 +43,7 @@ void testComparison_MorePredicates() { assertTrue(a.isTheSameAs(b)); - assertTrue(a.isSimilarTo(b)); + assertTrue(b.isSameAsOrNarrowerThan(a)); } @Test @@ -53,7 +53,7 @@ void testComparison_LessPredicates() { assertFalse(a.isTheSameAs(b)); - assertFalse(a.isSimilarTo(b)); + assertFalse(b.isSameAsOrNarrowerThan(a)); } @Test @@ -63,7 +63,7 @@ void testComparison_DifferentPredicate() { assertFalse(a.isTheSameAs(b)); - assertFalse(a.isSimilarTo(b)); + assertFalse(a.isSameAsOrNarrowerThan(b)); } @Test @@ -73,7 +73,7 @@ void testComparison_NoPredicates() { assertFalse(a.isTheSameAs(b)); - assertTrue(a.isSimilarTo(b)); + assertTrue(a.isSameAsOrNarrowerThan(b)); } @Test @@ -83,7 +83,7 @@ void testComparison_AddPredicates() { assertTrue(a.isTheSameAs(b)); - assertTrue(a.isSimilarTo(b)); + assertTrue(b.isSameAsOrNarrowerThan(a)); } private XPathStep buildStep(String elt, String... predicates) {