/*
         * <controlAdapters>
         *   <adapter controlType="System.Web.UI.WebControls.Image"
         *            adapterType="System.Web.UI.WebControls.Adapters.Html32ImageAdapter" />
         * </controlAdapters>
         */
        internal void ProcessControlAdaptersNode(XmlNode node)
        {
            HandlerBase.GetAndRemoveStringAttribute(node, "markupTextWriterType", ref _htmlTextWriterString);
            foreach (XmlNode child in node.ChildNodes)
            {
                if (child.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                if (child.Name != "adapter")
                {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_unrecognized_element), child);
                }
                XmlAttributeCollection nodeAttributes = child.Attributes;
                string controlString = null;
                string adapterString = null;
                HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "controlType", ref controlString);
                HandlerBase.GetAndRemoveRequiredStringAttribute(child, "adapterType", ref adapterString);

                Type type = CheckType(controlString, typeof(Control), child);

                // Normalize control type name
                controlString = type.AssemblyQualifiedName;

                if (!String.IsNullOrEmpty(adapterString))
                {
                    CheckType(adapterString, typeof(System.Web.UI.Adapters.ControlAdapter), child);
                }

                _adapters[controlString] = adapterString;
            }
            return;
        }
        /*
         * <capabilities>
         *   <capability name="mobileDeviceManufacturer" value="OpenWave"</capability>
         *   <capability name="numberOfSoftKeys" value="$(softkeys)"</capability>
         * </capabilities>
         */

        internal void ProcessCapabilitiesNode(XmlNode node)
        {
            foreach (XmlNode child in node.ChildNodes)
            {
                if (child.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                if (child.Name != "capability")
                {
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_base_unrecognized_element), child);
                }
                string capabilityName  = null;
                string capabilityValue = null;
                HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref capabilityName);
                HandlerBase.GetAndRemoveRequiredStringAttribute(child, "value", ref capabilityValue);
                _capabilities[capabilityName] = capabilityValue;
            }
            return;
        }
        internal void ProcessCaptureNode(XmlNode node, BrowserCapsElementType elementType)
        {
            string match  = null;
            string header = null;

            foreach (XmlNode child in node.ChildNodes)
            {
                if (child.NodeType != XmlNodeType.Element)
                {
                    continue;
                }
                switch (child.Name)
                {
                case "userAgent":
                    //match the user agent
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "match", ref match);
                    _captureHeaderChecks.Add(new CheckPair("User-Agent", match));
                    break;

                case "header":
                    //match some arbitrary header
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref header);
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "match", ref match);
                    _captureHeaderChecks.Add(new CheckPair(header, match));
                    break;

                case "capability":
                    //match against an already set capability
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref header);
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "match", ref match);
                    _captureCapabilityChecks.Add(new CheckPair(header, match));
                    break;

                default:
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_invalid_element, child.ToString()), child);
                }
            }
            return;
        }
        /*
         * /*
         * <identification>
         * <userAgent match="xxx" />
         * <header name="HTTP_X_JPHONE_DISPLAY" match="xxx" />
         * <capability name="majorVersion" match="^6$" />
         * </identification>
         * <capture>
         * <header name="HTTP_X_UP_DEVCAP_NUMSOFTKEYS" match="?'softkeys'\d+)" />
         * </capture>
         */
        internal void ProcessIdentificationNode(XmlNode node, BrowserCapsElementType elementType)
        {
            string match  = null;
            string header = null;
            bool   nonMatch;
            bool   emptyIdentification = true;

            foreach (XmlNode child in node.ChildNodes)
            {
                match    = String.Empty;
                nonMatch = false;
                if (child.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                switch (child.Name)
                {
                case "userAgent":
                    emptyIdentification = false;

                    //match the user agent
                    HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "match", ref match);
                    if (String.IsNullOrEmpty(match))
                    {
                        HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "nonMatch", ref match);

                        if (String.IsNullOrEmpty(match))
                        {
                            HandleMissingMatchAndNonMatchError(child);
                        }

                        nonMatch = true;
                    }
                    _idHeaderChecks.Add(new CheckPair("User-Agent", match, nonMatch));
                    if (nonMatch == false)
                    {
                        DisallowNonMatchAttribute(child);
                    }

                    break;

                case "header":
                    emptyIdentification = false;

                    //match some arbitrary header
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref header);
                    HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "match", ref match);
                    if (String.IsNullOrEmpty(match))
                    {
                        HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "nonMatch", ref match);

                        if (String.IsNullOrEmpty(match))
                        {
                            HandleMissingMatchAndNonMatchError(child);
                        }

                        nonMatch = true;
                    }
                    _idHeaderChecks.Add(new CheckPair(header, match, nonMatch));
                    if (nonMatch == false)
                    {
                        DisallowNonMatchAttribute(child);
                    }
                    break;

                case "capability":
                    emptyIdentification = false;

                    //match against an already set capability
                    HandlerBase.GetAndRemoveRequiredNonEmptyStringAttribute(child, "name", ref header);
                    HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "match", ref match);
                    if (String.IsNullOrEmpty(match))
                    {
                        HandlerBase.GetAndRemoveNonEmptyStringAttribute(child, "nonMatch", ref match);

                        if (String.IsNullOrEmpty(match))
                        {
                            HandleMissingMatchAndNonMatchError(child);
                        }

                        nonMatch = true;
                    }
                    _idCapabilityChecks.Add(new CheckPair(header, match, nonMatch));
                    //verify that match and nonMatch are not both specified
                    if (nonMatch == false)
                    {
                        DisallowNonMatchAttribute(child);
                    }
                    break;

                default:
                    throw new ConfigurationErrorsException(SR.GetString(SR.Config_invalid_element, child.ToString()), child);
                }
            }

            if (emptyIdentification)
            {
                throw new ConfigurationErrorsException(SR.GetString(SR.Browser_empty_identification), node);
            }

            return;
        }