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