// ====================================================================
        //
        //  PRIVATE/PROTECTED METHODS
        //
        // ====================================================================
        private void CheckTag()
        {
            if (TagName.EndsWith("/"))
            {
                TagName = TagName.Substring(0, TagName.Length - 1);
            }
            TagNameNS = TagName;

            ElementInfo = HtmlElementInfo.GetElementInfo(TagNameNS);

            int pos = TagName.IndexOf(':');

            if (pos != -1)
            {
                Namespace = TagName.Substring(0, pos);
                TagName   = TagName.Substring(pos + 1);
            }
            if (ElementInfo == null)
            {
                if (Namespace == null)
                {
                    AddWarning("Unknown tag: " + TagName);
                }
            }
            else
            {
                if (Parent != null)
                {
                    if (!ElementInfo.IsValidParent(Parent.TagName))
                    {
                        AddWarning("Invalid parent for " + TagName + " (parent: " + Parent.TagName + ")");
                    }
                }
            }
        }
        public static string BuildOpenTag(string tagName, List <Tuple <string, string> > attributes, bool noEvents, bool noUnknownAttributes)
        {
            HtmlElementInfo ei = null;

            if (noUnknownAttributes)
            {
                ei = HtmlElementInfo.GetElementInfo(tagName);
            }
            return(InternalBuildOpenTag(ei, tagName, attributes, noEvents, noUnknownAttributes, false));
        }
        // ====================================================================
        //
        //  STATIC METHODS (private/protected)
        //
        // ====================================================================
        private static string InternalBuildOpenTag(HtmlElementInfo ei, string tagName, List <Tuple <string, string> > attributes,
                                                   bool noEvents, bool noUnknownAttributes, bool xmlEmptyTag)
        {
            if (!noUnknownAttributes)
            {
                ei = null;
            }

            StringBuilder sb = new StringBuilder(16 + attributes.Count * 32);

            sb.Append("<");
            sb.Append(tagName);

            foreach (Tuple <string, string> p in attributes)
            {
                string name = p.Item1;
                if (string.IsNullOrWhiteSpace(name) || noEvents && name.StartsWith("on"))
                {
                    continue;
                }


                if (ei != null && ei.GetAttributeStatus(name) == AttrStatus.Unknown)
                {
                    continue;
                }

                if (p.Item2 == null)
                {
                    continue;                     // Empty attribute (valid on HTML5 and above)
                }
                sb.AppendFormat(" {0}=", p.Item1);
                string encodedValue = p.Item2 == null? "" : WebUtility.HtmlEncode(p.Item2);
                sb.AppendFormat("\"{0}\"", encodedValue);
            }
            if (xmlEmptyTag)
            {
                sb.Append(" />");
            }
            else
            {
                sb.Append(">");
            }
            return(sb.ToString());
        }
 public static string BuildOpenTag(HtmlElementInfo ei, List <Tuple <string, string> > attributes, bool noEvents, bool noUnknownAttributes)
 {
     return(InternalBuildOpenTag(ei, ei.TagName, attributes, noEvents, noUnknownAttributes, false));
 }