internal static void Validate(ValidationContext validationContext)
            {
                var element = (OpenXmlCompositeElement)validationContext.Element;
                ValidationErrorInfo errorInfo;

                foreach (var child in element.ChildElements)
                {
                    if (!(child is OpenXmlMiscNode))
                    {
                        errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_InvalidChildinLeafElement", element.XmlQualifiedName.ToString());
                        validationContext.EmitError(errorInfo);
                        return; // just return one error is enough.
                    }
                }
            }
        internal static void ValidateValue(ValidationContext validationContext, SimpleTypeRestriction simpleTypeConstraint,
                                                                       OpenXmlSimpleType value, string qname, bool isAttribute)
        {
            var element = validationContext.Element;
            string errorMessageResourceId;
            ValidationErrorInfo errorInfo;
            string subMessage;

            // special case, the type is different in Office2007 and Office2010.
            var redirectRestriction = simpleTypeConstraint as RedirectedRestriction;
            if (redirectRestriction != null)
            {
                var targetValue = redirectRestriction.ConvertValue(value);
                ValidateValue(validationContext, redirectRestriction.TargetRestriction, targetValue, qname, isAttribute);
                return;
            }

            if (isAttribute)
            {
                errorMessageResourceId = "Sch_AttributeValueDataTypeDetailed";
            }
            else
            {
                errorMessageResourceId = "Sch_ElementValueDataTypeDetailed";
            }

            // first, check whether the string is valid accoding the primitive type
            if (!simpleTypeConstraint.ValidateValueType(value))
            {
                if (simpleTypeConstraint.IsEnum)
                {
                    // enum is wrong
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, ValidationResources.Sch_EnumerationConstraintFailed);
                    errorInfo.SetDebugField(isAttribute? qname : null, "Sch_EnumerationConstraintFailed");
                }
                else if (simpleTypeConstraint.XsdType == XsdType.Union)
                {
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, isAttribute ? "Sch_AttributeUnionFailedEx" : "Sch_ElementUnionFailedEx", qname, value.InnerText);
                    errorInfo.SetDebugField(isAttribute? qname : null, null);
                }
                else if (string.IsNullOrEmpty(value.InnerText))
                {
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, isAttribute ? ValidationResources.Sch_EmptyAttributeValue : ValidationResources.Sch_EmptyElementValue);
                    errorInfo.SetDebugField(isAttribute? qname : null, isAttribute ? "Sch_EmptyAttributeValue" : "Sch_EmptyElementValue");
                }
                else if (simpleTypeConstraint.XsdType == XsdType.SpecialBoolean)
                {
                    // special boolean is ST_OnOff which is enum in the schema.
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, ValidationResources.Sch_EnumerationConstraintFailed);
                    errorInfo.SetDebugField(isAttribute ? qname : null, "Sch_EnumerationConstraintFailed");
                }
                else if (simpleTypeConstraint.IsList)
                {
                    // List
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, string.Empty);
                    errorInfo.SetDebugField(isAttribute? qname : null, null);
                }
                else
                {
                    subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_StringIsNotValidValue, value.InnerText, simpleTypeConstraint.ClrTypeName);
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                    errorInfo.SetDebugField(isAttribute? qname : null, "Sch_StringIsNotValidValue");
                }
                validationContext.EmitError(errorInfo);
            }
            else
            {
                bool validateConstraints = true;

                switch (simpleTypeConstraint.XsdType)
                {
                    case XsdType.Enum:
                    case XsdType.Boolean:
                    case XsdType.DateTime:
                    case XsdType.SpecialBoolean:
                        Debug.Assert(simpleTypeConstraint.Pattern == null);
                        Debug.Assert(simpleTypeConstraint.RestrictionField == RestrictionField.None);

                        // no other facets.
                        validateConstraints = false;
                        break;

                    case XsdType.NonNegativeInteger:
                    case XsdType.PositiveInteger:
                    case XsdType.Byte:
                    case XsdType.UnsignedByte:
                    case XsdType.Short:
                    case XsdType.UnsignedShort:
                    case XsdType.Int:
                    case XsdType.UnsignedInt:
                    case XsdType.Long:
                    case XsdType.UnsignedLong:
                    case XsdType.Float:
                    case XsdType.Double:
                    case XsdType.Decimal:
                    case XsdType.Integer: // TODO: integer should be decimal, while in current the CodeGen generate Int32 instead.
                        Debug.Assert(simpleTypeConstraint.Pattern == null);
                        Debug.Assert((simpleTypeConstraint.RestrictionField & RestrictionField.LengthRestriction) == RestrictionField.None);
                        break;

                    case XsdType.String:
                    case XsdType.Token:
                    case XsdType.HexBinary:
                    case XsdType.Base64Binary:
                    case XsdType.AnyURI:
                    case XsdType.QName:
                    case XsdType.ID:                        // no pattern defined for numeric type in Ecma376
                    case XsdType.NCName:
                    case XsdType.IDREF:
                    case XsdType.Language:
                        Debug.Assert((simpleTypeConstraint.RestrictionField & RestrictionField.MinMaxRestriction) == RestrictionField.None);
                        break;

                    case XsdType.List:
                        Debug.Assert(simpleTypeConstraint.Pattern == null);
                        Debug.Assert(simpleTypeConstraint.RestrictionField == RestrictionField.None);

                        // no other facets in current Ecma376.
                        validateConstraints = false;

                        break;

                    case XsdType.Union:
                        Debug.Assert(simpleTypeConstraint.Pattern == null);
                        Debug.Assert(simpleTypeConstraint.RestrictionField == RestrictionField.None);

                        // no other facets.
                        validateConstraints = false;
                        break;

                    default:
                        Debug.Assert(false);
                        break;
                }

                if (validateConstraints)
                {
                    var errorRestriction = simpleTypeConstraint.Validate(value);
                    if (errorRestriction != RestrictionField.None)
                    {
                        if ((errorRestriction & RestrictionField.MinInclusive) == RestrictionField.MinInclusive)
                        {
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MinInclusiveConstraintFailed, simpleTypeConstraint.GetRestrictionValue(RestrictionField.MinInclusive));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MinInclusiveConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }

                        if ((errorRestriction & RestrictionField.MinExclusive) == RestrictionField.MinExclusive)
                        {
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MinExclusiveConstraintFailed, simpleTypeConstraint.GetRestrictionValue(RestrictionField.MinExclusive));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MinExclusiveConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }

                        if ((errorRestriction & RestrictionField.MaxInclusive) == RestrictionField.MaxInclusive)
                        {
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MaxInclusiveConstraintFailed, simpleTypeConstraint.GetRestrictionValue(RestrictionField.MaxInclusive));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MaxInclusiveConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }

                        if ((errorRestriction & RestrictionField.MaxExclusive) == RestrictionField.MaxExclusive)
                        {
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MaxExclusiveConstraintFailed, simpleTypeConstraint.GetRestrictionValue(RestrictionField.MaxExclusive));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MaxExclusiveConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }
                        if ((errorRestriction & RestrictionField.Length) == RestrictionField.Length)
                        {
                            // length is not ok.
                            if (string.IsNullOrEmpty(value.InnerText))
                            {
                                errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, isAttribute ? ValidationResources.Sch_EmptyAttributeValue : ValidationResources.Sch_EmptyElementValue);
                                errorInfo.SetDebugField(isAttribute? qname : null, isAttribute ? "Sch_EmptyAttributeValue" : "Sch_EmptyElementValue");
                                validationContext.EmitError(errorInfo);
                            }
                            else
                            {
                                subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_LengthConstraintFailed, simpleTypeConstraint.XsdType.GetXsdDataTypeName(), simpleTypeConstraint.GetRestrictionValue(RestrictionField.Length));
                                errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                                errorInfo.SetDebugField(isAttribute? qname : null, "Sch_LengthConstraintFailed");
                                validationContext.EmitError(errorInfo);
                            }
                        }

                        if ((errorRestriction & RestrictionField.MinLength) == RestrictionField.MinLength)
                        {
                            // min length is not ok.
                            if (string.IsNullOrEmpty(value.InnerText))
                            {
                                errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, isAttribute ? ValidationResources.Sch_EmptyAttributeValue : ValidationResources.Sch_EmptyElementValue);
                                errorInfo.SetDebugField(isAttribute? qname : null, isAttribute ? "Sch_EmptyAttributeValue" : "Sch_EmptyElementValue");
                                validationContext.EmitError(errorInfo);
                            }
                            else
                            {
                                subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MinLengthConstraintFailed, simpleTypeConstraint.XsdType.GetXsdDataTypeName(), simpleTypeConstraint.GetRestrictionValue(RestrictionField.MinLength));
                                errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                                errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MinLengthConstraintFailed");
                                validationContext.EmitError(errorInfo);
                            }
                        }

                        if ((errorRestriction & RestrictionField.MaxLength) == RestrictionField.MaxLength)
                        {
                            // max length is not ok.
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_MaxLengthConstraintFailed, simpleTypeConstraint.XsdType.GetXsdDataTypeName(), simpleTypeConstraint.GetRestrictionValue(RestrictionField.MaxLength));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_MaxLengthConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }

                        if ((errorRestriction & RestrictionField.Pattern) == RestrictionField.Pattern)
                        {
                            // pattern is not ok.
                            subMessage = string.Format(CultureInfo.CurrentUICulture, ValidationResources.Sch_PatternConstraintFailed, simpleTypeConstraint.GetRestrictionValue(RestrictionField.Pattern));
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, errorMessageResourceId, qname, value.InnerText, subMessage);
                            errorInfo.SetDebugField(isAttribute? qname : null, "Sch_PatternConstraintFailed");
                            validationContext.EmitError(errorInfo);
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Validate the attributes constraint.
        /// </summary>
        /// <param name="validationContext">The validation context.</param>
        /// <param name="schemaTypeData">The constraint data of the schema type.</param>
        private static void ValidateAttributes(ValidationContext validationContext, SchemaTypeData schemaTypeData)
        {
            var element = validationContext.Element;

            Debug.Assert( element.Attributes == null && schemaTypeData.AttributeConstraintsCount == 0 ||
                          element.Attributes.Length == schemaTypeData.AttributeConstraintsCount );

            ValidationErrorInfo errorInfo;

            // validate xsd:use on attributes
            for (int i = 0; i < schemaTypeData.AttributeConstraintsCount; i++)
            {
                var attributeConstraint = schemaTypeData.AttributeConstraints[i];

                if (attributeConstraint.SupportedVersion.Includes(validationContext.FileFormat))
                {
                    // only check the attribute constraints defined in the specified file format version.

                    switch (attributeConstraint.XsdAttributeUse)
                    {
                        case XsdAttributeUse.Required:
                            if (element.Attributes[i] == null)
                            {
                                string attributeQname = element.GetFixedAttributeQname(i).ToString();
                                // error: miss required attribute
                                errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_MissRequiredAttribute", attributeQname);
                                errorInfo.SetDebugField(attributeQname, "Sch_MissRequiredAttribute");
                                validationContext.EmitError(errorInfo);
                            }
                            break;

                        case XsdAttributeUse.None: // none, so use default "optional"
                        case XsdAttributeUse.Optional:
                            break;

                        case XsdAttributeUse.Prohibited: // no "prohibited" in Ecma at now.
                        default:
                            Debug.Assert(false);
                            break;
                    }

                    if (element.Attributes[i] != null)
                    {
                        OpenXmlSimpleType attributeValue = element.Attributes[i];

                        string attributeQname = element.GetFixedAttributeQname(i).ToString();

                        ValidateValue(validationContext, attributeConstraint.SimpleTypeConstraint, attributeValue, attributeQname, true);
                    }
                }
                else
                {
                    if (element.Attributes[i] != null)
                    {
                        // The attribute is not defined in the specified version, report error.
                        if (validationContext.McContext.IsIgnorableNs(element.AttributeNamespaceIds[i]))
                        {
                            // Ignorable attribute, no error.
                        }
                        else
                        {
                            // emit error
                            string attributeQname = element.GetFixedAttributeQname(i).ToString(); ;
                            errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_UndeclaredAttribute", attributeQname);
                            errorInfo.SetDebugField(attributeQname, "Sch_UndeclaredAttribute");
                            validationContext.EmitError(errorInfo);
                        }
                    }
                }
            }

            // all unknown attributes (attributes not defined in schema) are in ExtendedAttributes.
            // they should be errors 
            foreach (var extendedAttribute in element.ExtendedAttributes)
            {
                if (validationContext.McContext.IsIgnorableNs(extendedAttribute.NamespaceUri))
                {
                    // Ignorable attribute, no error.
                }
                // xml:space is always allowed
                else if ("http://www.w3.org/XML/1998/namespace" == extendedAttribute.NamespaceUri)
                {
                }
                else
                {
                    // emit error
                    string attributeQname = extendedAttribute.XmlQualifiedName.ToString();
                    errorInfo = validationContext.ComposeSchemaValidationError(element, null, "Sch_UndeclaredAttribute", attributeQname);
                    errorInfo.SetDebugField(attributeQname, "Sch_UndeclaredAttribute");
                    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;
            }
        }
        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);
        }
        /// <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;
        }