/// <summary> /// 标签元素 /// </summary> /// <param name="ownerTemplate">宿主模板</param> protected Tag(Template ownerTemplate) : base(ownerTemplate) { this.InnerElements = new ElementCollection<Element>(); this.Attributes = new AttributeCollection(this); //注册添加属性时触发事件.用于设置自身的某些属性值 this.Attributes.Adding += OnAddingAttribute; }
/// <summary> /// 从表达式文本中构造表达式.如果表达式是以$字符开头.并且不是以$$字符开头.则认为是变量表达式.否则则认为是常量表达式 /// </summary> /// <param name="ownerTemplate"></param> /// <param name="expressionText"></param> /// <returns></returns> internal static IExpression CreateExpression(Template ownerTemplate, string expressionText) { if (string.IsNullOrEmpty(expressionText)) return new ConstantExpression(expressionText); if (expressionText.StartsWith("$") && !"$=".Equals(expressionText)) //"$="认为是字符串常量 { expressionText = expressionText.Remove(0, 1); if (expressionText.StartsWith("$")) { //$$字符开头.则认为是常量表达式 return new ConstantExpression(expressionText); } else { //变量表达式 return CreateVariableExpression(ownerTemplate, expressionText, false); } } else { //常量表达式 return Utility.IsInteger(expressionText) ? new ConstantExpression(Utility.ConverToInt32(expressionText)) : new ConstantExpression(expressionText); } }
/// <summary> /// 解析某个模板块的数据 /// </summary> /// <param name="template"></param> public void PreRender(Template template) { //根据模板块里定义的type属性条件取得新闻数据 List<News> newsData = NewsDbProvider.GetNewsData(template.Attributes.GetValue("type")); //设置变量newsdata的值 template.Variables.SetValue("newsdata", newsData); //取得模板块下Id为newslist的标签(也即是在cnblogs_newsdata.html文件中定义的foreach标签) Tag tag = template.GetChildTagById("newslist"); if (tag is ForEachTag) { //如果标签为foreach标签则设置其BeforeRender事件用于设置变量表达式{$:#.news.url}的值 tag.BeforeRender += (sender, e) => { ForEachTag t = (ForEachTag)sender; //取得当前项的值(因为foreach标签的数据源是List<News>集合,所以当前项的值类型为News实体) News news = (News)t.Item.Value; //设置当前项的变量表达式的值.也即是"{$:#.news.url}"变量表达式 t.Item.SetExpValue("url", NewsDbProvider.GetNewsUrl(news)); //当新闻不可见时.你可以取消本次输出 if (!news.Visible) e.Cancel = true; }; } }
/// <summary> /// 克隆当前元素到新的宿主模板 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> internal override Element Clone(Template ownerTemplate) { IncludeTag tag = new IncludeTag(ownerTemplate); this.CopyTo(tag); tag.File = this.File; tag.Charset = this.Charset; return tag; }
/// <summary> /// 带变量字段的初始化 /// </summary> /// <param name="ownerTemplate"></param> /// <param name="varExp"></param> internal VariableTag(Template ownerTemplate, VariableExpression varExp) : base(ownerTemplate) { //注册添加属性时触发事件.用于设置自身的某些属性值 this.Attributes = new AttributeCollection(this); this.Attributes.Adding += OnAddingAttribute; this.VarExpression = varExp; this.CallFunctions = new List<IExpression>(); }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal Template(Template ownerTemplate) : base(ownerTemplate) { this.Visible = true; this.Charset = (ownerTemplate == null ? Encoding.Default : ownerTemplate.Charset); this.Variables = new VariableCollection(); this.ChildTemplates = new ElementCollection<Template>(); this.fileDependencies = new List<string>(); this.UserDefinedFunctions = new UserDefinedFunctionCollection(); this.TagContainer = this; }
/// <summary> /// 构建标签元素 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="match"></param> /// <param name="isClosedTag">是否是自闭合标签</param> /// <returns></returns> internal static Tag CreateTag(Template ownerTemplate, Match match,out bool isClosedTag) { string tagName = match.Groups["tagname"].Value; isClosedTag = match.Groups["closed"].Success; Tag tag = TagFactory.FromTagName(ownerTemplate, tagName); if (tag == null) throw new ParserException(string.Format("不能识别的元素标签\"{0}\"", tagName)); ParseElementAttributes(tag, match); return tag; }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> internal override bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match, bool isClosedTag) { //判断标签的容器是否为ForEach标签 if (!(container is ForEachTag)) throw new ParserException(string.Format("未找到和{0}标签对应的{1}标签", this.TagName, this.EndTagName)); ForEachTag foreachTag = (ForEachTag)container; if (foreachTag.Else != null) throw new ParserException(string.Format("{0}标签不能定义多个{1}标签", this.EndTagName, this.TagName)); foreachTag.Else = this; return true; }
/// <summary> /// 根据标签名建立标签实例 /// </summary> /// <param name="ownerTemplate"></param> /// <param name="tagName"></param> /// <returns></returns> internal static Tag FromTagName(Template ownerTemplate, string tagName) { if (!string.IsNullOrEmpty(tagName)) { switch (tagName.ToLower()) { case "for": return new ForTag(ownerTemplate); case "foreach": return new ForEachTag(ownerTemplate); case "foreachelse": return new ForEachElseTag(ownerTemplate); case "if": return new IfTag(ownerTemplate); case "elseif": return new IfConditionTag(ownerTemplate); case "else": return new ElseTag(ownerTemplate); case "template": return new Template(ownerTemplate); case "include": return new IncludeTag(ownerTemplate); case "expression": return new ExpressionTag(ownerTemplate); case "function": return new FunctionTag(ownerTemplate); case "property": return new PropertyTag(ownerTemplate); case "serverdata": return new ServerDataTag(ownerTemplate); case "set": return new SetTag(ownerTemplate); case "import": return new ImportTag(ownerTemplate); case "output": return new OutputTag(ownerTemplate); case "panel": return new PanelTag(ownerTemplate); case "datareader": if (ownerTemplate.OwnerDocument.DocumentConfig != null && ownerTemplate.OwnerDocument.DocumentConfig.TagOpenMode == TagOpenMode.Full) { return new DataReaderTag(ownerTemplate); } else { return null; } } } return null; }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> internal override bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match, bool isClosedTag) { container.AppendChild(this); if (!string.IsNullOrEmpty(this.File)) { //修正文件地址 this.File = Utility.ResolveFilePath(this.Parent, this.File); if (System.IO.File.Exists(this.File)) { //增加到依赖文件列表 this.OwnerTemplate.AddFileDependency(this.File); //解析数据 new TemplateDocument(ownerTemplate, this, System.IO.File.ReadAllText(this.File, this.Charset), ownerTemplate.OwnerDocument.DocumentConfig); } } return !isClosedTag; }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal IfTag(Template ownerTemplate) : base(ownerTemplate) { this.ElseIfs = new ElementCollection<IfConditionTag>(); }
/// <summary> /// 克隆表达式 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> public IExpression Clone(Template ownerTemplate) { //常量表达式不会被模板外部修改.所以不进行数据克隆 return(this); }
/// <summary> /// 使用特性方法预解析模板数据 /// </summary> /// <param name="renderInstance"></param> /// <param name="renderMethod"></param> /// <param name="template"></param> internal static void PreRenderTemplateByAttributeMethod(string renderInstance, string renderMethod, Template template) { object render = GetRenderInstance(renderInstance); if (render != null) { //取得特性方法 MethodInfo method = null; MethodInfo[] methods = render.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo m in methods) { TemplateRenderMethodAttribute att = System.Attribute.GetCustomAttribute(m, typeof(TemplateRenderMethodAttribute)) as TemplateRenderMethodAttribute; if (att != null) { if (renderMethod.Equals(m.Name, StringComparison.InvariantCultureIgnoreCase)) { method = m; break; } } } if (method != null) { ParameterInfo[] pars = method.GetParameters(); if (pars.Length == 1 && pars[0].ParameterType == typeof(Template)) { method.Invoke(method.IsStatic ? null : render, new object[] { template }); } } } }
/// <summary> /// 克隆当前元素到新的宿主模板 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> internal override Element Clone(Template ownerTemplate) { ForTag tag = new ForTag(ownerTemplate); base.CopyTo(tag); tag.Index = this.Index == null ? null : this.Index.Clone(ownerTemplate); return tag; }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal FunctionTag(Template ownerTemplate) : base(ownerTemplate) { this.FunctionArgs = new ElementCollection <IExpression>(); }
/// <summary> /// 克隆当前元素到新的宿主模板 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> internal override Element Clone(Template ownerTemplate) { TemplateDocument tag = new TemplateDocument(this.DocumentConfig); //优先拷贝变量 foreach (Variable var in this.Variables) { tag.Variables.Add(var.Clone(tag)); } tag.Id = this.Id; tag.Name = this.Name; foreach (var att in this.Attributes) { tag.Attributes.Add(att.Clone(tag)); } tag.Charset = this.Charset; tag.File = this.File; tag.fileDependencies = this.fileDependencies; tag.Visible = this.Visible; foreach (Element element in this.InnerElements) { Element item = element.Clone(tag); tag.AppendChild(item); if (element is Template && this.DocumentElement == element) tag.DocumentElement = (Template)item; } if (tag.DocumentElement == null) tag.DocumentElement = tag; return tag; }
/// <summary> /// 解析字符串 /// </summary> /// <param name="ownerTemplate"></param> /// <param name="text"></param> private void ParseString(Template ownerTemplate, string text) { this.ParseString(ownerTemplate, ownerTemplate, text); }
/// <summary> /// 从模板中获取某个变量.如果不存在此变量则添加新的变量 /// </summary> /// <param name="ownerTemplate"></param> /// <param name="varName"></param> /// <returns></returns> internal static Variable GetVariableOrAddNew(Template ownerTemplate, string varName) { Variable var = ownerTemplate.Variables[varName]; if (var == null) { var = new Variable(ownerTemplate, varName); ownerTemplate.Variables.Add(var); } return var; }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> public virtual bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack <Tag> tagStack, string text, ref Match match, bool isClosedTag) { container.AppendChild(this); return(!isClosedTag); }
/// <summary> /// /// </summary> /// <param name="documentElement"></param> /// <param name="container"></param> /// <param name="text"></param> /// <param name="documentConfig"></param> internal TemplateDocument(Template documentElement, Tag container, string text, TemplateDocumentConfig documentConfig) { this.DocumentConfig = documentConfig; this.AppendChild(documentElement); this.ChildTemplates.Add(documentElement); this.ParseString(documentElement, container, text); }
/// <summary> /// /// </summary> /// <param name="documentElement"></param> /// <param name="text"></param> /// <param name="documentConfig"></param> internal TemplateDocument(Template documentElement, string text, TemplateDocumentConfig documentConfig) : this(documentElement, documentElement, text, documentConfig) { }
/// <summary> /// 解析字符串 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="text">模板文本数据</param> private void ParseString(Template ownerTemplate, Tag container, string text) { //设置根文档模板 this.DocumentElement = ownerTemplate; //this.Text = text; if (string.IsNullOrEmpty(text)) { return; } int charOffset = 0, offset = 0; bool isClosedTag; Match match = null; //标签堆栈 Stack <Tag> tagStack = new Stack <Tag>(); tagStack.Push(container); try { while (offset < text.Length) { if (ParserHelper.IsVariableTagStart(text, offset) && (match = ParserRegex.VarTagRegex.Match(text, offset)).Success) //匹配到模板变量 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建模板变量 ParserHelper.CreateVariableTag(ownerTemplate, container, match); } else if (ParserHelper.IsTagStart(text, offset) && (match = ParserRegex.TagRegex.Match(text, offset)).Success) //匹配到某种类型的标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建标签 Tag tag = ParserHelper.CreateTag(ownerTemplate, match, out isClosedTag); //将标签加入堆栈 tagStack.Push(tag); //将解析权交给标签 bool flag = tag.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); //非已闭合标签或者是单标签则处理标签的结束标签 if (flag) { tag.ProcessEndTag(ownerTemplate, tag, tagStack, text, ref match); } if (tagStack.Count > 0 && tagStack.Peek() == tag && isClosedTag) { //闭合标签则回滚一级 tagStack.Pop(); } //取得容器 if (tagStack.Count > 0) { container = tagStack.Peek(); } } else if (ParserHelper.IsCloseTagStart(text, offset) && (match = ParserRegex.EndTagRegex.Match(text, offset)).Success) //匹配到某个结束标签 { //取得标签名称 string name = match.Groups["tagname"].Value; //非匹配的结束标签.则模板有错 throw new ParserException("无效的结束标签"); } else if (ParserHelper.IsVTExpressionStart(text, offset)) { char s = ParserHelper.ReadChar(text, offset + ParserHelper.VTExpressionHead.Length); int startOffset = offset + ParserHelper.VTExpressionHead.Length + 1; int lastOffset = text.IndexOf(s, offset + ParserHelper.VTExpressionHead.Length + 1); if (lastOffset == -1) { throw new ParserException(string.Format("无法找到VT表达式\"{0}\"的结束标记", ParserHelper.VTExpressionHead)); } string code = text.Substring(startOffset, lastOffset - startOffset); if (code.Length > 0) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //解析表达式里的代码 new TemplateDocument(ownerTemplate, container, code, ownerTemplate.OwnerDocument.DocumentConfig); } offset = lastOffset + 1; charOffset = offset; continue; } else if (ParserHelper.IsCommentTagStart(text, offset)) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //找到注释的起始标记"<!--vt[",则直接查找结束标记"]-->" offset = text.IndexOf(ParserHelper.CommentTagEnd, offset + ParserHelper.CommentTagStart.Length); if (offset == -1) { throw new ParserException("无法找到注释的结束标记"); } offset += ParserHelper.CommentTagEnd.Length; charOffset = offset; continue; } //处理偏移位置 if (match != null && match.Success) { charOffset = offset = match.Index + match.Length; match = null; } else { offset++; } } //处理文本字符 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, text.Length - charOffset); if (tagStack.Count > 1) { //堆栈里还有其它元素.则有错误 throw new ParserException(string.Format("{0}标签未闭合", tagStack.Pop())); } } catch (ParserException ex) { //如果错误中不包含行号与列号.则计算行号与列号 if (!ex.HaveLineAndColumnNumber && match != null && match.Success) { //获取当前出错时正在解析的模板文件 string file = string.Empty; Tag tag = container; while (string.IsNullOrEmpty(file) && tag != null) { if (tag is Template) { file = ((Template)tag).File; } else if (tag is IncludeTag) { file = ((IncludeTag)tag).File; } tag = tag.Parent; } if (string.IsNullOrEmpty(file)) { throw new ParserException(Utility.GetLineAndColumnNumber(text, match.Index), match.ToString(), ex.Message); } else { throw new ParserException(file, Utility.GetLineAndColumnNumber(text, match.Index), match.ToString(), ex.Message); } } else { //继续抛出错误 throw; } } finally { //清空堆栈 tagStack.Clear(); tagStack = null; } }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> internal virtual bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match, bool isClosedTag) { container.AppendChild(this); return !isClosedTag; }
/// <summary> /// 结束标签的解析 /// </summary> /// <param name="ownerTemplate">模板宿主</param> /// <param name="container">元素容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> internal virtual void ProcessEndTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match) { int charOffset = 0, offset = 0; bool isClosedTag; charOffset = offset = match.Index + match.Length; match = null; while (offset < text.Length) { if (ParserHelper.IsVariableTagStart(text, offset) && (match = ParserRegex.VarTagRegex.Match(text, offset)).Success) //匹配到模板变量 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建模板变量 ParserHelper.CreateVariableTag(ownerTemplate, container, match); } else if (ParserHelper.IsTagStart(text, offset) && (match = ParserRegex.TagRegex.Match(text, offset)).Success) //匹配到某种类型的标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建标签 Tag tag = ParserHelper.CreateTag(ownerTemplate, match, out isClosedTag); if (container.IsSingleTag && tag.IsSingleTag) { //如果前容器是单一标签并且当前标签也是单一标签.则回退到上一级非单元素标签 while (tagStack.Count > 0) { container = tagStack.Peek(); if (container.IsSingleTag) { tagStack.Pop(); } else { break; } } } //将当前标签加入堆栈 tagStack.Push(tag); //将解析权交给标签 bool flag = tag.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); //非已闭合标签或者是单标签则处理标签的结束标签 if (flag) { tag.ProcessEndTag(ownerTemplate, tag, tagStack, text, ref match); } if (tagStack.Count > 0 && tagStack.Peek() == tag && isClosedTag) { //闭合标签则回滚一级 tagStack.Pop(); } if (tag.IsSingleTag) { //如果标签是单标签则退出寻找 break; } else { //取得容器 if (tagStack.Count > 0) container = tagStack.Peek(); } } else if (ParserHelper.IsCloseTagStart(text, offset) && (match = ParserRegex.EndTagRegex.Match(text, offset)).Success) //匹配到某个结束标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //取得标签名称 string name = match.Groups["tagname"].Value; //回滚标签堆栈.直到回滚到同名称元素的上级为此 while (tagStack.Count > 0) { Tag popTag = tagStack.Pop(); if (name.Equals(popTag.TagName, StringComparison.InvariantCultureIgnoreCase)) break; if (!name.Equals(popTag.EndTagName, StringComparison.InvariantCultureIgnoreCase)) { //非匹配的结束标签.则模板有错 throw new ParserException(string.Format("无效的结束标签,原期望的是{0}结束标签", popTag.EndTagName)); } } break; } else if (ParserHelper.IsVTExpressionStart(text, offset)) { char s = ParserHelper.ReadChar(text, offset + ParserHelper.VTExpressionHead.Length); int startOffset = offset + ParserHelper.VTExpressionHead.Length + 1; int lastOffset = text.IndexOf(s, offset + ParserHelper.VTExpressionHead.Length + 1); if (lastOffset == -1) throw new ParserException(string.Format("无法找到VT表达式[{0}{1}]的结束标记[{1}]", ParserHelper.VTExpressionHead, s)); string code = text.Substring(startOffset, lastOffset - startOffset); if (code.Length > 0) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //解析表达式里的代码 new TemplateDocument(ownerTemplate, container, code, ownerTemplate.OwnerDocument.DocumentConfig); } offset = lastOffset + 1; charOffset = offset; continue; } else if (ParserHelper.IsCommentTagStart(text, offset)) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //找到注释的起始标记"<!--vt[",则直接查找结束标记"]-->" offset = text.IndexOf(ParserHelper.CommentTagEnd, offset + ParserHelper.CommentTagStart.Length); if (offset == -1) throw new ParserException("无法找到注释的结束标记"); offset += ParserHelper.CommentTagEnd.Length; charOffset = offset; continue; } //处理偏移位置 if (match != null && match.Success) { charOffset = offset = match.Index + match.Length; match = null; } else { offset++; } } if (match == null) throw new ParserException(string.Format("{0}标签未闭合", container.TagName)); }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> internal override bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match, bool isClosedTag) { if (this.Variable == null && !this.Output) throw new ParserException(string.Format("{0}标签中如果未定义Output属性为true则必须定义var属性", this.TagName)); if (this.Values.Count < 1) throw new ParserException(string.Format("{0}标签中缺少value属性", this.TagName)); if (this.Values.Count > 1 && this.Format == null) throw new ParserException(string.Format("{0}标签如果已定义多个value属性,则也必须定义format属性", this.TagName)); return base.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); }
/// <summary> /// 解析字符串 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="text">模板文本数据</param> private void ParseString(Template ownerTemplate, Tag container, string text) { //设置根文档模板 this.DocumentElement = ownerTemplate; //this.Text = text; if (string.IsNullOrEmpty(text)) return; int charOffset = 0, offset = 0; bool isClosedTag; Match match = null; //标签堆栈 Stack<Tag> tagStack = new Stack<Tag>(); tagStack.Push(container); try { while (offset < text.Length) { if (ParserHelper.IsVariableTagStart(text, offset) && (match = ParserRegex.VarTagRegex.Match(text, offset)).Success) //匹配到模板变量 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建模板变量 ParserHelper.CreateVariableTag(ownerTemplate, container, match); } else if (ParserHelper.IsTagStart(text, offset) && (match = ParserRegex.TagRegex.Match(text, offset)).Success) //匹配到某种类型的标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建标签 Tag tag = ParserHelper.CreateTag(ownerTemplate, match, out isClosedTag); //将标签加入堆栈 tagStack.Push(tag); //将解析权交给标签 bool flag = tag.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); //非已闭合标签或者是单标签则处理标签的结束标签 if (flag) { tag.ProcessEndTag(ownerTemplate, tag, tagStack, text, ref match); } if (tagStack.Count > 0 && tagStack.Peek() == tag && isClosedTag) { //闭合标签则回滚一级 tagStack.Pop(); } //取得容器 if (tagStack.Count > 0) container = tagStack.Peek(); } else if (ParserHelper.IsCloseTagStart(text, offset) && (match = ParserRegex.EndTagRegex.Match(text, offset)).Success) //匹配到某个结束标签 { //取得标签名称 string name = match.Groups["tagname"].Value; //非匹配的结束标签.则模板有错 throw new ParserException("无效的结束标签"); } else if (ParserHelper.IsVTExpressionStart(text, offset)) { char s = ParserHelper.ReadChar(text, offset + ParserHelper.VTExpressionHead.Length); int startOffset = offset + ParserHelper.VTExpressionHead.Length + 1; int lastOffset = text.IndexOf(s, offset + ParserHelper.VTExpressionHead.Length + 1); if (lastOffset == -1) throw new ParserException(string.Format("无法找到VT表达式\"{0}\"的结束标记", ParserHelper.VTExpressionHead)); string code = text.Substring(startOffset, lastOffset - startOffset); if (code.Length > 0) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //解析表达式里的代码 new TemplateDocument(ownerTemplate, container, code, ownerTemplate.OwnerDocument.DocumentConfig); } offset = lastOffset + 1; charOffset = offset; continue; } else if (ParserHelper.IsCommentTagStart(text, offset)) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //找到注释的起始标记"<!--vt[",则直接查找结束标记"]-->" offset = text.IndexOf(ParserHelper.CommentTagEnd, offset + ParserHelper.CommentTagStart.Length); if (offset == -1) throw new ParserException("无法找到注释的结束标记"); offset += ParserHelper.CommentTagEnd.Length; charOffset = offset; continue; } //处理偏移位置 if (match != null && match.Success) { charOffset = offset = match.Index + match.Length; match = null; } else { offset++; } } //处理文本字符 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, text.Length - charOffset); if (tagStack.Count > 1) { //堆栈里还有其它元素.则有错误 throw new ParserException(string.Format("{0}标签未闭合", tagStack.Pop())); } } catch (ParserException ex) { //如果错误中不包含行号与列号.则计算行号与列号 if (!ex.HaveLineAndColumnNumber && match != null && match.Success) { //获取当前出错时正在解析的模板文件 string file = string.Empty; Tag tag = container; while (string.IsNullOrEmpty(file) && tag != null) { if (tag is Template) { file = ((Template)tag).File; } else if (tag is IncludeTag) { file = ((IncludeTag)tag).File; } tag = tag.Parent; } if (string.IsNullOrEmpty(file)) { throw new ParserException(Utility.GetLineAndColumnNumber(text, match.Index), match.ToString(), ex.Message); } else { throw new ParserException(file, Utility.GetLineAndColumnNumber(text, match.Index), match.ToString(), ex.Message); } } else { //继续抛出错误 throw; } } finally { //清空堆栈 tagStack.Clear(); tagStack = null; } }
/// <summary> /// 克隆当前元素到新的宿主模板 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> internal override Element Clone(Template ownerTemplate) { SetTag tag = new SetTag(ownerTemplate); this.CopyTo(tag); tag.Variable = this.Variable == null ? null : this.Variable.Clone(ownerTemplate); tag.Output = this.Output; foreach (IExpression exp in this.Values) { tag.Values.Add((IExpression)(exp.Clone(ownerTemplate))); } return tag; }
/// <summary> /// 结束标签的解析 /// </summary> /// <param name="ownerTemplate">模板宿主</param> /// <param name="container">元素容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> public virtual void ProcessEndTag(Template ownerTemplate, Tag container, Stack <Tag> tagStack, string text, ref Match match) { int charOffset = 0, offset = 0; bool isClosedTag; charOffset = offset = match.Index + match.Length; match = null; while (offset < text.Length) { if (ParserHelper.IsVariableTagStart(text, offset) && (match = ParserRegex.VarTagRegex.Match(text, offset)).Success) //匹配到模板变量 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建模板变量 ParserHelper.CreateVariableTag(ownerTemplate, container, match); } else if (ParserHelper.IsTagStart(text, offset) && (match = ParserRegex.TagRegex.Match(text, offset)).Success) //匹配到某种类型的标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //构建标签 Tag tag = ParserHelper.CreateTag(ownerTemplate, match, out isClosedTag); if (container.IsSingleTag && tag.IsSingleTag) { //如果前容器是单一标签并且当前标签也是单一标签.则回退到上一级非单元素标签 while (tagStack.Count > 0) { container = tagStack.Peek(); if (container.IsSingleTag) { tagStack.Pop(); } else { break; } } } //将当前标签加入堆栈 tagStack.Push(tag); //将解析权交给标签 bool flag = tag.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); //非已闭合标签或者是单标签则处理标签的结束标签 if (flag) { tag.ProcessEndTag(ownerTemplate, tag, tagStack, text, ref match); } if (tagStack.Count > 0 && tagStack.Peek() == tag && isClosedTag) { //闭合标签则回滚一级 tagStack.Pop(); } if (tag.IsSingleTag) { //如果标签是单标签则退出寻找 break; } else { //取得容器 if (tagStack.Count > 0) { container = tagStack.Peek(); } } } else if (ParserHelper.IsCloseTagStart(text, offset) && (match = ParserRegex.EndTagRegex.Match(text, offset)).Success) //匹配到某个结束标签 { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, match.Index - charOffset); //取得标签名称 string name = match.Groups["tagname"].Value; //回滚标签堆栈.直到回滚到同名称元素的上级为此 while (tagStack.Count > 0) { Tag popTag = tagStack.Pop(); if (name.Equals(popTag.TagName, StringComparison.InvariantCultureIgnoreCase)) { break; } if (!name.Equals(popTag.EndTagName, StringComparison.InvariantCultureIgnoreCase)) { //非匹配的结束标签.则模板有错 throw new ParserException(string.Format("无效的结束标签,原期望的是{0}结束标签", popTag.EndTagName)); } } break; } else if (ParserHelper.IsVTExpressionStart(text, offset)) { char s = ParserHelper.ReadChar(text, offset + ParserHelper.VTExpressionHead.Length); int startOffset = offset + ParserHelper.VTExpressionHead.Length + 1; int lastOffset = text.IndexOf(s, offset + ParserHelper.VTExpressionHead.Length + 1); if (lastOffset == -1) { throw new ParserException(string.Format("无法找到VT表达式[{0}{1}]的结束标记[{1}]", ParserHelper.VTExpressionHead, s)); } string code = text.Substring(startOffset, lastOffset - startOffset); if (code.Length > 0) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //解析表达式里的代码 new TemplateDocument(ownerTemplate, container, code, ownerTemplate.OwnerDocument.DocumentConfig); } offset = lastOffset + 1; charOffset = offset; continue; } else if (ParserHelper.IsCommentTagStart(text, offset)) { //构建文本节点 ParserHelper.CreateTextNode(ownerTemplate, container, text, charOffset, offset - charOffset); //找到注释的起始标记"<!--vt[",则直接查找结束标记"]-->" offset = text.IndexOf(ParserHelper.CommentTagEnd, offset + ParserHelper.CommentTagStart.Length); if (offset == -1) { throw new ParserException("无法找到注释的结束标记"); } offset += ParserHelper.CommentTagEnd.Length; charOffset = offset; continue; } //处理偏移位置 if (match != null && match.Success) { charOffset = offset = match.Index + match.Length; match = null; } else { offset++; } } if (match == null) { throw new ParserException(string.Format("{0}标签未闭合", container.TagName)); } }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal IncludeTag(Template ownerTemplate) : base(ownerTemplate) { this.Charset = ownerTemplate.Charset; }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal SetTag(Template ownerTemplate) : base(ownerTemplate) { this.Values = new ElementCollection <IExpression>(); }
/// <summary> /// 根据前缀获取变量的模板所有者 /// </summary> /// <param name="template"></param> /// <param name="prefix"></param> /// <returns>如果prefix值为null则返回template的根模板.如果为空值.则为template.如果为#则返回template的父模板.否则返回对应Id的模板</returns> internal static Template GetOwnerTemplateByPrefix(Template template, string prefix) { if (prefix == string.Empty) return template; //前缀为空.则返回当前模板 if (prefix == "#") return template.OwnerTemplate ?? template; //前缀为#.则返回父模板(如果父模板不存在则返回当前模板) //取得根模板 while (template.OwnerTemplate != null) template = template.OwnerTemplate; //如果没有前缀.则返回根模板.否则返回对应Id的模板 return prefix == null ? template : template.GetChildTemplateById(prefix); }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal IfTag(Template ownerTemplate) : base(ownerTemplate) { this.ElseIfs = new ElementCollection <IfConditionTag>(); }
/// <summary> /// 预解析模板数据 /// </summary> /// <param name="renderInstance">模板解析器实例的配置</param> /// <param name="template">要解析处理的模板</param> internal static void PreRenderTemplate(string renderInstance, Template template) { ITemplateRender render = GetRenderInstance(renderInstance) as ITemplateRender; if (render != null) render.PreRender(template); }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal DataReaderTag(Template ownerTemplate) : base(ownerTemplate) { this.Parameters = new ElementCollection <IExpression>(); }
/// <summary> /// 克隆表达式 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> public IExpression Clone(Template ownerTemplate) { //常量表达式不会被模板外部修改.所以不进行数据克隆 return this; }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal SetTag(Template ownerTemplate) : base(ownerTemplate) { this.Values = new ElementCollection<IExpression>(); }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> /// <param name="text"></param> internal TextNode(Template ownerTemplate, string text) : base(ownerTemplate) { this.Text = text; }
/// <summary> /// 开始解析标签数据 /// </summary> /// <param name="ownerTemplate">宿主模板</param> /// <param name="container">标签的容器</param> /// <param name="tagStack">标签堆栈</param> /// <param name="text"></param> /// <param name="match"></param> /// <param name="isClosedTag">是否闭合标签</param> /// <returns>如果需要继续处理EndTag则返回true.否则请返回false</returns> internal override bool ProcessBeginTag(Template ownerTemplate, Tag container, Stack<Tag> tagStack, string text, ref Match match, bool isClosedTag) { if (this.From == null) throw new ParserException(string.Format("{0}标签中缺少from属性", this.TagName)); if (this.To == null) throw new ParserException(string.Format("{0}标签中缺少to属性", this.TagName)); return base.ProcessBeginTag(ownerTemplate, container, tagStack, text, ref match, isClosedTag); }
/// <summary> /// 克隆当前元素到新的宿主模板 /// </summary> /// <param name="ownerTemplate"></param> /// <returns></returns> internal override Element Clone(Template ownerTemplate) { return(new TextNode(ownerTemplate, this.Text)); }
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> internal ForTag(Template ownerTemplate) : base(ownerTemplate) {}
/// <summary> /// /// </summary> /// <param name="ownerTemplate"></param> public ImportTag(Template ownerTemplate) : base(ownerTemplate) { }