Mono.Xml.DTDValidatingReader.DtdValidateAttributes C# (CSharp) Method

DtdValidateAttributes() private method

private DtdValidateAttributes ( DTDAttListDeclaration decl, bool validate ) : void
decl DTDAttListDeclaration
validate bool
return void
		private void DtdValidateAttributes (DTDAttListDeclaration decl, bool validate)
		{
			while (reader.MoveToNextAttribute ()) {
				string attrName = reader.Name;
				AttributeSlot slot = GetAttributeSlot ();
				slot.Name = reader.Name;
				slot.LocalName = reader.LocalName;
				slot.Prefix = reader.Prefix;
				XmlReader targetReader = reader;
				string attrValue = String.Empty;
				// For attribute node, it always resolves
				// entity references on attributes.
				while (attributeValueEntityStack.Count >= 0) {
					if (!targetReader.ReadAttributeValue ()) {
						if (attributeValueEntityStack.Count > 0) {
							targetReader = attributeValueEntityStack.Pop () as XmlReader;
							continue;
						} else
							break;
					}
					switch (targetReader.NodeType) {
					case XmlNodeType.EntityReference:
						DTDEntityDeclaration edecl = DTD.EntityDecls [targetReader.Name];
						if (edecl == null) {
							HandleError (String.Format ("Referenced entity {0} is not declared.", targetReader.Name),
								XmlSeverityType.Error);
						} else {
							XmlTextReader etr = new XmlTextReader (edecl.EntityValue, XmlNodeType.Attribute, ParserContext);
							attributeValueEntityStack.Push (targetReader);
							targetReader = etr;
							continue;
						}
						break;
					case XmlNodeType.EndEntity:
						break;
					default:
						attrValue += targetReader.Value;
						break;
					}
				}
				
				reader.MoveToElement ();
				reader.MoveToAttribute (attrName);
				slot.Value = FilterNormalization (attrName, attrValue);

				if (!validate)
					continue;

				// Validation

				DTDAttributeDefinition def = decl [reader.Name];
				if (def == null) {
					HandleError (String.Format ("Attribute {0} is not declared.", reader.Name),
						XmlSeverityType.Error);
					continue;
				}

				// check enumeration constraint
				if (def.EnumeratedAttributeDeclaration.Count > 0)
					if (!def.EnumeratedAttributeDeclaration.Contains (slot.Value))
						HandleError (String.Format ("Attribute enumeration constraint error in attribute {0}, value {1}.",
							reader.Name, attrValue), XmlSeverityType.Error);
				if (def.EnumeratedNotations.Count > 0)
					if (!def.EnumeratedNotations.Contains (
						slot.Value))
						HandleError (String.Format ("Attribute notation enumeration constraint error in attribute {0}, value {1}.",
							reader.Name, attrValue), XmlSeverityType.Error);

				// check type constraint
				string normalized = null;
				if (def.Datatype != null)
					normalized = FilterNormalization (def.Name, attrValue);
				else
					normalized = attrValue;
				DTDEntityDeclaration ent;

				// Common process to get list value
				string [] list = null;
				switch (def.Datatype.TokenizedType) {
				case XmlTokenizedType.IDREFS:
				case XmlTokenizedType.ENTITIES:
				case XmlTokenizedType.NMTOKENS:
					try {
						list = def.Datatype.ParseValue (normalized, NameTable, null) as string [];
					} catch (Exception) {
						HandleError ("Attribute value is invalid against its data type.", XmlSeverityType.Error);
						list = new string [0];
					}
					break;
				default:
					try {
						def.Datatype.ParseValue (normalized, NameTable, null);
					} catch (Exception ex) {
						HandleError (String.Format ("Attribute value is invalid against its data type '{0}'. {1}", def.Datatype, ex.Message), XmlSeverityType.Error);
					}
					break;
				}

				switch (def.Datatype.TokenizedType) {
				case XmlTokenizedType.ID:
					if (this.idList.Contains (normalized)) {
						HandleError (String.Format ("Node with ID {0} was already appeared.", attrValue),
							XmlSeverityType.Error);
					} else {
						if (missingIDReferences.Contains (normalized))
							missingIDReferences.Remove (normalized);
						idList.Add (normalized);
					}
					break;
				case XmlTokenizedType.IDREF:
					if (!idList.Contains (normalized))
						missingIDReferences.Add (normalized);
					break;
				case XmlTokenizedType.IDREFS:
					for (int i = 0; i < list.Length; i++) {
						string idref = list [i];
						if (!idList.Contains (idref))
							missingIDReferences.Add (idref);
					}
					break;
				case XmlTokenizedType.ENTITY:
					ent = dtd.EntityDecls [normalized];
					if (ent == null)
						HandleError ("Reference to undeclared entity was found in attribute: " + reader.Name + ".", XmlSeverityType.Error);
					else if (ent.NotationName == null)
						HandleError ("The entity specified by entity type value must be an unparsed entity. The entity definition has no NDATA in attribute: " + reader.Name + ".", XmlSeverityType.Error);
					break;
				case XmlTokenizedType.ENTITIES:
					for (int i = 0; i < list.Length; i++) {
						string entref = list [i];
						ent = dtd.EntityDecls [FilterNormalization (reader.Name, entref)];
						if (ent == null)
							HandleError ("Reference to undeclared entity was found in attribute: " + reader.Name + ".", XmlSeverityType.Error);
						else if (ent.NotationName == null)
							HandleError ("The entity specified by ENTITIES type value must be an unparsed entity. The entity definition has no NDATA in attribute: " + reader.Name + ".", XmlSeverityType.Error);
					}
					break;
//				case XmlTokenizedType.NMTOKEN: nothing to do
//				case XmlTokenizedType.NMTOKENS: nothing to do
				}

				if (isStandalone && !def.IsInternalSubset && 
					attrValue != normalized)
					HandleError ("In standalone document, attribute value characters must not be checked against external definition.", XmlSeverityType.Error);

				if (def.OccurenceType == 
					DTDAttributeOccurenceType.Fixed &&
					attrValue != def.DefaultValue)
					HandleError (String.Format ("Fixed attribute {0} in element {1} has invalid value {2}.",
						def.Name, decl.Name, attrValue),
						XmlSeverityType.Error);
			}

			if (validate)
				VerifyDeclaredAttributes (decl);

			MoveToElement ();
		}