/// <summary> /// Simple parsing to check if input fragment is well-formed, /// HTML elements that do not required end tags (i.e. <BR>) /// will be ignored by this parser. /// </summary> /// <param name="text"> /// text being parsed /// </param> internal static bool IsWellFormed(String text) { int textPos = 0; TagStack stack = new TagStack(); StringBuilder builder = new StringBuilder(); for (;;) { Match match = null; // 1: scan for text up to the next tag. if ((match = _textRegex.Match(text, textPos)).Success) { textPos = match.Index + match.Length; } // we might be done now if (textPos == text.Length) { while (!stack.IsEmpty()) { if (!IsEndTagOptional(stack.Pop())) { return(false); } } return(true); } // First check if it's a unclosed tag (i.e. <mobile:Form >) if ((match = _unclosedTagRegex.Match(text, textPos)).Success) { String startTag = match.Groups["tagname"].Value; stack.Push(startTag); } // Check to see if it's a tag else if ((match = _tagRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an end tag else if ((match = _endtagRegex.Match(text, textPos)).Success) { String endTag = match.Groups["tagname"].Value; bool matched = false; while (!stack.IsEmpty()) { String startTag = stack.Pop(); if (String.Compare(endTag, startTag, true /*ignoreCase*/, CultureInfo.InvariantCulture) != 0) { if (IsEndTagOptional(startTag)) { continue; } // no match against start tag that requires an end tag return(false); } // we found a match here. matched = true; break; } if (!matched && stack.IsEmpty()) { return(false); } } // Check to see if it's a directive (i.e. <%@ %> block) else if ((match = _directiveRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's a server side include // e.g. <!-- #include file="foo.inc" --> else if ((match = _includeRegex.Match(text, textPos)).Success) { // skip it } // Check to see if it's a comment (<%-- --%> block // e.g. <!-- Blah! --> else if ((match = _commentRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an asp expression block (i.e. <%= %> block) else if ((match = _aspExprRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's a databinding expression block (i.e. <%# %> block) // This does not include <%# %> blocks used as values for // attributes of server tags. else if ((match = _databindExprRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an asp code block else if ((match = _aspCodeRegex.Match(text, textPos)).Success) { // skip } // Did we process the block that started with a '<'? if (match == null || !match.Success) { // Skip the '<' textPos++; } else { textPos = match.Index + match.Length; } // we might be done now if (textPos == text.Length) { while (!stack.IsEmpty()) { if (!IsEndTagOptional(stack.Pop())) { return(false); } } return(true); } } }
/// <summary> /// Simple parsing to check if input fragment is well-formed, /// HTML elements that do not required end tags (i.e. <BR>) /// will be ignored by this parser. /// </summary> /// <param name="text"> /// text being parsed /// </param> internal static bool IsWellFormed(String text) { int textPos = 0; TagStack stack = new TagStack(); for (;;) { Match match = null; // 1: scan for text up to the next tag. if ((match = _textRegex.Match(text, textPos)).Success) { textPos = match.Index + match.Length; } // we might be done now if (textPos == text.Length) { while (!stack.IsEmpty()) { if (!IsEndTagOptional(stack.Pop())) { return false; } } return true; } // First check if it's a unclosed tag (i.e. <mobile:Form >) if ((match = _unclosedTagRegex.Match(text, textPos)).Success) { String startTag = match.Groups["tagname"].Value; stack.Push(startTag); } // Check to see if it's a tag else if ((match = _tagRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an end tag else if ((match = _endtagRegex.Match(text, textPos)).Success) { String endTag = match.Groups["tagname"].Value; bool matched = false; while (!stack.IsEmpty()) { String startTag = stack.Pop(); if (String.Compare(endTag, startTag, StringComparison.OrdinalIgnoreCase) != 0) { if (IsEndTagOptional(startTag)) { continue; } // no match against start tag that requires an end tag return false; } // we found a match here. matched = true; break; } if (!matched && stack.IsEmpty()) { return false; } } // Check to see if it's a directive (i.e. <%@ %> block) else if ((match = _directiveRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's a server side include // e.g. <!-- #include file="foo.inc" --> else if ((match = _includeRegex.Match(text, textPos)).Success) { // skip it } // Check to see if it's a comment (<%-- --%> block // e.g. <!-- Blah! --> else if ((match = _commentRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an asp expression block (i.e. <%= %> block) else if ((match = _aspExprRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's a databinding expression block (i.e. <%# %> block) // This does not include <%# %> blocks used as values for // attributes of server tags. else if ((match = _databindExprRegex.Match(text, textPos)).Success) { // skip } // Check to see if it's an asp code block else if ((match = _aspCodeRegex.Match(text, textPos)).Success) { // skip } // Did we process the block that started with a '<'? if (match == null || !match.Success) { // Skip the '<' textPos++; } else { textPos = match.Index + match.Length; } // we might be done now if (textPos == text.Length) { while (!stack.IsEmpty()) { if (!IsEndTagOptional(stack.Pop())) { return false; } } return true; } } }