/// <summary> /// Called when a tag is detected. This method will parse the tag. /// </summary> protected void ParseTag() { _tag.Clear(); _insertEndTag = null; var tagName = new StringBuilder(); _source.Read(); // Is it a comment? if (_source.Peek(TagConst.CommentBegin)) { _source.Skip(TagConst.CommentBegin.Length); while (!_source.Peek(TagConst.CommentEnd)) { int ch = _source.Read(); if (ch != -1) { tagName.Append((char)ch); } else { break; } } _source.Skip(TagConst.CommentEnd.Length); _tag.TagType = Tag.Type.Comment; _tag.Name = tagName.ToString(); return; } // Is it CDATA? if (_source.Peek(TagConst.CDATABegin)) { _source.Skip(TagConst.CDATABegin.Length); while (!_source.Peek(TagConst.CDATAEnd)) { int ch = _source.Read(); if (ch != -1) { tagName.Append((char)ch); } else { break; } } _source.Skip(TagConst.CDATAEnd.Length); _tag.TagType = Tag.Type.CDATA; _tag.Name = tagName.ToString(); return; } // Find the tag name while (_source.Peek() != -1) { // if this is the end of the tag, then stop if (char.IsWhiteSpace((char)_source.Peek()) || (_source.Peek() == '>')) { break; } // if this is both a begin and end tag then stop if ((tagName.Length > 0) && (_source.Peek() == '/')) { break; } tagName.Append((char)_source.Read()); } EatWhitespace(); if (tagName[0] == '/') { _tag.Name = tagName.ToString().Substring(1); _tag.TagType = Tag.Type.End; } else { _tag.Name = tagName.ToString(); _tag.TagType = Tag.Type.Begin; } // get the attributes while ((_source.Peek() != '>') && (_source.Peek() != -1)) { string attributeName = ParseAttributeName(); string attributeValue = null; if (attributeName.Equals("/")) { EatWhitespace(); if (_source.Peek() == '>') { _insertEndTag = _tag.Name; break; } } // is there a value? EatWhitespace(); if (_source.Peek() == '=') { _source.Read(); attributeValue = ParseString(); } _tag.SetAttribute(attributeName, attributeValue); } _source.Read(); }