/// <summary> /// Parse in tag /// </summary> protected ParsedToken ParseInTag() { _CurrentRead = null; // Whitespaces CharInfo c; while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } var cpos = c.Position; // EOF ? if (c == CharInfo.EOF) { _CurrentToken = null; _State = ParseState.Content; ResetTagBuffer(); throw new ParseError("Unexpected end of file. Tag not closed.", ReadPosition); } // End of auto closed tag ? else if (c == '/' && _State == ParseState.Tag) { CharInfo saveSlash = c; bool spaces = false; while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { spaces = true; } if (c != '>') { // Prepare a correct next tag SaveChar(new CharInfo('>', (c == CharInfo.EOF) ? saveSlash.Position : c.Position)); SaveChar(saveSlash); throw new ParseError("Invalid char after '/'. End of auto closed tag expected.", cpos); } if (spaces) { // Prepare a correct next tag SaveChar(c); SaveChar(saveSlash); // Raise the error throw new ParseError("Invalid auto closed tag, '/' need to be follow by '>'.", cpos); } // Returns autoclosed var result = ParsedTag.AutoClosedTag(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } // End of process instruction else if (c == '?' && _State == ParseState.ProcessInstruction) { c = ReadChar(false); if (c != '>') { throw new ParseError("Invalid char after '?'. End of process instruction expected.", cpos); } // Returns processinstruction var result = ParsedTag.CloseProcessInstruction(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } else if (c == '>') { // Check tag if (_State == ParseState.ProcessInstruction) { throw new ParseError("A process instruction need to be closed with '?>'.", cpos); } // Returns close var result = ParsedTag.CloseTag(((ParsedTag)_CurrentToken).TagName); result.Position = cpos; _CurrentToken = null; _CurrentRead = null; _State = ParseState.Content; ResetTagBuffer(); return(result); } // Get the attribute name if (!IsAttributeNameChar(c.AsChar)) { throw new ParseError("Unexpected character.", cpos); } AddToCurrentRead(c); while ((c = ReadChar(false)) != CharInfo.EOF && IsAttributeNameChar(c.AsChar)) { AddToCurrentRead(c); } if (c != CharInfo.EOF) { SaveChar(c); } String attrName = GetCurrentRead(true); ParsePosition attrPos = cpos; // Whitespaces while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } // Attribute whithout value if (c != '=') { SaveChar(c); // Attribute whithout content return(new ParsedAttribute() { Position = attrPos, Name = attrName, Value = null, Quote = '\0' }); } // Whitespaces while ((c = ReadChar(false)) != CharInfo.EOF && Char.IsWhiteSpace(c.AsChar)) { ; } // Search the value if (c == 0 || c == '/' || c == '?' || c == '>') { _CurrentAttr = new ParsedAttribute() { Position = attrPos, Name = attrName, Value = null, Quote = '\0' }; if (c != CharInfo.EOF) { SaveChar(c); } throw new ParseError("Attribute value expected.", ReadPosition); } // Quoted value ? _CurrentRead = null; char quote = '\0'; if (c == '"' || c == '\'') { quote = c.AsChar; while ((c = ReadChar(false)) != CharInfo.EOF && c != quote) { AddToCurrentRead(c); } _CurrentAttr = new ParsedAttribute() { Position = attrPos, Name = attrName, Value = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities), Quote = quote }; if (c == CharInfo.EOF) { throw new ParseError("Unexpected end of file. Attribute is not closed.", ReadPosition); } var result = _CurrentAttr; _CurrentAttr = null; return(result); } // Unquoted value AddToCurrentRead(c); while ((c = ReadChar(false)) != CharInfo.EOF && !Char.IsWhiteSpace(c.AsChar) && c != '"' && c != '\'' && c != '=' && c != '<' && c != '>' && c != '`') { AddToCurrentRead(c); } SaveChar(c); return(new ParsedAttribute() { Position = attrPos, Name = attrName, Value = HEntity.HtmlDecode(GetCurrentRead(true), RemoveUnknownOrInvalidEntities), Quote = quote }); }