Inheritance: System.Xml.Xsl.Xslt.StylesheetLevel
Exemplo n.º 1
0
        private Stylesheet LoadStylesheet(XmlReader reader, bool include)
        {
            string baseUri = reader.BaseURI;
            Debug.Assert(!_documentUriInUse.Contains(baseUri), "Circular references must be checked while processing xsl:include and xsl:import");
            _documentUriInUse.Add(baseUri, null);
            _compiler.AddModule(baseUri);

            Stylesheet prevStylesheet = _curStylesheet;
            XsltInput prevInput = _input;
            Stylesheet thisStylesheet = include ? _curStylesheet : _compiler.CreateStylesheet();

            _input = new XsltInput(reader, _compiler, _atoms);
            _curStylesheet = thisStylesheet;

            try
            {
                LoadDocument();
                if (!include)
                {
                    _compiler.MergeWithStylesheet(_curStylesheet);

                    List<Uri> importHrefs = _curStylesheet.ImportHrefs;
                    _curStylesheet.Imports = new Stylesheet[importHrefs.Count];
                    // Imports should be compiled in the reverse order. Template lookup logic relies on that.
                    for (int i = importHrefs.Count; 0 <= --i;)
                    {
                        _curStylesheet.Imports[i] = LoadStylesheet(importHrefs[i], /*include:*/false);
                    }
                }
            }
            catch (XslLoadException)
            {
                throw;
            }
            catch (Exception e)
            {
                if (!XmlException.IsCatchableException(e))
                {
                    throw;
                }
                // Note that XmlResolver or XmlReader may throw XmlException with SourceUri == null.
                // In that case we report current line information from XsltInput.
                XmlException ex = e as XmlException;
                ISourceLineInfo lineInfo = (ex != null && ex.SourceUri != null ?
                    new SourceLineInfo(ex.SourceUri, ex.LineNumber, ex.LinePosition, ex.LineNumber, ex.LinePosition) :
                    _input.BuildReaderLineInfo()
                );
                throw new XslLoadException(e, lineInfo);
            }
            finally
            {
                _documentUriInUse.Remove(baseUri);
                _input = prevInput;
                _curStylesheet = prevStylesheet;
            }
            return thisStylesheet;
        }
        private QilNode InvokeApplyFunction(Stylesheet 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

            // Special treatment for current/position/last
            XslFlags flags;
            if (! compiler.ModeFlags.TryGetValue(mode, out flags)) {
                flags = 0;
            }
            if (IsDebug) {
                flags = XslFlags.FullFocus;
            }

            flags |= XslFlags.Current; // Due to recursive nature of Apply(Templates/Imports) we will need current node any way
            Debug.Assert(actualArgs[0].Name == nameCurrent, "Caller should always pass $current as a first argument to apply-* calls.");

            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.
            Dictionary<QilName, List<QilFunction>> funcTable = (
                sheet == null ? compiler.ApplyTemplatesFunctions : sheet.ApplyImportsFunctions
            );

            List<QilFunction> functionsForMode;
            if (!funcTable.TryGetValue(mode, out functionsForMode)) {
                functionsForMode = funcTable[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.False(), T.NodeNotRtfS);
                string attMode = (mode.LocalName.Length == 0) ? string.Empty : " mode=\"" + mode.QualifiedName + '"';
                applyFunction.DebugName = (sheet == null ? "<xsl:apply-templates" : "<xsl:apply-imports") + attMode + '>';
                functionsForMode.Add(applyFunction);
                this.functions.Add(applyFunction);

                // 3. Function body
                QilIterator current = (QilIterator)formalArgs[0];

                // 3.1 Built-in templates
                QilTernary builtinTemplates = f.BaseFactory.Conditional(f.IsType(current, elementOrDocumentType),
                    // This will be fixed up later
                    f.BaseFactory.Nop(f.BaseFactory.Unknown(T.NodeNotRtfS)),
                    f.Conditional(f.IsType(current, textOrAttributeType),
                        f.TextCtor(f.XPathNodeValue(current)),
                        f.Sequence()
                    )
                );

                // 3.2 Stylesheet templates
                matcherBuilder.CollectPatterns(sheet ?? compiler.PrincipalStylesheet, mode, /*applyImports:*/sheet != null);
                applyFunction.Definition = matcherBuilder.BuildMatcher(current, actualArgs, /*otherwise:*/builtinTemplates);

                // 3.3 Fix up the loop in built-in templates
                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));
                    if ((flags & XslFlags.Last) != 0) {
                        // Mark that we need last argument
                        curLoop.GetLast();
                    }

                    /* 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.
                        const bool Xslt10Rules = true;
                        if (Xslt10Rules) {
                            List<XslNode> newActualArgs = new List<XslNode>(3);
                            int argNum = 0;
                            if ((flags & XslFlags.Current ) != 0) { newActualArgs.Add(actualArgs[argNum ++]); }
                            if ((flags & XslFlags.Position) != 0) { newActualArgs.Add(actualArgs[argNum ++]); }
                            if ((flags & XslFlags.Last    ) != 0) { newActualArgs.Add(actualArgs[argNum ++]); }
                            actualArgs = newActualArgs;
                        }

                        // Fix values of current, position, and last
                        {
                            int argNum = 0;
                            if ((flags & XslFlags.Current ) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetCurrentNode    (); }
                            if ((flags & XslFlags.Position) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetCurrentPosition(); }
                            if ((flags & XslFlags.Last    ) != 0) { ((VarPar)actualArgs[argNum ++]).Value = GetLastPosition   (); }
                        }
                    }
                    loopOnContent = curLoop.ConstructLoop(InvokeApplyFunction(/*sheet:*/null, mode, actualArgs));
                    curLoop = curLoopSaved;
                }

                Debug.Assert(builtinTemplates.Center.NodeType == QilNodeType.Nop);
                ((QilUnary)builtinTemplates.Center).Child = loopOnContent;
            }
            return f.Invoke(applyFunction, invokeArgs);
        }
Exemplo n.º 3
0
        // ------------- CompileAndSortMatchPatterns() -------------

        private void CompileAndSortMatches(Stylesheet sheet)
        {
            Debug.Assert(sheet.TemplateMatches.Count == 0);

            foreach (Template template in sheet.Templates)
            {
                if (template.Match != null)
                {
                    EnterScope(template);
                    QilNode result = CompileMatchPattern(template.Match);
                    if (result.NodeType == QilNodeType.Sequence)
                    {
                        QilList filters = (QilList)result;
                        for (int idx = 0; idx < filters.Count; idx++)
                        {
                            sheet.AddTemplateMatch(template, (QilLoop)filters[idx]);
                        }
                    }
                    else
                    {
                        sheet.AddTemplateMatch(template, (QilLoop)result);
                    }
                    ExitScope();
                }
            }

            sheet.SortTemplateMatches();

            foreach (Stylesheet import in sheet.Imports)
            {
                CompileAndSortMatches(import);
            }
        }
        private QilNode GenerateApply(Stylesheet sheet, XslNode node) {
            Debug.Assert(
                node.NodeType == XslNodeType.ApplyTemplates ||
                node.NodeType == XslNodeType.ApplyImports
            );

            if (compiler.Settings.CheckOnly) {
                return f.Sequence();
            }
            AddImplicitArgs(node);
            return InvokeApplyFunction(sheet, /*mode:*/node.Name, node.Content);
        }
Exemplo n.º 5
0
        private Stylesheet LoadStylesheet(XmlReader reader, bool include) {
            string baseUri = reader.BaseURI;
            Debug.Assert(!documentUriInUse.Contains(baseUri), "Circular references must be checked while processing xsl:include and xsl:import");
            documentUriInUse.Add(baseUri, null);

            Stylesheet  prevStylesheet  = curStylesheet;
            XsltInput   prevInput       = input;
            Stylesheet  thisStylesheet  = include ? curStylesheet : compiler.CreateStylesheet();

            input         = new XsltInput(reader, compiler);
            curStylesheet = thisStylesheet;

            try {
                LoadDocument();
                if (!include) {
                    compiler.MergeWithStylesheet(curStylesheet);

                    List<Uri> importHrefs = curStylesheet.ImportHrefs;
                    curStylesheet.Imports = new Stylesheet[importHrefs.Count];
                    // We can't reverce imports order. Template lookup relies on it after compilation
                    // Imports should be compiled in the reverse order
                    for (int i = importHrefs.Count - 1; 0 <= i; i--) {
                        curStylesheet.Imports[i] = LoadStylesheet(importHrefs[i], /*include:*/false);
                    }
                }
            }
            catch (XslLoadException) {
                throw;
            }
            catch (Exception e) {
                if (!XmlException.IsCatchableException(e)) {
                    throw;
                }
                XmlException ex = e as XmlException;
                if (ex != null) {
                    SourceLineInfo lineInfo = new SourceLineInfo(input.Uri, ex.LineNumber, ex.LinePosition, ex.LineNumber, ex.LinePosition);
                    throw new XslLoadException(ex, lineInfo);
                }
                input.FixLastLineInfo();
                throw new XslLoadException(e, input.BuildLineInfo());
            }
            finally {
                documentUriInUse.Remove(baseUri);
                input         = prevInput;
                curStylesheet = prevStylesheet;
            }
            return thisStylesheet;
        }
Exemplo n.º 6
0
 public static XslNode ApplyImports(QilName mode, Stylesheet sheet, XslVersion xslVer)
 {
     return(new XslNode(XslNodeType.ApplyImports, mode, sheet, xslVer));
 }
Exemplo n.º 7
0
 public RootLevel(Stylesheet principal)
 {
     base.Imports = new Stylesheet[] { principal };
 }
Exemplo n.º 8
0
 public void MergeWithStylesheet(Stylesheet sheet)
 {
     MergeWhitespaceRules(sheet);
     MergeAttributeSets(sheet);
     MergeGlobalVarPars(sheet);
 }