protected virtual void EmitInvalidElementError(ValidationContext validationContext, ParticleMatchInfo particleMatchInfo) { OpenXmlElement child; // re-validate the element, collect the expected children information if (particleMatchInfo.Match != ParticleMatch.Nomatch) { #if DEBUG var oldParticleMatchInfo = particleMatchInfo; particleMatchInfo = new ParticleMatchInfo(); #endif child = validationContext.GetFirstChildMc(); validationContext.CollectExpectedChildren = true; particleMatchInfo.Reset(child); particleMatchInfo.InitExpectedChildren(); this.TryMatch(particleMatchInfo, validationContext); validationContext.CollectExpectedChildren = false; #if DEBUG Debug.Assert(particleMatchInfo.Match == oldParticleMatchInfo.Match); Debug.Assert(particleMatchInfo.LastMatchedElement == oldParticleMatchInfo.LastMatchedElement); #endif } var element = validationContext.Element; if (particleMatchInfo.LastMatchedElement == null) { child = validationContext.GetFirstChildMc(); } else { child = validationContext.GetNextChildMc(particleMatchInfo.LastMatchedElement); } ValidationErrorInfo errorInfo; string expectedChildren = null; switch (particleMatchInfo.Match) { case ParticleMatch.Nomatch: expectedChildren = GetExpectedChildrenMessage(validationContext.Element, this.GetExpectedElements()); break; case ParticleMatch.Partial: // error: the child can not be matched, it is invalid if (child == null) { // missing child errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_IncompleteContentExpectingComplex", GetExpectedChildrenMessage(element, particleMatchInfo.ExpectedChildren)); validationContext.EmitError(errorInfo); return; } else { expectedChildren = GetExpectedChildrenMessage(validationContext.Element, particleMatchInfo.ExpectedChildren); } break; case ParticleMatch.Matched: if (this.ParticleConstraint.CanOccursMoreThanOne) { expectedChildren = GetExpectedChildrenMessage(validationContext.Element, this.GetExpectedElements()); } else { expectedChildren = GetExpectedChildrenMessage(validationContext.Element, particleMatchInfo.ExpectedChildren); } break; } if (validationContext.Element.CanContainsChild(child)) { // The child can be contained in the parent, but not follow the schema. errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_UnexpectedElementContentExpectingComplex", child.XmlQualifiedName.ToString(), expectedChildren); } else { //Fix bug #448264, specifal case: same element name, but wrong type. Only occurs when validating memory DOM. var validElement = element.TryCreateValidChild(validationContext.FileFormat, child.NamespaceUri, child.LocalName); if (validElement == null) { errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_InvalidElementContentExpectingComplex", child.XmlQualifiedName.ToString(), expectedChildren); } else { // parent can contains a different type of element with same name errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_InvalidElementContentWrongType", child.XmlQualifiedName.ToString(), child.GetType().Name); } } validationContext.EmitError(errorInfo); }
protected override void EmitInvalidElementError(ValidationContext validationContext, ParticleMatchInfo particleMatchInfo) { var element = validationContext.Element; OpenXmlElement child; if (particleMatchInfo.LastMatchedElement == null) { child = validationContext.GetFirstChildMc(); } else { child = validationContext.GetNextChildMc(particleMatchInfo.LastMatchedElement); } string expectedChildren; ValidationErrorInfo errorInfo; switch (particleMatchInfo.Match) { case ParticleMatch.Nomatch: expectedChildren = GetExpectedChildrenMessage(validationContext.Element, this.GetExpectedElements()); errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_InvalidElementContentExpectingComplex", child.XmlQualifiedName.ToString(), expectedChildren); validationContext.EmitError(errorInfo); break; case ParticleMatch.Partial: case ParticleMatch.Matched: if (this._childrenParticles.ContainsKey(child.ElementTypeId)) { // more than one occurs of a child. errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_AllElement", child.XmlQualifiedName.ToString()); validationContext.EmitError(errorInfo); } else { expectedChildren = GetExpectedChildrenMessage(validationContext.Element, particleMatchInfo.ExpectedChildren); errorInfo = validationContext.ComposeSchemaValidationError(element, child, "Sch_InvalidElementContentExpectingComplex", child.XmlQualifiedName.ToString(), expectedChildren); validationContext.EmitError(errorInfo); } break; } }
/// <summary> /// Be called on root particle of complex type. /// </summary> /// <param name="validationContext"></param> /// <returns></returns> internal override void Validate(ValidationContext validationContext) { Debug.Assert(validationContext != null); OpenXmlCompositeElement element = validationContext.Element as OpenXmlCompositeElement; Debug.Assert(element != null); var child = validationContext.GetFirstChildMc(); ValidationErrorInfo errorInfo; // no children if (child == null) { if (this.ParticleConstraint.MinOccurs == 0) { // no child, ok return; } else { var requiredElements = this.GetRequiredElements(); if ( requiredElements.Count > 0 ) { errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_IncompleteContentExpectingComplex", GetExpectedChildrenMessage(element, requiredElements)); validationContext.EmitError(errorInfo); } return; } } if (this._particleMatchInfo == null) { this._particleMatchInfo = new ParticleMatchInfo(child); } else { _particleMatchInfo.Reset(child); } this.TryMatch(_particleMatchInfo, validationContext); switch (_particleMatchInfo.Match) { case ParticleMatch.Nomatch: // error: can not be matched, it is invalid EmitInvalidElementError(validationContext, _particleMatchInfo); return; case ParticleMatch.Partial: EmitInvalidElementError(validationContext, _particleMatchInfo); return; case ParticleMatch.Matched: Debug.Assert(_particleMatchInfo.LastMatchedElement != null); child = validationContext.GetNextChildMc(_particleMatchInfo.LastMatchedElement); { // Two cases now. // 1. All children be matched. // 2. Too many children ( > maxOccurs ). if (child != null) { // invalid child EmitInvalidElementError(validationContext, _particleMatchInfo); // TODO: how can we tell the user what is the required child? Use reflection in OpenXmlElement. } else { //Debug.Assert(result.Valid == true); } } break; } return; }