private static string EvalValue(CustomXsltContext customContext, XNode contextNode, string valueOrExpression) { // TODO this is quick and dirty if (valueOrExpression.StartsWith("{") && valueOrExpression.EndsWith("}")) { string expression = valueOrExpression.Substring(1, valueOrExpression.Length - 2); object value = contextNode.XPathEvaluate(expression, customContext); return ResultToString(value); } return valueOrExpression; }
protected virtual XDocument ApplyMetaTransforms(XDocument workingDoc, CustomXsltContext customContext, IFileProvider provider, TempFileCollection tempFiles) { // check for meta-template directives and expand int metaCount = 0; XElement metaNode = workingDoc.Root.Elements("meta-template").FirstOrDefault(); while (metaNode != null) { if (EvalCondition(customContext, metaNode, this.GetAttributeValueOrDefault(metaNode, "condition"))) { XslCompiledTransform metaTransform = this.LoadStylesheet(provider, this.GetAttributeValue(metaNode, "stylesheet")); XsltArgumentList xsltArgList = new XsltArgumentList(); // TODO this is a quick fix/hack xsltArgList.AddExtensionObject(Namespaces.Template, new TemplateXsltExtensions(null, null)); var metaParamNodes = metaNode.Elements("with-param"); foreach (XElement paramNode in metaParamNodes) { string pName = this.GetAttributeValue(paramNode, "name"); string pExpr = this.GetAttributeValue(paramNode, "select"); try { xsltArgList.AddParam(pName, string.Empty, workingDoc.XPathEvaluate(pExpr, customContext)); } catch (XPathException ex) { throw new TemplateException(this._templateSourcePath, paramNode.Attribute("select"), string.Format( "Unable to process XPath expression: '{0}'", pExpr), ex); } } // this isn't very nice, but I can't figure out another way to get LineInfo included in the transformed document XDocument outputDoc; using (MemoryStream tempStream = new MemoryStream()) using (XmlWriter outputWriter = XmlWriter.Create(tempStream, new XmlWriterSettings { Indent = true })) { metaTransform.Transform(workingDoc.CreateNavigator(), xsltArgList, outputWriter, new XmlFileProviderResolver(provider)); outputWriter.Close(); // rewind stream tempStream.Seek(0, SeekOrigin.Begin); outputDoc = XDocument.Load(tempStream, LoadOptions.SetLineInfo); // create and register temp file // this will override the value set in PrepareTemplate in case of template inhertence // TODO this is a bit hacky, maybe add Template.Name {get;} instead of this._basePath (which could be anything) string filename = this._basePath + ".meta." + (++metaCount).ToString(CultureInfo.InvariantCulture); this._templateSourcePath = this.SaveTempFile(tempFiles, outputDoc, filename); } TraceSources.TemplateSource.TraceVerbose("Template after transformation by {0}", this.GetAttributeValue(metaNode, "stylesheet")); TraceSources.TemplateSource.TraceData(TraceEventType.Verbose, 1, outputDoc.CreateNavigator()); workingDoc = outputDoc; } else { // didn't process, so remove it metaNode.Remove(); } // select next template metaNode = workingDoc.Root.Elements("meta-template").FirstOrDefault(); } return workingDoc; }
private static bool EvalCondition(CustomXsltContext customContext, XNode contextNode, string condition) { bool shouldApply; if (string.IsNullOrWhiteSpace(condition)) shouldApply = true; else { object value = contextNode.XPathEvaluate(condition, customContext); shouldApply = ResultToBool(value); } return shouldApply; }
private static CustomXsltContext CreateCustomXsltContext(VersionComponent? ignoredVersionComponent) { CustomXsltContext xpathContext = new CustomXsltContext(); xpathContext.RegisterFunction(string.Empty, "get-id", new XsltContextAssetIdGetter()); xpathContext.RegisterFunction(string.Empty, "get-version", new XsltContextAssetVersionGetter()); xpathContext.RegisterFunction(string.Empty, "substring-before-last", new XsltContextSubstringBeforeLastFunction()); xpathContext.RegisterFunction(string.Empty, "substring-after-last", new XsltContextSubstringAfterLastFunction()); xpathContext.RegisterFunction(string.Empty, "iif", new XsltContextTernaryOperator()); xpathContext.RegisterFunction(string.Empty, "get-significant-version", new XsltContextAssetVersionGetter(ignoredVersionComponent)); xpathContext.RegisterFunction(string.Empty, "coalesce", new XsltContextCoalesceFunction()); xpathContext.RegisterFunction(string.Empty, "join", new XsltContextJoinFunction()); return xpathContext; }