/// <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; } }