Esempio n. 1
0
 public void CollectPatterns(StylesheetLevel sheet, QilName mode)
 {
     Clear();
     foreach (Stylesheet import in sheet.Imports)
     {
         CollectPatternsInternal(import, mode);
     }
 }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        // ----------------- 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);
        }