Skip to content

Commit 1971175

Browse files
Separating the absolute match into two cases:
- `<xsl:template match="/">`, resolves as absolute match, axis self (should start by #document node); - Other cases (for instance, `<xsl:template match="/root">`), that should start by the first child of #document node.
1 parent a797cfe commit 1971175

File tree

1 file changed

+41
-5
lines changed

1 file changed

+41
-5
lines changed

src/xpath/match-resolver.ts

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ export class MatchResolver {
4040
}
4141

4242
if (expression.absolute) {
43+
// If expression is absolute and the axis of first step is self,
44+
// the match starts by the #document node (for instance, `<xsl:template match="/">`).
45+
// Otherwise (axis === 'child'), the match stasts on the first
46+
// child of #document node.
47+
const firstStep = expression.steps[0];
48+
if (firstStep.axis === 'self') {
49+
return this.absoluteXsltMatchByDocumentNode(expression, context);
50+
}
51+
4352
return this.absoluteXsltMatch(expression, context);
4453
}
4554

@@ -58,14 +67,13 @@ export class MatchResolver {
5867
}
5968

6069
/**
61-
* Finds all the nodes through absolute xPath search.
62-
* Returns only nodes that match either the context position node,
63-
* or an ancestor.
70+
* Finds all the nodes through absolute XPath search, starting on
71+
* the #document parent node.
6472
* @param expression The Expression.
6573
* @param context The Expression Context.
6674
* @returns The list of found nodes.
6775
*/
68-
private absoluteXsltMatch(expression: LocationExpr, context: ExprContext): XNode[] {
76+
private absoluteXsltMatchByDocumentNode(expression: LocationExpr, context: ExprContext): XNode[] {
6977
const clonedContext = context.clone([context.root], undefined, 0, undefined);
7078
const matchedNodes = expression.evaluate(clonedContext).nodeSetValue();
7179
const finalList = [];
@@ -75,9 +83,37 @@ export class MatchResolver {
7583
finalList.push(element);
7684
continue;
7785
}
86+
}
87+
88+
return finalList;
89+
}
90+
91+
/**
92+
* Finds all the nodes through absolute xPath search, starting with the
93+
* first child of the #document node.
94+
* @param expression The Expression.
95+
* @param context The Expression Context.
96+
* @returns The list of found nodes.
97+
*/
98+
private absoluteXsltMatch(expression: LocationExpr, context: ExprContext): XNode[] {
99+
const firstChildOfRoot = context.root.childNodes[0];
100+
const clonedContext = context.clone([firstChildOfRoot], undefined, 0, undefined);
101+
const matchedNodes = expression.evaluate(clonedContext).nodeSetValue();
102+
const finalList = [];
103+
104+
// If the context is pointing to #document node, it's child node is
105+
// considered.
106+
let nodeList: XNode[];
107+
if (context.nodeList.length === 1 && context.nodeList[0].nodeName === '#document') {
108+
nodeList = [context.nodeList[0].childNodes[0]];
109+
} else {
110+
nodeList = context.nodeList;
111+
}
78112

79-
if (element.getAncestorById(context.nodeList[context.position].id) !== undefined) {
113+
for (let element of matchedNodes) {
114+
if (element.id === nodeList[context.position].id) {
80115
finalList.push(element);
116+
continue;
81117
}
82118
}
83119

0 commit comments

Comments
 (0)