public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
		{
			var resolver = new PathResolver(liveDefinition.Folder);
			var hostPage = DNNContext.Current.Page;

			var args = new XsltArgumentList();
			args.AddExtensionObject("urn:ddrmenu", new XsltFunctions());
			args.AddExtensionObject("urn:dnngarden", new XsltFunctions());
			args.AddParam("ControlID", "", DNNContext.Current.HostControl.ClientID);
			args.AddParam("Options", "", ConvertToJson(liveDefinition.ClientOptions));
			args.AddParam("DNNPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Dnn)));
			args.AddParam("ManifestPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Manifest)));
			args.AddParam("PortalPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Portal)));
			args.AddParam("SkinPath", "", hostPage.ResolveUrl(resolver.Resolve("/", PathResolver.RelativeTo.Skin)));
			liveDefinition.TemplateArguments.ForEach(a => args.AddParam(a.Name, "", a.Value));

			HttpContext.Current.Items["Resolver"] = resolver;

			using (var xmlStream = new MemoryStream())
			{
				Utilities.SerialiserFor(source.GetType()).Serialize(xmlStream, source);
				xmlStream.Seek(0, SeekOrigin.Begin);
				xsl.Transform(XmlReader.Create(xmlStream), args, htmlWriter);
			}
		}
        public bool LoadDefinition(TemplateDefinition baseDefinition)
        {
            var virtualPath = baseDefinition.TemplateVirtualPath;

            if (!virtualPath.EndsWith(".cshtml", StringComparison.InvariantCultureIgnoreCase) &&
                !virtualPath.EndsWith(".vbhtml", StringComparison.InvariantCultureIgnoreCase))
            {
                return false;
            }

            return true;
        }
		public bool LoadDefinition(TemplateDefinition baseDefinition)
		{
			try
			{
                var virtualPath = baseDefinition.TemplateVirtualPath;
                if (!virtualPath.EndsWith(".xsl", StringComparison.InvariantCultureIgnoreCase) &&
                    !virtualPath.EndsWith(".xslt", StringComparison.InvariantCultureIgnoreCase))
                {
                    return false;
                }

				xsl = Utilities.CachedXslt(baseDefinition.TemplatePath);
				return true;
			}
			catch (Exception)
			{
				return false;
			}
		}
        public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
        {
            if (!(string.IsNullOrEmpty(liveDefinition.TemplateVirtualPath)))
            {
                var resolver = new PathResolver(liveDefinition.Folder);
                dynamic model = new ExpandoObject();
                model.Source = source;
                model.ControlID = DNNContext.Current.HostControl.ClientID;
                model.Options = ConvertToJson(liveDefinition.ClientOptions);
                model.DNNPath = resolver.Resolve("/", PathResolver.RelativeTo.Dnn);
                model.ManifestPath = resolver.Resolve("/", PathResolver.RelativeTo.Manifest);
                model.PortalPath = resolver.Resolve("/", PathResolver.RelativeTo.Portal);
                model.SkinPath = resolver.Resolve("/", PathResolver.RelativeTo.Skin);
                var modelDictionary = model as IDictionary<string, object>;
                liveDefinition.TemplateArguments.ForEach(a => modelDictionary.Add(a.Name, a.Value));

                var razorEngine = new RazorEngine(liveDefinition.TemplateVirtualPath, null, null);
                var writer = new StringWriter();
                razorEngine.Render<dynamic>(writer, model);

                htmlWriter.Write(writer.ToString());
            }
        }
        internal static TemplateDefinition FromManifest(string manifestUrl)
        {
            var httpContext  = HttpContext.Current;
            var cache        = httpContext.Cache;
            var manifestPath = httpContext.Server.MapPath(manifestUrl);

            var baseDef = cache[manifestPath] as TemplateDefinition;

            if (baseDef == null)
            {
                baseDef = new TemplateDefinition {
                    Folder = Path.GetDirectoryName(manifestUrl)
                };

                var xml = new XmlDocument {
                    XmlResolver = null
                };
                xml.Load(manifestPath);

                var resolver = new PathResolver(baseDef.Folder);

                // ReSharper disable PossibleNullReferenceException
                foreach (XmlNode node in xml.DocumentElement.ChildNodes)

                // ReSharper restore PossibleNullReferenceException
                {
                    if (node.NodeType == XmlNodeType.Element)
                    {
                        var elt = (XmlElement)node;
                        switch (elt.LocalName)
                        {
                        case "template":
                            baseDef.TemplateVirtualPath = GetResolvedPath(elt, resolver);
                            baseDef.TemplatePath        = httpContext.Server.MapPath(baseDef.TemplateVirtualPath);
                            break;

                        case "templateHead":
                            baseDef.TemplateHeadPath = httpContext.Server.MapPath(GetResolvedPath(elt, resolver));
                            break;

                        case "scripts":
                            foreach (XmlElement scriptElt in elt.GetElementsByTagName("script"))
                            {
                                var jsObject   = scriptElt.GetAttribute("jsObject");
                                var scriptPath = string.IsNullOrEmpty(scriptElt.InnerText.Trim())
                                                        ? string.Empty
                                                        : Globals.ResolveUrl(GetResolvedPath(scriptElt, resolver));
                                if (string.IsNullOrEmpty(jsObject))
                                {
                                    var jsLibraryName = scriptElt.GetAttribute("name");
                                    if (!string.IsNullOrEmpty(jsLibraryName))
                                    {
                                        SpecificVersion specificityTemp;
                                        SpecificVersion?specificity = null;
                                        Version         libraryVersion;
                                        if (!Version.TryParse(scriptElt.GetAttribute("version"), out libraryVersion))
                                        {
                                            libraryVersion = null;
                                        }
                                        else if (Enum.TryParse(scriptElt.GetAttribute("specificVersion"), true, out specificityTemp))
                                        {
                                            specificity = specificityTemp;
                                        }

                                        baseDef.ScriptLibraries[jsLibraryName] = Tuple.Create(libraryVersion, specificity);
                                        continue;
                                    }

                                    baseDef.ScriptUrls.Add(scriptPath);
                                    continue;
                                }

                                if (string.IsNullOrEmpty(scriptPath))
                                {
                                    // support legacy named jsObjects that map to libraries
                                    if (jsObject.Equals("jQuery"))
                                    {
                                        Version         libraryVersion = null;
                                        SpecificVersion?specificity    = null;
                                        baseDef.ScriptLibraries[CommonJs.jQuery]        = Tuple.Create(libraryVersion, specificity);
                                        baseDef.ScriptLibraries[CommonJs.jQueryMigrate] = Tuple.Create(libraryVersion, specificity);
                                    }
                                    else if (jsObject.Equals("jQuery.ui"))
                                    {
                                        Version         libraryVersion = null;
                                        SpecificVersion?specificity    = null;
                                        baseDef.ScriptLibraries[CommonJs.jQueryUI] = Tuple.Create(libraryVersion, specificity);
                                    }

                                    continue;
                                }

                                var script = CreateScript(jsObject, scriptPath);
                                if (!string.IsNullOrEmpty(script))
                                {
                                    baseDef.ScriptKeys.Add(jsObject);
                                    baseDef.Scripts.Add(jsObject, script);
                                }
                            }

                            break;

                        case "stylesheets":
                            foreach (XmlElement cssElt in elt.GetElementsByTagName("stylesheet"))
                            {
                                var cssPath = Globals.ResolveUrl(GetResolvedPath(cssElt, resolver));
                                baseDef.StyleSheets.Add(cssPath);
                            }

                            break;

                        case "defaultClientOptions":
                            foreach (XmlElement optionElt in elt.GetElementsByTagName("clientOption"))
                            {
                                var optionName  = optionElt.GetAttribute("name");
                                var optionType  = optionElt.GetAttribute("type");
                                var optionValue = optionElt.GetAttribute("value");
                                if (string.IsNullOrEmpty(optionType))
                                {
                                    optionType = "passthrough";
                                }

                                switch (optionType)
                                {
                                case "number":
                                    baseDef.DefaultClientOptions.Add(new ClientNumber(optionName, optionValue));
                                    break;

                                case "boolean":
                                    baseDef.DefaultClientOptions.Add(new ClientBoolean(optionName, optionValue));
                                    break;

                                case "string":
                                    baseDef.DefaultClientOptions.Add(new ClientString(optionName, optionValue));
                                    break;

                                default:
                                    baseDef.DefaultClientOptions.Add(new ClientOption(optionName, optionValue));
                                    break;
                                }
                            }

                            break;

                        case "defaultTemplateArguments":
                            foreach (XmlElement argElt in elt.GetElementsByTagName("templateArgument"))
                            {
                                var argName  = argElt.GetAttribute("name");
                                var argValue = argElt.GetAttribute("value");
                                baseDef.DefaultTemplateArguments.Add(new TemplateArgument(argName, argValue));
                            }

                            break;
                        }
                    }
                }

                foreach (var processor in DNNAbstract.SupportedTemplateProcessors())
                {
                    if (processor.LoadDefinition(baseDef))
                    {
                        baseDef.Processor = processor;
                        break;
                    }
                }

                if (baseDef.Processor == null)
                {
                    throw new ApplicationException(string.Format("Can't find processor for manifest {0}", manifestPath));
                }

                cache.Insert(manifestPath, baseDef, new CacheDependency(new[] { manifestPath, baseDef.TemplatePath }));
            }

            var result = baseDef.Clone();

            result.Reset();
            return(result);
        }
		public bool LoadDefinition(TemplateDefinition baseDefinition)
		{
			if (!baseDefinition.TemplateVirtualPath.EndsWith(".txt", StringComparison.InvariantCultureIgnoreCase))
			{
				return false;
			}

			var templateText = Utilities.CachedFileContent(baseDefinition.TemplatePath);
			var xml = new XmlDocument();
			const string xmlNs = "http://www.w3.org/1999/XSL/Transform";
			xml.LoadXml(
				@"
				<xsl:stylesheet version='1.0' xmlns:xsl='" + xmlNs + @"' xmlns:ddr='urn:ddrmenu'>
					<xsl:output method='html'/>
					<xsl:template match='/*'>
						<xsl:apply-templates select='root' />
					</xsl:template>
					<xsl:template match='root'>
					</xsl:template>
				</xsl:stylesheet>");

			var validParams = baseDefinition.DefaultTemplateArguments.ConvertAll(a => a.Name.ToLowerInvariant());
			validParams.AddRange(new[] { "controlid", "options", "dnnpath", "manifestpath", "portalpath", "skinpath" });

			var docElt = xml.DocumentElement;
			var outputElt = (XmlElement)(docElt.GetElementsByTagName("output", xmlNs)[0]);
			foreach (var param in validParams)
			{
				var elt = xml.CreateElement("param", xmlNs);
				elt.SetAttribute("name", param);
				docElt.InsertAfter(elt, outputElt);
			}

			var current = (XmlElement)(docElt.GetElementsByTagName("template", xmlNs)[1]);
			var stack = new Stack<XmlElement>();

			var re =
				new Regex(
					@"(\[(?<directive>(\*|\*\>|\/\*|\>|\/\>|\?|\?!|\/\?|\=))(?<nodename>[A-Z]*)(-(?<modename>[0-9A-Z]*))?\])",
					RegexOptions.Compiled | RegexOptions.IgnoreCase);
			var index = 0;
			foreach (Match match in re.Matches(templateText))
			{
				current.AppendChild(xml.CreateTextNode(templateText.Substring(index, match.Index - index)));

				var directive = match.Groups["directive"].Value;
				var nodeName = match.Groups["nodename"].Value.ToLowerInvariant();
				var modeName = match.Groups["modename"].Value.ToLowerInvariant();

				string alias;
				if (aliases.TryGetValue(nodeName, out alias))
				{
					nodeName = alias;
				}

				if (directive == "=")
				{
					var elt = xml.CreateElement("value-of", xmlNs);
					if (validParams.Contains(nodeName))
					{
						elt.SetAttribute("select", "ddr:HtmlEncode($" + nodeName + ")");
					}
					else
					{
						elt.SetAttribute("select", "ddr:HtmlEncode(concat(" + nodeName + ", @" + nodeName + "))");
					}
					current.AppendChild(elt);
				}
				else if (directive == "*")
				{
					var elt = xml.CreateElement("for-each", xmlNs);
					elt.SetAttribute("select", nodeName);
					current.AppendChild(elt);
					stack.Push(current);
					current = elt;
				}
				else if (directive == "*>")
				{
					var elt = xml.CreateElement("apply-templates", xmlNs);
					elt.SetAttribute("select", nodeName);
					elt.SetAttribute("mode", "M" + modeName);
					current.AppendChild(elt);
				}
				else if (directive == ">")
				{
					var elt = xml.CreateElement("template", xmlNs);
					elt.SetAttribute("match", nodeName);
					elt.SetAttribute("mode", "M" + modeName);
					xml.DocumentElement.AppendChild(elt);
					stack.Push(current);
					current = elt;
				}
				else if (directive[0] == '?')
				{
					XmlElement elt;
					if (nodeName != "else")
					{
						elt = xml.CreateElement("when", xmlNs);
                        var test = String.Format("{0} or (@{0}=1) or (@{0}!=0 and @{0}!=1 and @{0}!='')", nodeName);
						if (directive == "?!")
						{
							test = String.Format("not({0})", test);
						}
						elt.SetAttribute("test", test);

						var choose = xml.CreateElement("choose", xmlNs);
						current.AppendChild(choose);
						choose.AppendChild(elt);
						stack.Push(current);
					}
					else
					{
						elt = xml.CreateElement("otherwise", xmlNs);
						current.ParentNode.AppendChild(elt);
					}
					current = elt;
				}
				else if (directive[0] == '/')
				{
					current = stack.Pop();
				}
				index = match.Index + match.Length;
			}
			current.AppendChild(xml.CreateTextNode(templateText.Substring(index)));

			xsl = new XslCompiledTransform();
			xsl.Load(xml);
			return true;
		}
		public void Render(object source, HtmlTextWriter htmlWriter, TemplateDefinition liveDefinition)
		{
			var resolver = new PathResolver(liveDefinition.Folder);
			var args = new XsltArgumentList();
			args.AddExtensionObject("urn:ddrmenu", new XsltFunctions());
			args.AddExtensionObject("urn:dnngarden", new XsltFunctions());
			args.AddParam("controlid", "", DNNContext.Current.HostControl.ClientID);
			args.AddParam("options", "", ConvertToJson(liveDefinition.ClientOptions));
			args.AddParam("dnnpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Dnn));
			args.AddParam("manifestpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Manifest));
			args.AddParam("portalpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Portal));
			args.AddParam("skinpath", "", resolver.Resolve("/", PathResolver.RelativeTo.Skin));
			liveDefinition.TemplateArguments.ForEach(a => args.AddParam(a.Name.ToLowerInvariant(), "", a.Value));

			var sb = new StringBuilder();

			using (var xmlStream = new MemoryStream())
			using (var outputWriter = new StringWriter(sb))
			{
				Utilities.SerialiserFor(source.GetType()).Serialize(xmlStream, source);
				xmlStream.Seek(0, SeekOrigin.Begin);
				xsl.Transform(XmlReader.Create(xmlStream), args, outputWriter);
			}

			htmlWriter.Write(HttpUtility.HtmlDecode(sb.ToString()));
		}
        /// <inheritdoc/>
        public bool LoadDefinition(TemplateDefinition baseDefinition)
        {
            if (!baseDefinition.TemplateVirtualPath.EndsWith(".txt", StringComparison.InvariantCultureIgnoreCase))
            {
                return(false);
            }

            var templateText = Utilities.CachedFileContent(baseDefinition.TemplatePath);
            var xml          = new XmlDocument {
                XmlResolver = null
            };
            const string xmlNs = "http://www.w3.org/1999/XSL/Transform";

            xml.LoadXml(
                @"
				<xsl:stylesheet version='1.0' xmlns:xsl='"                 + xmlNs + @"' xmlns:ddr='urn:ddrmenu'>
					<xsl:output method='html'/>
					<xsl:template match='/*'>
						<xsl:apply-templates select='root' />
					</xsl:template>
					<xsl:template match='root'>
					</xsl:template>
				</xsl:stylesheet>"                );

            var validParams = baseDefinition.DefaultTemplateArguments.ConvertAll(a => a.Name.ToLowerInvariant());

            validParams.AddRange(new[] { "controlid", "options", "dnnpath", "manifestpath", "portalpath", "skinpath" });

            var docElt    = xml.DocumentElement;
            var outputElt = (XmlElement)docElt.GetElementsByTagName("output", xmlNs)[0];

            foreach (var param in validParams)
            {
                var elt = xml.CreateElement("param", xmlNs);
                elt.SetAttribute("name", param);
                docElt.InsertAfter(elt, outputElt);
            }

            var current = (XmlElement)docElt.GetElementsByTagName("template", xmlNs)[1];
            var stack   = new Stack <XmlElement>();

            var index = 0;

            foreach (Match match in TemplatesRegex.Matches(templateText))
            {
                current.AppendChild(xml.CreateTextNode(templateText.Substring(index, match.Index - index)));

                var directive = match.Groups["directive"].Value;
                var nodeName  = match.Groups["nodename"].Value.ToLowerInvariant();
                var modeName  = match.Groups["modename"].Value.ToLowerInvariant();

                string alias;
                if (aliases.TryGetValue(nodeName, out alias))
                {
                    nodeName = alias;
                }

                if (directive == "=")
                {
                    var elt = xml.CreateElement("value-of", xmlNs);
                    if (validParams.Contains(nodeName))
                    {
                        elt.SetAttribute("select", "ddr:HtmlEncode($" + nodeName + ")");
                    }
                    else
                    {
                        elt.SetAttribute("select", "ddr:HtmlEncode(concat(" + nodeName + ", @" + nodeName + "))");
                    }

                    current.AppendChild(elt);
                }
                else if (directive == "*")
                {
                    var elt = xml.CreateElement("for-each", xmlNs);
                    elt.SetAttribute("select", nodeName);
                    current.AppendChild(elt);
                    stack.Push(current);
                    current = elt;
                }
                else if (directive == "*>")
                {
                    var elt = xml.CreateElement("apply-templates", xmlNs);
                    elt.SetAttribute("select", nodeName);
                    elt.SetAttribute("mode", "M" + modeName);
                    current.AppendChild(elt);
                }
                else if (directive == ">")
                {
                    var elt = xml.CreateElement("template", xmlNs);
                    elt.SetAttribute("match", nodeName);
                    elt.SetAttribute("mode", "M" + modeName);
                    xml.DocumentElement.AppendChild(elt);
                    stack.Push(current);
                    current = elt;
                }
                else if (directive[0] == '?')
                {
                    XmlElement elt;
                    if (nodeName != "else")
                    {
                        elt = xml.CreateElement("when", xmlNs);
                        var test = string.Format("{0} or (@{0}=1) or (@{0}!=0 and @{0}!=1 and @{0}!='')", nodeName);
                        if (directive == "?!")
                        {
                            test = string.Format("not({0})", test);
                        }

                        elt.SetAttribute("test", test);

                        var choose = xml.CreateElement("choose", xmlNs);
                        current.AppendChild(choose);
                        choose.AppendChild(elt);
                        stack.Push(current);
                    }
                    else
                    {
                        elt = xml.CreateElement("otherwise", xmlNs);
                        current.ParentNode.AppendChild(elt);
                    }

                    current = elt;
                }
                else if (directive[0] == '/')
                {
                    current = stack.Pop();
                }

                index = match.Index + match.Length;
            }

            current.AppendChild(xml.CreateTextNode(templateText.Substring(index)));

            this.xsl = new XslCompiledTransform();
            this.xsl.Load(xml);
            return(true);
        }
		internal static TemplateDefinition FromManifest(string manifestUrl)
		{
			var httpContext = HttpContext.Current;
			var cache = httpContext.Cache;
			var manifestPath = httpContext.Server.MapPath(manifestUrl);

			var baseDef = cache[manifestPath] as TemplateDefinition;
			if (baseDef == null)
			{
				baseDef = new TemplateDefinition {Folder = Path.GetDirectoryName(manifestUrl)};

				var xml = new XmlDocument();
				xml.Load(manifestPath);

				var resolver = new PathResolver(baseDef.Folder);

				// ReSharper disable PossibleNullReferenceException
				foreach (XmlNode node in xml.DocumentElement.ChildNodes)
					// ReSharper restore PossibleNullReferenceException
				{
					if (node.NodeType == XmlNodeType.Element)
					{
						var elt = (XmlElement)node;
						switch (elt.LocalName)
						{
							case "template":
								baseDef.TemplateVirtualPath = GetResolvedPath(elt, resolver);
								baseDef.TemplatePath = httpContext.Server.MapPath(baseDef.TemplateVirtualPath);
								break;
							case "templateHead":
								baseDef.TemplateHeadPath = httpContext.Server.MapPath(GetResolvedPath(elt, resolver));
								break;
							case "scripts":
								foreach (XmlElement scriptElt in elt.GetElementsByTagName("script"))
								{
									var jsObject = scriptElt.GetAttribute("jsObject");
									var scriptPath = String.IsNullOrEmpty(scriptElt.InnerText.Trim())
									                 	? ""
									                 	: Globals.ResolveUrl(GetResolvedPath(scriptElt, resolver));
									var key = String.IsNullOrEmpty(jsObject) ? scriptPath : jsObject;
									var script = CreateScript(jsObject, scriptPath);
									if (!String.IsNullOrEmpty(script))
									{
										baseDef.ScriptKeys.Add(key);
										baseDef.Scripts.Add(key, script);
									}
								}
								break;
							case "stylesheets":
								foreach (XmlElement cssElt in elt.GetElementsByTagName("stylesheet"))
								{
									var cssPath = Globals.ResolveUrl(GetResolvedPath(cssElt, resolver));
									baseDef.StyleSheets.Add(cssPath);
								}
								break;
							case "defaultClientOptions":
								foreach (XmlElement optionElt in elt.GetElementsByTagName("clientOption"))
								{
									var optionName = optionElt.GetAttribute("name");
									var optionType = optionElt.GetAttribute("type");
									var optionValue = optionElt.GetAttribute("value");
									if (String.IsNullOrEmpty(optionType))
									{
										optionType = "passthrough";
									}
									switch (optionType)
									{
										case "number":
											baseDef.DefaultClientOptions.Add(new ClientNumber(optionName, optionValue));
											break;
										case "boolean":
											baseDef.DefaultClientOptions.Add(new ClientBoolean(optionName, optionValue));
											break;
										case "string":
											baseDef.DefaultClientOptions.Add(new ClientString(optionName, optionValue));
											break;
										default:
											baseDef.DefaultClientOptions.Add(new ClientOption(optionName, optionValue));
											break;
									}
								}
								break;
							case "defaultTemplateArguments":
								foreach (XmlElement argElt in elt.GetElementsByTagName("templateArgument"))
								{
									var argName = argElt.GetAttribute("name");
									var argValue = argElt.GetAttribute("value");
									baseDef.DefaultTemplateArguments.Add(new TemplateArgument(argName, argValue));
								}
								break;
						}
					}
				}

				foreach (var processor in DNNAbstract.SupportedTemplateProcessors())
				{
					if (processor.LoadDefinition(baseDef))
					{
						baseDef.Processor = processor;
						break;
					}
				}

				if (baseDef.Processor == null)
				{
					throw new ApplicationException(String.Format("Can't find processor for manifest {0}", manifestPath));
				}

				cache.Insert(manifestPath, baseDef, new CacheDependency(new[] {manifestPath, baseDef.TemplatePath}));
			}

			var result = baseDef.Clone();
			result.Reset();
			return result;
		}
        internal static TemplateDefinition FromManifest(string manifestUrl)
        {
            var httpContext  = HttpContext.Current;
            var cache        = httpContext.Cache;
            var manifestPath = httpContext.Server.MapPath(manifestUrl);

            var baseDef = cache[manifestPath] as TemplateDefinition;

            if (baseDef == null)
            {
                baseDef = new TemplateDefinition {
                    Folder = Path.GetDirectoryName(manifestUrl)
                };

                var xml = new XmlDocument();
                xml.Load(manifestPath);

                var resolver = new PathResolver(baseDef.Folder);

                // ReSharper disable PossibleNullReferenceException
                foreach (XmlNode node in xml.DocumentElement.ChildNodes)
                // ReSharper restore PossibleNullReferenceException
                {
                    if (node.NodeType == XmlNodeType.Element)
                    {
                        var elt = (XmlElement)node;
                        switch (elt.LocalName)
                        {
                        case "template":
                            baseDef.TemplateVirtualPath = GetResolvedPath(elt, resolver);
                            baseDef.TemplatePath        = httpContext.Server.MapPath(baseDef.TemplateVirtualPath);
                            break;

                        case "templateHead":
                            baseDef.TemplateHeadPath = httpContext.Server.MapPath(GetResolvedPath(elt, resolver));
                            break;

                        case "scripts":
                            foreach (XmlElement scriptElt in elt.GetElementsByTagName("script"))
                            {
                                var jsObject   = scriptElt.GetAttribute("jsObject");
                                var scriptPath = String.IsNullOrEmpty(scriptElt.InnerText.Trim())
                                                                                                ? ""
                                                                                                : Globals.ResolveUrl(GetResolvedPath(scriptElt, resolver));
                                var key    = String.IsNullOrEmpty(jsObject) ? scriptPath : jsObject;
                                var script = CreateScript(jsObject, scriptPath);
                                if (!String.IsNullOrEmpty(script))
                                {
                                    baseDef.ScriptKeys.Add(key);
                                    baseDef.Scripts.Add(key, script);
                                }
                            }
                            break;

                        case "stylesheets":
                            foreach (XmlElement cssElt in elt.GetElementsByTagName("stylesheet"))
                            {
                                var cssPath = Globals.ResolveUrl(GetResolvedPath(cssElt, resolver));
                                baseDef.StyleSheets.Add(cssPath);
                            }
                            break;

                        case "defaultClientOptions":
                            foreach (XmlElement optionElt in elt.GetElementsByTagName("clientOption"))
                            {
                                var optionName  = optionElt.GetAttribute("name");
                                var optionType  = optionElt.GetAttribute("type");
                                var optionValue = optionElt.GetAttribute("value");
                                if (String.IsNullOrEmpty(optionType))
                                {
                                    optionType = "passthrough";
                                }
                                switch (optionType)
                                {
                                case "number":
                                    baseDef.DefaultClientOptions.Add(new ClientNumber(optionName, optionValue));
                                    break;

                                case "boolean":
                                    baseDef.DefaultClientOptions.Add(new ClientBoolean(optionName, optionValue));
                                    break;

                                case "string":
                                    baseDef.DefaultClientOptions.Add(new ClientString(optionName, optionValue));
                                    break;

                                default:
                                    baseDef.DefaultClientOptions.Add(new ClientOption(optionName, optionValue));
                                    break;
                                }
                            }
                            break;

                        case "defaultTemplateArguments":
                            foreach (XmlElement argElt in elt.GetElementsByTagName("templateArgument"))
                            {
                                var argName  = argElt.GetAttribute("name");
                                var argValue = argElt.GetAttribute("value");
                                baseDef.DefaultTemplateArguments.Add(new TemplateArgument(argName, argValue));
                            }
                            break;
                        }
                    }
                }

                foreach (var processor in DNNAbstract.SupportedTemplateProcessors())
                {
                    if (processor.LoadDefinition(baseDef))
                    {
                        baseDef.Processor = processor;
                        break;
                    }
                }

                if (baseDef.Processor == null)
                {
                    throw new ApplicationException(String.Format("Can't find processor for manifest {0}", manifestPath));
                }

                cache.Insert(manifestPath, baseDef, new CacheDependency(new[] { manifestPath, baseDef.TemplatePath }));
            }

            var result = baseDef.Clone();

            result.Reset();
            return(result);
        }