public void CollectPatterns(StylesheetLevel sheet, QilName mode) { Clear(); foreach (Stylesheet import in sheet.Imports) { CollectPatternsInternal(import, mode); } }
private QilNode InvokeApplyFunction(StylesheetLevel sheet, QilName mode, IList<XslNode> actualArgs) { // Here we create function that has one argument for each with-param in apply-templates // We have actualArgs -- list of xsl:with-param(name, value) // From it we create: // invokeArgs -- values to use with QilInvoke // formalArgs -- list of iterators to use with QilFunction // actualArgs -- modify it to hold iterators (formalArgs) instead of values to ise in invoke generator inside function budy XslFlags flags; { if (!sheet.ModeFlags.TryGetValue(mode, out flags)) { flags = 0; } flags |= XslFlags.Current; // Due to recursive nature of Apply(Templates/Imports) we will need current node any way } actualArgs = AddRemoveImplicitArgs(actualArgs, flags); QilList invokeArgs = _f.ActualParameterList(); QilFunction applyFunction = null; // Look at the list of all functions that have been already built. If a suitable one is found, reuse it. List<QilFunction> functionsForMode; if (!sheet.ApplyFunctions.TryGetValue(mode, out functionsForMode)) { functionsForMode = sheet.ApplyFunctions[mode] = new List<QilFunction>(); } foreach (QilFunction func in functionsForMode) { if (FillupInvokeArgs(func.Arguments, actualArgs, /*ref*/invokeArgs)) { applyFunction = func; break; } } // If a suitable function has not been found, create it if (applyFunction == null) { invokeArgs.Clear(); // We wasn't able to find suitable function. Let's build new: // 1. Function arguments QilList formalArgs = _f.FormalParameterList(); for (int i = 0; i < actualArgs.Count; i++) { Debug.Assert(actualArgs[i].NodeType == XslNodeType.WithParam, "All Sorts was removed in CompileSorts()"); VarPar withParam = (VarPar)actualArgs[i]; // Add actual arg to 'invokeArgs' array. No need to clone it since it must be // a literal or a reference. invokeArgs.Add(withParam.Value); // Create correspondent formal arg QilParameter formalArg = _f.Parameter(i == 0 ? T.NodeNotRtf : withParam.Value.XmlType); formalArg.Name = CloneName(withParam.Name); formalArgs.Add(formalArg); // Change actual arg value to formalArg for reuse in calling built-in templates rules withParam.Value = formalArg; } // 2. Function header applyFunction = _f.Function(formalArgs, _f.Boolean((flags & XslFlags.SideEffects) != 0), T.NodeNotRtfS ); string attMode = (mode.LocalName.Length == 0) ? string.Empty : " mode=\"" + mode.QualifiedName + '"'; applyFunction.DebugName = (sheet is RootLevel ? "<xsl:apply-templates" : "<xsl:apply-imports") + attMode + '>'; functionsForMode.Add(applyFunction); _functions.Add(applyFunction); // 3. Function body Debug.Assert(actualArgs[0].Name == _nameCurrent, "Caller should always pass $current as a first argument to apply-* calls."); QilIterator current = (QilIterator)formalArgs[0]; // 3.1 Built-in templates: // 3.1.1 loop over content of current element QilLoop loopOnContent; { QilIterator iChild = _f.For(_f.Content(current)); QilNode filter = _f.Filter(iChild, _f.IsType(iChild, T.Content)); filter.XmlType = T.ContentS; // not attribute LoopFocus curLoopSaved = _curLoop; _curLoop.SetFocus(_f.For(filter)); /* Prepare actual arguments */ // At XSLT 1.0, if a built-in template rule is invoked with parameters, the parameters are not // passed on to any templates invoked by the built-in rule. At XSLT 2.0, these parameters are // passed through the built-in template rule unchanged. // we can't just modify current/position/last of actualArgs in XSLT 2.0 as we tried before, // becuase flags for apply-import amy now be different then flags for apply-templates, so // we may need to add some space for additional position/last arguments QilNode body = InvokeApplyFunction(_compiler.Root, mode, /*actualArgs:*/null); if (IsDebug) { body = _f.Sequence(InvokeOnCurrentNodeChanged(), body); } loopOnContent = _curLoop.ConstructLoop(body); _curLoop = curLoopSaved; } // 3.1.2 switch on type of current node QilTernary builtinTemplates = _f.BaseFactory.Conditional(_f.IsType(current, _elementOrDocumentType), loopOnContent, _f.Conditional(_f.IsType(current, _textOrAttributeType), _f.TextCtor(_f.XPathNodeValue(current)), _f.Sequence() ) ); // 3.2 Stylesheet templates _matcherBuilder.CollectPatterns(sheet, mode); applyFunction.Definition = _matcherBuilder.BuildMatcher(current, actualArgs, /*otherwise:*/builtinTemplates); } return _f.Invoke(applyFunction, invokeArgs); }
// ----------------- apply-templates, apply-imports ----------------------------- // private QilNode GenerateApply(StylesheetLevel sheet, XslNode node) { Debug.Assert( node.NodeType == XslNodeType.ApplyTemplates && sheet is RootLevel || node.NodeType == XslNodeType.ApplyImports && sheet is Stylesheet ); if (_compiler.Settings.CheckOnly) { return _f.Sequence(); } return InvokeApplyFunction(sheet, /*mode:*/node.Name, node.Content); }