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