protected virtual ParsedTemplate PrepareTemplate(TemplateData templateData, Stack<IFileProvider> providers = null) { // set up temp file container TempFileCollection tempFiles = new TempFileCollection(templateData.TemporaryFilesPath, templateData.KeepTemporaryFiles); if (!Directory.Exists(tempFiles.TempDir)) Directory.CreateDirectory(tempFiles.TempDir); if (providers == null) providers = new Stack<IFileProvider>(); // clone orig doc XDocument workingDoc; // this is required to preserve the line information using (var xmlReader = this._templateDefinition.CreateReader()) workingDoc = XDocument.Load(xmlReader, LoadOptions.SetLineInfo); // template inheritence XAttribute templateInheritsAttr = workingDoc.Root.Attribute("inherits"); if (templateInheritsAttr != null) { int depth = providers.Count + 1; Template inheritedTemplate = new Template(this._container); inheritedTemplate.Load(this._templateResolver, templateInheritsAttr.Value); ParsedTemplate parsedTemplate = inheritedTemplate.PrepareTemplate(templateData, providers); providers.Push(inheritedTemplate.GetScopedFileProvider()); // a little hacky but it should work with the Reverse()/AddFirst() foreach (XElement elem in parsedTemplate.Source.Root.Elements().Reverse()) { workingDoc.Root.AddFirst(new XElement(elem)); } // create and register temp file (this can be overriden later if there are meta-template directives // in the template this._templateSourcePath = this.SaveTempFile(tempFiles, workingDoc, "inherited." + depth); } // add our file provider to the top of the stack providers.Push(this.GetScopedFileProvider()); // start by loading any parameters as they are needed for meta-template evaluation CustomXsltContext customContext = CreateCustomXsltContext(templateData.IgnoredVersionComponent); XElement[] paramNodes = workingDoc.Root.Elements("parameter").ToArray(); var globalParams = paramNodes.Select(paramNode => new ExpressionXPathVariable(this.GetAttributeValue(paramNode, "name"), this.GetAttributeValueOrDefault(paramNode, "select"))) .ToArray(); customContext.PushVariableScope(workingDoc, globalParams); var arguments = templateData.Arguments .Select(argument => new ConstantXPathVariable(argument.Key, argument.Value)) .ToArray(); customContext.PushVariableScope(workingDoc, arguments); // we're going to need this later XmlFileProviderResolver fileResolver = new XmlFileProviderResolver(providers, this._basePath); // expand any meta-template directives workingDoc = ApplyMetaTransforms(workingDoc, customContext, providers, tempFiles); // there was neither inheretance, nor any meta-template directives if (this._templateSourcePath == null) { // save current template to disk this._templateSourcePath = this.SaveTempFile(tempFiles, workingDoc); } // loading template List<Stylesheet> stylesheets = new List<Stylesheet>(); List<Resource> resources = new List<Resource>(); List<Index> indices = new List<Index>(); foreach (XElement elem in workingDoc.Root.Elements()) { // we alread proessed the parameters if (elem.Name.LocalName == "parameter") continue; if (elem.Name.LocalName == "apply-stylesheet") { stylesheets.Add(this.ParseStylesheet(providers, stylesheets, elem)); } else if (elem.Name.LocalName == "index") { indices.Add(this.ParseIndexDefinition(elem)); } else if (elem.Name.LocalName == "include-resource") { resources.Add(ParseResouceDefinition(providers, elem)); } else { throw new Exception("Unknown element: " + elem.Name.LocalName); } } return new ParsedTemplate { Parameters = globalParams, Source = workingDoc, Resources = resources.ToArray(), Stylesheets = stylesheets.ToArray(), Indices = indices.ToArray(), TemporaryFiles = tempFiles, }; }
/// <summary> /// The load stylesheet. /// </summary> /// <param name="fileProvider"><see cref="IFileProvider"/> used to load the stylesheet.</param> /// <param name="name"> /// </param> /// <returns> /// </returns> private XslCompiledTransform LoadStylesheet(IFileProvider fileProvider, string name) { XslCompiledTransform ret = new XslCompiledTransform(true); using (Stream str = fileProvider.OpenFile(name, FileMode.Open)) { XmlReader reader = XmlReader.Create(str, new XmlReaderSettings { CloseInput = true, }); XsltSettings settings = new XsltSettings(false, true); XmlResolver resolver = new XmlFileProviderResolver(fileProvider); ret.Load(reader, settings, resolver); } return ret; }
/// <summary> /// The load stylesheet. /// </summary> /// <param name="resourceProvider"></param> /// <param name="name"> /// </param> /// <returns> /// </returns> private XslCompiledTransform LoadStylesheet(Stack<IFileProvider> resourceProvider, string name) { XslCompiledTransform ret = new XslCompiledTransform(true); foreach (var provider in resourceProvider) { if (provider.FileExists(name)) { using (Stream str = provider.OpenFile(name, FileMode.Open)) { XmlReader reader = XmlReader.Create(str, new XmlReaderSettings {CloseInput = true,}); XsltSettings settings = new XsltSettings(false, true); XmlResolver resolver = new XmlFileProviderResolver(resourceProvider); ret.Load(reader, settings, resolver); } break; } } return ret; }