private void EndElementIdentityConstraints() { for (int ci = this.validationStack.Length - 1; ci >= this.startIDConstraint; ci--) { // no constraint for this level if (((ValidationState)(this.validationStack[ci])).Constr == null) { continue; } // else ConstraintStruct[] constraints = ((ValidationState)this.validationStack[ci]).Constr; for (int i = 0; i < constraints.Length; ++i) { // EndChildren // axisFields is not null, but may be empty for (int j = 0; j < constraints[i].axisFields.Count; ++j) { LocatedActiveAxis laxis = (LocatedActiveAxis)constraints[i].axisFields[j]; // check field from here // isMatched is false when nextElement is null. so needn't change this part. if (laxis.isMatched) { Debug.WriteLine("Element Field Filling Value!"); Debug.WriteLine("Name: " + reader.LocalName + "\t|\tURI: " + reader.NamespaceURI + "\t|\tValue: " + reader.TypedValueObject + "\n"); // fill value laxis.isMatched = false; if (laxis.Ks[laxis.Column] != null) { // [field...] should be evaluated to either an empty node-set or a node-set with exactly one member // two matches... already existing field value in the table. SendValidationEvent(Res.Sch_FieldSingleValueExpected, reader.LocalName); } else { // for element, reader.Value = ""; string stringValue = !hasSibling ? textString : textValue.ToString(); // only for identity-constraint exception reporting if (reader.TypedValueObject != null && stringValue.Length != 0) { laxis.Ks[laxis.Column] = new TypedObject(reader.TypedValueObject, stringValue, context.ElementDecl.Datatype); } } } // EndChildren laxis.EndElement(reader.LocalName, reader.NamespaceURI); } if (constraints[i].axisSelector.EndElement(reader.LocalName, reader.NamespaceURI)) { // insert key sequence into hash (+ located active axis tuple leave for later) KeySequence ks = constraints[i].axisSelector.PopKS(); // unqualified keysequence are not allowed switch (constraints[i].constraint.Role) { case CompiledIdentityConstraint.ConstraintRole.Key: if (!ks.IsQualified()) { //Key's fields can't be null... if we can return context node's line info maybe it will be better //only keymissing & keyduplicate reporting cases are necessary to be dealt with... 3 places... SendValidationEvent(new XmlSchemaException(Res.Sch_MissingKey, constraints[i].constraint.name.ToString(), reader.BaseURI, ks.PosLine, ks.PosCol)); } else if (constraints[i].qualifiedTable.Contains(ks)) { // unique or key checking value confliction // for redundant key, reporting both occurings // doesn't work... how can i retrieve value out?? SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey, new string[2] { ks.ToString(), constraints[i].constraint.name.ToString() }, reader.BaseURI, ks.PosLine, ks.PosCol)); } else { constraints[i].qualifiedTable.Add(ks, ks); } break; case CompiledIdentityConstraint.ConstraintRole.Unique: if (!ks.IsQualified()) { continue; } if (constraints[i].qualifiedTable.Contains(ks)) { // unique or key checking confliction SendValidationEvent(new XmlSchemaException(Res.Sch_DuplicateKey, new string[2] { ks.ToString(), constraints[i].constraint.name.ToString() }, reader.BaseURI, ks.PosLine, ks.PosCol)); } else { constraints[i].qualifiedTable.Add(ks, ks); } break; case CompiledIdentityConstraint.ConstraintRole.Keyref: // is there any possibility: // 2 keyrefs: value is equal, type is not // both put in the hashtable, 1 reference, 1 not if (constraints[i].qualifiedTable != null) //Will be null in cases when the keyref is outside the scope of the key, that is not allowed by our impl { if (!ks.IsQualified() || constraints[i].qualifiedTable.Contains(ks)) { continue; } constraints[i].qualifiedTable.Add(ks, ks); } break; } } } } // current level's constraint struct ConstraintStruct[] vcs = ((ValidationState)(this.validationStack[this.validationStack.Length - 1])).Constr; if (vcs != null) { // validating all referencing tables... for (int i = 0; i < vcs.Length; ++i) { if ((vcs[i].constraint.Role == CompiledIdentityConstraint.ConstraintRole.Keyref) || (vcs[i].keyrefTable == null)) { continue; } foreach (KeySequence ks in vcs[i].keyrefTable.Keys) { if (!vcs[i].qualifiedTable.Contains(ks)) { SendValidationEvent(new XmlSchemaException(Res.Sch_UnresolvedKeyref, new string[2] { ks.ToString(), vcs[i].constraint.name.ToString() }, reader.BaseURI, ks.PosLine, ks.PosCol)); } } } } }
private void EndElementIdentityConstraints() { for (int i = this.validationStack.Length - 1; i >= this.startIDConstraint; i--) { if (((ValidationState)this.validationStack[i]).Constr != null) { ConstraintStruct[] structArray = ((ValidationState)this.validationStack[i]).Constr; for (int j = 0; j < structArray.Length; j++) { KeySequence sequence; for (int k = 0; k < structArray[j].axisFields.Count; k++) { LocatedActiveAxis axis = (LocatedActiveAxis)structArray[j].axisFields[k]; if (axis.isMatched) { axis.isMatched = false; if (axis.Ks[axis.Column] != null) { base.SendValidationEvent("Sch_FieldSingleValueExpected", base.reader.LocalName); } else { string svalue = !base.hasSibling ? base.textString : base.textValue.ToString(); if ((base.reader.TypedValueObject != null) && (svalue.Length != 0)) { axis.Ks[axis.Column] = new TypedObject(base.reader.TypedValueObject, svalue, base.context.ElementDecl.Datatype); } } } axis.EndElement(base.reader.LocalName, base.reader.NamespaceURI); } if (structArray[j].axisSelector.EndElement(base.reader.LocalName, base.reader.NamespaceURI)) { sequence = structArray[j].axisSelector.PopKS(); switch (structArray[j].constraint.Role) { case CompiledIdentityConstraint.ConstraintRole.Unique: if (sequence.IsQualified()) { if (!structArray[j].qualifiedTable.Contains(sequence)) { goto Label_02E0; } base.SendValidationEvent(new XmlSchemaException("Sch_DuplicateKey", new string[] { sequence.ToString(), structArray[j].constraint.name.ToString() }, base.reader.BaseURI, sequence.PosLine, sequence.PosCol)); } break; case CompiledIdentityConstraint.ConstraintRole.Key: if (sequence.IsQualified()) { goto Label_01ED; } base.SendValidationEvent(new XmlSchemaException("Sch_MissingKey", structArray[j].constraint.name.ToString(), base.reader.BaseURI, sequence.PosLine, sequence.PosCol)); break; case CompiledIdentityConstraint.ConstraintRole.Keyref: if (((structArray[j].qualifiedTable != null) && sequence.IsQualified()) && !structArray[j].qualifiedTable.Contains(sequence)) { structArray[j].qualifiedTable.Add(sequence, sequence); } break; } } continue; Label_01ED: if (structArray[j].qualifiedTable.Contains(sequence)) { base.SendValidationEvent(new XmlSchemaException("Sch_DuplicateKey", new string[] { sequence.ToString(), structArray[j].constraint.name.ToString() }, base.reader.BaseURI, sequence.PosLine, sequence.PosCol)); } else { structArray[j].qualifiedTable.Add(sequence, sequence); } continue; Label_02E0: structArray[j].qualifiedTable.Add(sequence, sequence); } } } ConstraintStruct[] constr = ((ValidationState)this.validationStack[this.validationStack.Length - 1]).Constr; if (constr != null) { for (int m = 0; m < constr.Length; m++) { if ((constr[m].constraint.Role != CompiledIdentityConstraint.ConstraintRole.Keyref) && (constr[m].keyrefTable != null)) { foreach (KeySequence sequence2 in constr[m].keyrefTable.Keys) { if (!constr[m].qualifiedTable.Contains(sequence2)) { base.SendValidationEvent(new XmlSchemaException("Sch_UnresolvedKeyref", sequence2.ToString(), base.reader.BaseURI, sequence2.PosLine, sequence2.PosCol)); } } } } } }