Skip to content

TEDEFO-5150: Preserve predicates and always return a valid path when adding an axis - #59

Merged
rousso merged 2 commits into
developfrom
TEDEFO-5150-preserve-predicates-when-adding-an-axis
Aug 29, 2026
Merged

TEDEFO-5150: Preserve predicates and always return a valid path when adding an axis#59
rousso merged 2 commits into
developfrom
TEDEFO-5150-preserve-predicates-when-adding-an-axis

Conversation

@rousso

@rousso rousso commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Fixes TEDEFO-5150. Best merged squashed: the second commit replaces the design of the first rather than building on it.

XPathProcessor.addAxis discarded the predicates of the path it rewrote, and threw a bare NoSuchElementException on a path made only of parent steps. Looking into it turned up further cases where it returned XPath that does not compile.

What changed

Predicates are kept, by composing the result from XPathStep.toString() rather than from the step text alone. This is the same fault as TEDEFO-5148, in a second function of the same class.

The function now returns a valid path for every valid path given, and no longer throws:

input before after
b[x]/c preceding::b/c preceding::b[x]/c
..[x]/b preceding::b preceding::node()[x]/b
.. NoSuchElementException preceding::node()
. preceding::. preceding::node()
./b preceding::./b preceding::b
@x preceding::@x preceding::node()/@x
child::b/c preceding::child::b/c preceding::b/c
doc('x')/b preceding::doc('x')/b preceding::node()/doc('x')/b
/a/b preceding::a/b preceding::a/b

Leading steps that only move about are dropped, as before, since an axis searches the document from the context node regardless of them; one carrying a predicate stays, because the predicate describes what we are looking for. Where the axis lands on a step that cannot be looked for elsewhere, that step keeps its place behind a step walking the axis.

An absolute path behaves exactly as it did. Its anchor cannot be kept, because an axis cannot be followed by a separator, so the path is read from the context as before.

How a step is read

Deciding what may follow an axis is read from the parse tree rather than guessed from the step text, which is what the first attempt did and what broke on doc('x'), id('x') and (a | b). The listener asks the parser directly — KW_ATTRIBUTE(), KW_NAMESPACE(), KW_SELF(), KW_PARENT(), and kindtest().anykindtest() for node() — so a step is read the same way however it is spelled: . and self::node() agree, as do .. and parent::node(), and b and child::b.

What is recorded is only what addAxis needs, not a model of XPath: whether the step can be looked for along another axis, only moves about, or has to stay where it is. That classification and the node test behind it are private to XPathStep, and the original spelling of every step is preserved.

No public API changes. XPathStep keeps its constructor, its runtime type, its equality and its ordering; a step read from a path and one built from its text remain equal, with agreeing hashCode and compareTo. The only entry japicmp attributes to the class is the toString() that came from TEDEFO-5148.

Scope

addAxis serves the axis that can be written on an EFX-1 field reference and nothing more; it is not a general way of rewriting XPath, and its javadoc now says so. EFX-2 has no axis syntax and ScriptGenerator.composeFieldReferenceWithAxis is already marked for removal, which is why the implementation is kept proportional to that one caller.

Impact

No SDK content is affected. The only use of an axis in the SDK is preceding::BT-687-LotResult in the view templates of notice types 32, 33 and 35, whose context already contains the predicated step, so the path reaching the function carries no predicate.

Verification

Every output above was compiled with Saxon; a sweep of 30 inputs reports no valid input producing invalid output, and every abbreviated step was checked against its spelled-out form. The full test suite passes here, japicmp reports binary compatibility, and all 1377 tests in the EFX toolkit pass against this build.

@rousso
rousso merged commit c13257d into develop Aug 29, 2026
5 checks passed
@rousso
rousso deleted the TEDEFO-5150-preserve-predicates-when-adding-an-axis branch August 29, 2026 12:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant