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); }
// ------------- 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); }
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; }
public static XslNode ApplyImports(QilName mode, Stylesheet sheet, XslVersion xslVer) { return(new XslNode(XslNodeType.ApplyImports, mode, sheet, xslVer)); }
public RootLevel(Stylesheet principal) { base.Imports = new Stylesheet[] { principal }; }
public void MergeWithStylesheet(Stylesheet sheet) { MergeWhitespaceRules(sheet); MergeAttributeSets(sheet); MergeGlobalVarPars(sheet); }