private object ValidateAttribute()

in src/dotnet-svcutil/lib/src/FrameworkFork/Microsoft.Xml/Xml/schema/XmlSchemaValidator.cs [526:739]


        private object ValidateAttribute(string lName, string ns, XmlValueGetter attributeValueGetter, string attributeStringValue, XmlSchemaInfo schemaInfo)
        {
            if (lName == null)
            {
                throw new ArgumentNullException("localName");
            }
            if (ns == null)
            {
                throw new ArgumentNullException("namespaceUri");
            }

            ValidatorState toState = _validationStack.Length > 1 ? ValidatorState.Attribute : ValidatorState.TopLevelAttribute;
            CheckStateTransition(toState, s_methodNames[(int)toState]);

            object typedVal = null;
            _attrValid = true;
            XmlSchemaValidity localValidity = XmlSchemaValidity.NotKnown;
            XmlSchemaAttribute localAttribute = null;
            XmlSchemaSimpleType localMemberType = null;

            ns = _nameTable.Add(ns);
            if (Ref.Equal(ns, _nsXmlNs))
            {
                return null;
            }

            SchemaAttDef attributeDef = null;
            SchemaElementDecl currentElementDecl = _context.ElementDecl;
            XmlQualifiedName attQName = new XmlQualifiedName(lName, ns);
            if (_attPresence[attQName] != null)
            { //this attribute already checked as it is duplicate;
                SendValidationEvent(ResXml.Sch_DuplicateAttribute, attQName.ToString());
                if (schemaInfo != null)
                {
                    schemaInfo.Clear();
                }
                return null;
            }

            if (!Ref.Equal(ns, _nsXsi))
            { //TODO add xmlns check here
                XmlSchemaObject pvtAttribute = _currentState == ValidatorState.TopLevelAttribute ? _partialValidationType : null;
                AttributeMatchState attributeMatchState;
                attributeDef = _compiledSchemaInfo.GetAttributeXsd(currentElementDecl, attQName, pvtAttribute, out attributeMatchState);

                switch (attributeMatchState)
                {
                    case AttributeMatchState.UndeclaredElementAndAttribute:
                        if ((attributeDef = CheckIsXmlAttribute(attQName)) != null)
                        { //Try for xml attribute
                            goto case AttributeMatchState.AttributeFound;
                        }
                        if (currentElementDecl == null
                            && _processContents == XmlSchemaContentProcessing.Strict
                            && attQName.Namespace.Length != 0
                            && _compiledSchemaInfo.Contains(attQName.Namespace)
                        )
                        {
                            _attrValid = false;
                            SendValidationEvent(ResXml.Sch_UndeclaredAttribute, attQName.ToString());
                        }
                        else if (_processContents != XmlSchemaContentProcessing.Skip)
                        {
                            SendValidationEvent(ResXml.Sch_NoAttributeSchemaFound, attQName.ToString(), XmlSeverityType.Warning);
                        }
                        break;

                    case AttributeMatchState.UndeclaredAttribute:
                        if ((attributeDef = CheckIsXmlAttribute(attQName)) != null)
                        {
                            goto case AttributeMatchState.AttributeFound;
                        }
                        else
                        {
                            _attrValid = false;
                            SendValidationEvent(ResXml.Sch_UndeclaredAttribute, attQName.ToString());
                        }
                        break;

                    case AttributeMatchState.ProhibitedAnyAttribute:
                        if ((attributeDef = CheckIsXmlAttribute(attQName)) != null)
                        {
                            goto case AttributeMatchState.AttributeFound;
                        }
                        else
                        {
                            _attrValid = false;
                            SendValidationEvent(ResXml.Sch_ProhibitedAttribute, attQName.ToString());
                        }
                        break;

                    case AttributeMatchState.ProhibitedAttribute:
                        _attrValid = false;
                        SendValidationEvent(ResXml.Sch_ProhibitedAttribute, attQName.ToString());
                        break;

                    case AttributeMatchState.AttributeNameMismatch:
                        _attrValid = false;
                        SendValidationEvent(ResXml.Sch_SchemaAttributeNameMismatch, new string[] { attQName.ToString(), ((XmlSchemaAttribute)pvtAttribute).QualifiedName.ToString() });
                        break;

                    case AttributeMatchState.ValidateAttributeInvalidCall:
                        Debug.Assert(_currentState == ValidatorState.TopLevelAttribute); //Re-set state back to start on error with partial validation type
                        _currentState = ValidatorState.Start;
                        _attrValid = false;
                        SendValidationEvent(ResXml.Sch_ValidateAttributeInvalidCall, string.Empty);
                        break;

                    case AttributeMatchState.AnyIdAttributeFound:
                        if (_wildID == null)
                        {
                            _wildID = attributeDef;
                            Debug.Assert(currentElementDecl != null);
                            XmlSchemaComplexType ct = currentElementDecl.SchemaType as XmlSchemaComplexType;
                            Debug.Assert(ct != null);
                            if (ct.ContainsIdAttribute(false))
                            {
                                SendValidationEvent(ResXml.Sch_AttrUseAndWildId, string.Empty);
                            }
                            else
                            {
                                goto case AttributeMatchState.AttributeFound;
                            }
                        }
                        else
                        { //More than one attribute per element cannot match wildcard if both their types are derived from ID
                            SendValidationEvent(ResXml.Sch_MoreThanOneWildId, string.Empty);
                        }
                        break;

                    case AttributeMatchState.AttributeFound:
                        Debug.Assert(attributeDef != null);
                        localAttribute = attributeDef.SchemaAttribute;
                        if (currentElementDecl != null)
                        { //Have to add to hashtable to check whether to add default attributes
                            _attPresence.Add(attQName, attributeDef);
                        }
                        object attValue;
                        if (attributeValueGetter != null)
                        {
                            attValue = attributeValueGetter();
                        }
                        else
                        {
                            attValue = attributeStringValue;
                        }
                        typedVal = CheckAttributeValue(attValue, attributeDef);
                        XmlSchemaDatatype datatype = attributeDef.Datatype;
                        if (datatype.Variety == XmlSchemaDatatypeVariety.Union && typedVal != null)
                        { //Unpack the union
                            XsdSimpleValue simpleValue = typedVal as XsdSimpleValue;
                            Debug.Assert(simpleValue != null);

                            localMemberType = simpleValue.XmlType;
                            datatype = simpleValue.XmlType.Datatype;
                            typedVal = simpleValue.TypedValue;
                        }
                        CheckTokenizedTypes(datatype, typedVal, true);
                        if (HasIdentityConstraints)
                        {
                            AttributeIdentityConstraints(attQName.Name, attQName.Namespace, typedVal, attValue.ToString(), datatype);
                        }
                        break;

                    case AttributeMatchState.AnyAttributeLax:
                        SendValidationEvent(ResXml.Sch_NoAttributeSchemaFound, attQName.ToString(), XmlSeverityType.Warning);
                        break;

                    case AttributeMatchState.AnyAttributeSkip:
                        break;

                    default:
                        break;
                }
            }
            else
            { //Attribute from xsi namespace
                lName = _nameTable.Add(lName);
                if (Ref.Equal(lName, _xsiTypeString) || Ref.Equal(lName, _xsiNilString) || Ref.Equal(lName, _xsiSchemaLocationString) || Ref.Equal(lName, _xsiNoNamespaceSchemaLocationString))
                {
                    _attPresence.Add(attQName, SchemaAttDef.Empty);
                }
                else
                {
                    _attrValid = false;
                    SendValidationEvent(ResXml.Sch_NotXsiAttribute, attQName.ToString());
                }
            }

            if (!_attrValid)
            {
                localValidity = XmlSchemaValidity.Invalid;
            }
            else if (attributeDef != null)
            {
                localValidity = XmlSchemaValidity.Valid;
            }
            if (schemaInfo != null)
            {
                schemaInfo.SchemaAttribute = localAttribute;
                schemaInfo.SchemaType = localAttribute == null ? null : localAttribute.AttributeSchemaType;
                schemaInfo.MemberType = localMemberType;
                schemaInfo.IsDefault = false;
                schemaInfo.Validity = localValidity;
            }
            if (ProcessSchemaHints)
            {
                if (_validatedNamespaces[ns] == null)
                {
                    _validatedNamespaces.Add(ns, ns);
                }
            }
            return typedVal;
        }