@@ -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