Ejemplo n.º 1
0
        /// <summary>
        /// Validate the DOM tree under the specified OpenXmlElement.
        /// </summary>
        /// <param name="schemaValidator">The schemaValidator.</param>
        /// <param name="openxmlElement">The root of the sub tree.</param>
        /// <returns>Returns the validation result in ValidationResult.</returns>
        /// <remarks>
        /// Only schema validating.
        /// </remarks>
        internal static ValidationResult Validate(this SchemaValidator schemaValidator, OpenXmlElement openxmlElement)
        {
            Debug.Assert(openxmlElement != null);

            var validationResult = new ValidationResult();

            Debug.Assert(!(openxmlElement is OpenXmlUnknownElement || openxmlElement is OpenXmlMiscNode));

            // Can not just validate AlternateContent / Choice / Fallback
            // Debug.Assert(!(openxmlElement is AlternateContent))
            Debug.Assert(!(openxmlElement is AlternateContentChoice || openxmlElement is AlternateContentFallback));

            var validationContext = new ValidationContext();
            validationContext.ValidationErrorEventHandler += validationResult.OnValidationError;

            validationContext.Element = openxmlElement;

            schemaValidator.Validate(validationContext);

            return validationResult;
        }
        private void TestSimpleSequence4(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;
            ColorTransformCategories categories = new ColorTransformCategories();
            var expected = categories;
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(categories).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as SequenceParticleValidator;
            validationContext.Element = categories;

              //<xsd:complexType name="CT_CTCategories">
              //  <xsd:sequence minOccurs="0" maxOccurs="unbounded">
              //    <xsd:element name="cat" type="CT_CTCategory" minOccurs="0" maxOccurs="unbounded">
              //  </xsd:sequence>
              //</xsd:complexType>

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            categories.AppendChild(new ColorTransformCategory());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            categories.AppendChild(new ColorTransformCategory());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            categories.AppendChild(new ColorTransformCategory());
            target.Validate(validationContext);
            Assert.True(actual.Valid);


            // ***** error case ******

            // 1st child is invalid
            errorChild = categories.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":cat"));

            actual.Clear();
            // last child is invalid
            categories.RemoveChild(errorChild);
            errorChild = categories.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":cat"));

            actual.Clear();
            // 2nd child is invalid
            categories.RemoveChild(errorChild);
            errorChild = categories.InsertAfter(new Paragraph(), categories.FirstChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":cat"));

            actual.Clear();
            // 3rd child is invalid
            categories.RemoveChild(errorChild);
            errorChild = categories.InsertBefore(new Paragraph(), categories.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":cat"));

            actual.Clear();
            // only one invalid child
            categories.RemoveAllChildren();
            errorChild = categories.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":cat"));
        }
        private void TestSimpleSequence(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;

            //<xsd:complexType name="CT_FFDDList">
            //  <xsd:sequence>
            //    <xsd:element name="result" type="CT_DecimalNumber" minOccurs="0">
            //    <xsd:element name="default" type="CT_DecimalNumber" minOccurs="0">
            //    <xsd:element name="listEntry" type="CT_String" minOccurs="0" maxOccurs="unbounded">
            //  </xsd:sequence>
            //</xsd:complexType>
            DropDownListFormField ddList = new DropDownListFormField();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(ddList).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as SequenceParticleValidator;

            validationContext.Element = ddList;

            // ***** good case ******
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            ddList.AppendChild(new DropDownListSelection());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            ddList.AppendChild(new DefaultDropDownListItemIndex());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            ddList.AppendChild(new ListEntryFormField());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            ddList.AppendChild(new ListEntryFormField());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******
            ddList = new DropDownListFormField();
            validationContext.Element = ddList;
            var expected = ddList;

            // invalid child
            OpenXmlElement errorChild = ddList.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":result"));

            actual.Clear();
            // 2nd child is invalid
            ddList.PrependChild(new DropDownListSelection());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // the sequence of the first 2 children are wrong
            errorChild = ddList.FirstChild;
            ddList.PrependChild(new DefaultDropDownListItemIndex());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // 1st and 2nd are same type, maxOccurs error
            errorChild = ddList.FirstChild;
            ddList.PrependChild(new DefaultDropDownListItemIndex());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // the 2nd and 3rd are same type, maxOccurs error
            ddList.PrependChild(new DropDownListSelection());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // expectedNode are now the 4th, the first 3 are OK.
            ddList.InsertAfter(new ListEntryFormField(), errorChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
        }
        private void TestSimpleSequence2(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            Ruby ruby = new Ruby();
            OpenXmlElement errorChild;

            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(ruby).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as SequenceParticleValidator;
            validationContext.Element = ruby;
            var expected = ruby;
            //<xsd:complexType name="CT_Ruby">
            //  <xsd:sequence>
            //    <xsd:element name="rubyPr" type="CT_RubyPr">
            //    <xsd:element name="rt" type="CT_RubyContent">
            //    <xsd:element name="rubyBase" type="CT_RubyContent">
            //  </xsd:sequence>
            //</xsd:complexType>}

            // ***** good case ******
            ruby.Append(new RubyProperties(), new RubyContent(), new RubyBase());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // No RubyBase child, incomplete error
            ruby.RemoveChild(ruby.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_IncompleteContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rubyBase"));

            actual.Clear();
            // No RubyContent child, incomplete error
            ruby.RemoveChild(ruby.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_IncompleteContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rt"));

            actual.Clear();
            // Empty, incomplete error
            ruby.RemoveChild(ruby.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_IncompleteContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rubyPr"));

            actual.Clear();
            // No RubyContent child, incomplete error
            ruby.Append(new RubyProperties(), new RubyBase());
            errorChild = ruby.LastChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rt"));

            actual.Clear();
            // No RubyProperties child, incomplete error
            ruby.RemoveAllChildren();
            ruby.Append(new RubyContent(), new RubyBase());
            errorChild = ruby.FirstChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rubyPr"));

            actual.Clear();
            // first should be RubyProperties()
            ruby.PrependChild(new RubyContent());
            errorChild = ruby.FirstChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rubyPr"));

            actual.Clear();
            // 2nd and 3rd are same element, error
            errorChild = ruby.FirstChild.NextSibling();
            ruby.PrependChild(new RubyProperties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rt"));
        }
        private void ValidatePpr(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            ParagraphProperties pPr = new ParagraphProperties();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(pPr).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ParticleValidator;
            validationContext.Element = pPr;
            var expected = pPr;

              //<xsd:complexType name="CT_PPr">
              //  <xsd:complexContent>
              //    <xsd:extension base="CT_PPrBase">
              //      <xsd:sequence>
              //        <xsd:element name="rPr" type="CT_ParaRPr" minOccurs="0">
              //        <xsd:element name="sectPr" type="CT_SectPr" minOccurs="0">
              //        <xsd:element name="pPrChange" type="CT_PPrChange" minOccurs="0">
              //      </xsd:sequence>
              //    </xsd:extension>
              //  </xsd:complexContent>
              //</xsd:complexType>

              //<xsd:complexType name="CT_PPrBase">
              //  <xsd:sequence>
              //    <xsd:element name="pStyle" type="CT_String" minOccurs="0">
              //    <xsd:element name="keepNext" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="keepLines" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="pageBreakBefore" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="framePr" type="CT_FramePr" minOccurs="0">
              //    <xsd:element name="widowControl" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="numPr" type="CT_NumPr" minOccurs="0">
              //    <xsd:element name="suppressLineNumbers" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="pBdr" type="CT_PBdr" minOccurs="0">
              //    <xsd:element name="shd" type="CT_Shd" minOccurs="0">
              //    <xsd:element name="tabs" type="CT_Tabs" minOccurs="0">
              //    <xsd:element name="suppressAutoHyphens" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="kinsoku" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="wordWrap" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="overflowPunct" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="topLinePunct" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="autoSpaceDE" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="autoSpaceDN" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="bidi" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="adjustRightInd" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="snapToGrid" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="spacing" type="CT_Spacing" minOccurs="0">
              //    <xsd:element name="ind" type="CT_Ind" minOccurs="0">
              //    <xsd:element name="contextualSpacing" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="mirrorIndents" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="suppressOverlap" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="jc" type="CT_Jc" minOccurs="0">
              //    <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0">
              //    <xsd:element name="textAlignment" type="CT_TextAlignment" minOccurs="0">
              //    <xsd:element name="textboxTightWrap" type="CT_TextboxTightWrap" minOccurs="0">
              //    <xsd:element name="outlineLvl" type="CT_DecimalNumber" minOccurs="0">
              //    <xsd:element name="divId" type="CT_DecimalNumber" minOccurs="0">
              //    <xsd:element name="cnfStyle" type="CT_Cnf" minOccurs="0" maxOccurs="1">
              //  </xsd:sequence>
              //</xsd:complexType>

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new KeepLines());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new Tabs());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new Kinsoku());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new OutlineLevel());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new ConditionalFormatStyle());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new ParagraphMarkRunProperties());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            pPr.AppendChild(new ParagraphPropertiesChange());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // SectionProperties dup error
            errorChild = pPr.AppendChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            pPr.RemoveChild(errorChild);

            actual.Clear();
            // SectionProperties order wrong
            errorChild = pPr.FirstChild;
            pPr.PrependChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            pPr.RemoveChild(pPr.FirstChild);

        }
        private void ValidateBlip(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            Drawing.Blip blip = new Drawing.Blip();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(blip).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ParticleValidator;
            validationContext.Element = blip;
            var expected = blip;

            //<xsd:complexType name="CT_Blip">
            //  <xsd:sequence>
            //    <xsd:choice minOccurs="0" maxOccurs="unbounded">
            //      <xsd:element name="alphaBiLevel" type="CT_AlphaBiLevelEffect" minOccurs="1" maxOccurs="1">
            //      <xsd:element name="alphaCeiling" type="CT_AlphaCeilingEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="alphaFloor" type="CT_AlphaFloorEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="alphaInv" type="CT_AlphaInverseEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="alphaMod" type="CT_AlphaModulateEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="alphaModFix" type="CT_AlphaModulateFixedEffect" minOccurs="1" maxOccurs="1">
            //      <xsd:element name="alphaRepl" type="CT_AlphaReplaceEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="biLevel" type="CT_BiLevelEffect" minOccurs="1" maxOccurs="1">
            //      <xsd:element name="blur" type="CT_BlurEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="clrChange" type="CT_ColorChangeEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="clrRepl" type="CT_ColorReplaceEffect" minOccurs="1" maxOccurs="1">
            //      <xsd:element name="duotone" type="CT_DuotoneEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="fillOverlay" type="CT_FillOverlayEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="grayscl" type="CT_GrayscaleEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="hsl" type="CT_HSLEffect" minOccurs="1" maxOccurs="1" />
            //      <xsd:element name="lum" type="CT_LuminanceEffect" minOccurs="1" maxOccurs="1">
            //      <xsd:element name="tint" type="CT_TintEffect" minOccurs="1" maxOccurs="1">
            //    </xsd:choice>
            //    <xsd:element name="extLst" type="CT_OfficeArtExtensionList" minOccurs="0" maxOccurs="1"></xsd:element>
            //  </xsd:sequence>
            //  <xsd:attributeGroup ref="AG_Blob"></xsd:attributeGroup>
            //  <xsd:attribute name="cstate" type="ST_BlipCompression" use="optional" default="none">
            //</xsd:complexType>
            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            blip.AppendChild(new Drawing.LuminanceEffect());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            blip.AppendChild(new Drawing.LuminanceEffect());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            blip.AppendChild(new Drawing.AlphaBiLevel());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            blip.AppendChild(new Drawing.Blur());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            blip.AppendChild(new Drawing.BiLevel());
            target.Validate(validationContext);
            Assert.True(actual.Valid);
            
            blip.AppendChild(new Drawing.BlipExtensionList());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******
            // ExtensionList can not be the first
            errorChild = blip.FirstChild;
            blip.PrependChild(new Drawing.BlipExtensionList());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            blip.RemoveChild(blip.FirstChild);

            actual.Clear();
            // can only have one ExtensionList at last
            errorChild = blip.AppendChild(new Drawing.BlipExtensionList());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            blip.RemoveChild(errorChild);
        }
        private void TestSimpleAll(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            Properties properties = new Properties();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(properties).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as AllParticleValidator;
            validationContext.Element = properties;
            var expected = properties;

            //<xsd:complexType name="CT_Properties">
            //  <xsd:all>
            //    <xsd:element name="Template" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="Manager" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="Company" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="Pages" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="Words" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="Characters" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="PresentationFormat" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="Lines" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="Paragraphs" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="Slides" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="Notes" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="TotalTime" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="HiddenSlides" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="MMClips" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="ScaleCrop" minOccurs="0" maxOccurs="1" type="xsd:boolean">
            //    <xsd:element name="HeadingPairs" minOccurs="0" maxOccurs="1" type="CT_VectorVariant">
            //    <xsd:element name="TitlesOfParts" minOccurs="0" maxOccurs="1" type="CT_VectorLpstr">
            //    <xsd:element name="LinksUpToDate" minOccurs="0" maxOccurs="1" type="xsd:boolean">
            //    <xsd:element name="CharactersWithSpaces" minOccurs="0" maxOccurs="1" type="xsd:int">
            //    <xsd:element name="SharedDoc" minOccurs="0" maxOccurs="1" type="xsd:boolean">
            //    <xsd:element name="HyperlinkBase" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="HLinks" minOccurs="0" maxOccurs="1" type="CT_VectorVariant">
            //    <xsd:element name="HyperlinksChanged" minOccurs="0" maxOccurs="1" type="xsd:boolean">
            //    <xsd:element name="DigSig" minOccurs="0" maxOccurs="1" type="CT_DigSigBlob">
            //    <xsd:element name="Application" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="AppVersion" minOccurs="0" maxOccurs="1" type="xsd:string">
            //    <xsd:element name="DocSecurity" minOccurs="0" maxOccurs="1" type="xsd:int">
            //  </xsd:all>
            //</xsd:complexType> 

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any one is ok
            properties.AppendChild(new Company());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any order is ok
            properties.AppendChild(new Template());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any order is ok
            properties.AppendChild(new DocumentSecurity());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any order is ok
            properties.AppendChild(new HyperlinkBase());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // first is invlaid
            errorChild = properties.PrependChild(new Properties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":Template"));
            Assert.True(actual.Errors[0].Description.Contains(":DocSecurity"));
            properties.RemoveChild(errorChild);

            actual.Clear();
            //invalid child in middle
            errorChild = properties.InsertBefore(new Properties(), properties.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(":Template"));
            Assert.True(actual.Errors[0].Description.Contains(":AppVersion"));
            properties.RemoveChild(errorChild);

            actual.Clear();
            // dup 
            errorChild = properties.FirstChild;
            properties.PrependChild(new Company());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_AllElement", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            properties.RemoveChild(errorChild);

        }
        private void TestSimpleChoice2(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            BuildSubElement bldSub = new BuildSubElement();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(bldSub).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ChoiceParticleValidator;
            validationContext.Element = bldSub;
            var expected = bldSub;
            
              //<xsd:complexType name="CT_AnimationGraphicalObjectBuildProperties">
              //  <xsd:choice>
              //    <xsd:element name="bldDgm" type="CT_AnimationDgmBuildProperties">
              //    <xsd:element name="bldChart" type="CT_AnimationChartBuildProperties">
              //  </xsd:choice>
              //</xsd:complexType>

            // ***** good case ******
            bldSub.AppendChild(new Drawing.BuildChart());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            bldSub.RemoveAllChildren();
            bldSub.AppendChild(new Drawing.BuildDiagram());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // empty
            bldSub.RemoveAllChildren();
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_IncompleteContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":bldDgm"));
            Assert.True(actual.Errors[0].Description.Contains(":bldChart"));

            actual.Clear();
            // both element are exist
            bldSub.Append(new Drawing.BuildChart(), new Drawing.BuildDiagram());
            errorChild = bldSub.LastChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            //first is invalid
            errorChild = bldSub.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":bldDgm"));
            Assert.True(actual.Errors[0].Description.Contains(":bldChart"));

        }
        private void TestSimpleChoice(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            FieldChar fldChar = new FieldChar();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(fldChar).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ChoiceParticleValidator;
            validationContext.Element = fldChar;
            var expected = fldChar;

              //<xsd:complexType name="CT_FldChar">
              //  <xsd:choice>
              //    <xsd:element name="fldData" type="CT_Text" minOccurs="0" maxOccurs="1">
              //    <xsd:element name="ffData" type="CT_FFData" minOccurs="0" maxOccurs="1">
              //    <xsd:element name="numberingChange" type="CT_TrackChangeNumbering" minOccurs="0">
              //  </xsd:choice>
              //</xsd:complexType>

            // ***** good case ******
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            fldChar.AppendChild(new FieldData());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            fldChar.RemoveAllChildren();
            fldChar.AppendChild(new FormFieldData());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            fldChar.RemoveAllChildren();
            fldChar.AppendChild(new NumberingChange() );
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // 1st is invalid
            errorChild = fldChar.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":fldData"));
            Assert.True(actual.Errors[0].Description.Contains(":ffData"));
            Assert.True(actual.Errors[0].Description.Contains(":numberingChange"));

            actual.Clear();
            // second is invalid
            fldChar.RemoveChild(errorChild);
            errorChild = fldChar.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            
            actual.Clear();
            // dup first child
            fldChar.RemoveAllChildren();
            fldChar.Append(new FieldData(), new FieldData());
            errorChild = fldChar.LastChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // two different 
            fldChar.RemoveAllChildren();
            fldChar.Append(new FieldData(), new FormFieldData());
            errorChild = fldChar.LastChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // two different 
            fldChar.RemoveAllChildren();
            fldChar.Append(new FormFieldData(), new FieldData());
            errorChild = fldChar.LastChild;
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
        }
        private void TestSimpleGroup(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            Header header = new Header();
            var expected = header;
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(header).ParticleConstraint;

            // the complex type contains a <xsd:group .../> as child
            var target = particleConstraint.ParticleValidator as GroupParticleValidator;
            validationContext.Element = header;

              //<xsd:complexType name="CT_HdrFtr">
              //  <xsd:group ref="EG_BlockLevelElts" minOccurs="1" maxOccurs="unbounded" />
              //</xsd:complexType>

              //<xs:group name="EG_BlockLevelElts">
              //  <xs:choice>
              //    <xs:group ref="EG_BlockLevelEltsBase" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_BlockLevelChunkElts" minOccurs="0" maxOccurs="unbounded" />
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_BlockLevelEltsBase">
              //  <xs:choice>
              //    <xs:element name="altChunk" type="CT_AltChunk" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //  </xs:choice>
              //</xs:group>

              //<xsd:group name="EG_BlockLevelChunkElts">
              //  <xsd:choice>
              //    <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded" />
              //  </xsd:choice>
              //</xsd:group>

              //<xs:group name="EG_ContentBlockContent">
              //  <xs:choice>
              //    <xs:group ref="EG_ContentBlockContentBase" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded" />
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_ContentBlockContentBase">
              //  <xs:choice>
              //    <xs:element name="customXml" type="CT_CustomXmlBlock"></xs:element>
              //    <xs:element name="sdt" type="CT_SdtBlock"></xs:element>
              //    <xs:element name="p" type="CT_P" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //    <xs:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //  </xs:choice>
              //</xs:group>


            // ***** good case ******
            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // Paragraph is ok
            header.Append(new Paragraph());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // Table is ok
            header.Append(new Table());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more Paragraph is ok
            header.Append(new Paragraph());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // Sdt is ok
            header.Append(new SdtBlock());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // altChunk is ok
            header.Append(new AltChunk());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // altChunk is ok
            header.Append(new AltChunk());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more Paragraph is ok
            header.Append(new Paragraph());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******
            //first is invalid
            errorChild = header.PrependChild(new Run());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":altChunk"));
            Assert.True(actual.Errors[0].Description.Contains(":tbl"));
            header.RemoveChild(errorChild);

            actual.Clear();
            //last is invalid
            errorChild = header.AppendChild(new Run());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":altChunk"));
            Assert.True(actual.Errors[0].Description.Contains(":tbl"));
            header.RemoveChild(errorChild);
        }
        private void TestSimpleChoice3(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            FormFieldData ffData = new FormFieldData();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(ffData).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ChoiceParticleValidator;
            validationContext.Element = ffData;
            var expected = ffData;
            
            //<xs:complexType name="CT_FFData">
            //  <xs:choice maxOccurs="unbounded">
            //    <xs:element name="name" type="CT_FFName">
            //    <xs:element name="enabled" type="CT_OnOff">
            //    <xs:element name="calcOnExit" type="CT_OnOff">
            //    <xs:element name="entryMacro" type="CT_MacroName" minOccurs="0" maxOccurs="1">
            //    <xs:element name="exitMacro" type="CT_MacroName" minOccurs="0" maxOccurs="1">
            //    <xs:element name="helpText" type="CT_FFHelpText" minOccurs="0" maxOccurs="1">
            //    <xs:element name="statusText" type="CT_FFStatusText" minOccurs="0" maxOccurs="1">
            //    <xs:choice>
            //      <xs:element name="checkBox" type="CT_FFCheckBox">
            //      <xs:element name="ddList" type="CT_FFDDList">
            //      <xs:element name="textInput" type="CT_FFTextInput">
            //    </xs:choice>
            //  </xs:choice>
            //</xs:complexType>

            // ***** good case ******

            // empty is ok, as there are child with minOccurs="0"
            target.Validate(validationContext);
            Assert.True(actual.Valid);
  
            ffData.AppendChild(new FormFieldName());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // dup element
            ffData.AppendChild(new FormFieldName());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            ffData.RemoveAllChildren();
            ffData.AppendChild(new StatusText());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 2 element
            ffData.AppendChild(new HelpText());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // dup element
            ffData.AppendChild(new HelpText());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more element
            ffData.AppendChild(new Enabled());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more element
            ffData.AppendChild(new CheckBox());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more element
            ffData.AppendChild(new TextInput());
            target.Validate(validationContext);
            Assert.True(actual.Valid);
            
            // ***** error case ******
            ffData.RemoveAllChildren();
            ffData.AppendChild(new HelpText());
            ffData.AppendChild(new CheckBox());

            //first is invalid
            errorChild = ffData.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":name"));
            Assert.True(actual.Errors[0].Description.Contains(":textInput"));

            actual.Clear();
            //invalid child in middle
            ffData.RemoveChild(errorChild);
            errorChild = ffData.InsertBefore(new Paragraph(), ffData.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":name"));
            Assert.True(actual.Errors[0].Description.Contains(":textInput"));

            actual.Clear();
            //invalid child in last
            ffData.RemoveChild(errorChild);
            errorChild = ffData.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":name"));
            Assert.True(actual.Errors[0].Description.Contains(":textInput"));
        }
        private void TestSimpleGroup2(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            SectionProperties sectPr = new SectionProperties();
            var expected = sectPr;
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(sectPr).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as SequenceParticleValidator;
            validationContext.Element = sectPr;
                          
              //<xsd:complexType name="CT_SectPr">
              //  <xsd:sequence>
              //    <xsd:group ref="EG_HdrFtrReferences" minOccurs="0" maxOccurs="6"></xsd:group>
              //    <xsd:group ref="EG_SectPrContents" minOccurs="0"></xsd:group>
              //    <xsd:element name="sectPrChange" type="CT_SectPrChange" minOccurs="0">
              //  </xsd:sequence>
              //  <xsd:attributeGroup ref="AG_SectPrAttributes"></xsd:attributeGroup>
              //</xsd:complexType>

              //<xsd:group name="EG_HdrFtrReferences">
              //  <xsd:choice>
              //    <xsd:element name="headerReference" type="CT_HdrFtrRef" minOccurs="0">
              //    <xsd:element name="footerReference" type="CT_HdrFtrRef" minOccurs="0">
              //  </xsd:choice>
              //</xsd:group>

              //<xsd:group name="EG_SectPrContents">
              //  <xsd:sequence>
              //    <xsd:element name="footnotePr" type="CT_FtnProps" minOccurs="0">
              //    <xsd:element name="endnotePr" type="CT_EdnProps" minOccurs="0">
              //    <xsd:element name="type" type="CT_SectType" minOccurs="0">
              //    <xsd:element name="pgSz" type="CT_PageSz" minOccurs="0">
              //    <xsd:element name="pgMar" type="CT_PageMar" minOccurs="0">
              //    <xsd:element name="paperSrc" type="CT_PaperSource" minOccurs="0">
              //    <xsd:element name="pgBorders" type="CT_PageBorders" minOccurs="0">
              //    <xsd:element name="lnNumType" type="CT_LineNumber" minOccurs="0">
              //    <xsd:element name="pgNumType" type="CT_PageNumber" minOccurs="0">
              //    <xsd:element name="cols" type="CT_Columns" minOccurs="0">
              //    <xsd:element name="formProt" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="vAlign" type="CT_VerticalJc" minOccurs="0">
              //    <xsd:element name="noEndnote" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="titlePg" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="textDirection" type="CT_TextDirection" minOccurs="0">
              //    <xsd:element name="bidi" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="rtlGutter" type="CT_OnOff" minOccurs="0">
              //    <xsd:element name="docGrid" type="CT_DocGrid" minOccurs="0">
              //    <xsd:element name="printerSettings" type="CT_Rel" minOccurs="0">
              //  </xsd:sequence>
              //</xsd:group>

            // ***** good case ******
            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // headerReference is ok
            sectPr.Append(new HeaderReference());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // headerReference and footerReference
            sectPr.Append(new FooterReference());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // footerReference
            sectPr.RemoveChild(sectPr.FirstChild);
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 3 group <= 6, ok
            sectPr.Append(new HeaderReference(), new HeaderReference());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 5 group <= 6, ok
            sectPr.Append(new HeaderReference(), new HeaderReference());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 6 group <= 6, ok
            sectPr.Append(new HeaderReference());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // no EG_SectPrContents is ok
            sectPr.RemoveAllChildren();
            sectPr.Append(new HeaderReference(), new FooterReference(), new SectionPropertiesChange());
            Assert.True(actual.Valid);

            // test EG_SectPrContents
            sectPr.RemoveAllChildren();
            sectPr.Append(new HeaderReference(), new FooterReference(), new SectionType());
            Assert.True(actual.Valid);

            // 
            sectPr.AppendChild(new PaperSource());
            Assert.True(actual.Valid);

            sectPr.AppendChild(new TitlePage());
            Assert.True(actual.Valid);

            sectPr.AppendChild(new PrinterSettingsReference());
            Assert.True(actual.Valid);

            sectPr.AppendChild(new SectionPropertiesChange());
            Assert.True(actual.Valid);

            sectPr.RemoveAllChildren();
            sectPr.Append(new SectionPropertiesChange());
            Assert.True(actual.Valid);

            // ***** error case ******

            // 7 group > 6, error
            sectPr.RemoveAllChildren();
            sectPr.Append(new HeaderReference(), new HeaderReference(), new FooterReference(), new FooterReference(), new HeaderReference(), new HeaderReference());
            errorChild = sectPr.AppendChild(new HeaderReference());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            sectPr.RemoveChild(errorChild);

            actual.Clear();
            //first is invalid
            errorChild = sectPr.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":headerReference"));
            Assert.True(actual.Errors[0].Description.Contains(":footerReference"));
            Assert.False(actual.Errors[0].Description.Contains(":footnotePr"));
            Assert.False(actual.Errors[0].Description.Contains(":sectPrChange"));
            sectPr.RemoveChild(errorChild);

            actual.Clear();
            //invalid child in middle
            errorChild = sectPr.InsertBefore(new Paragraph(), sectPr.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            sectPr.RemoveChild(errorChild);

            actual.Clear();
            // order wrong
            errorChild = sectPr.FirstChild;
            sectPr.PrependChild(new SectionType());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));

            actual.Clear();
            // dup error
            sectPr.RemoveAllChildren();
            sectPr.Append(new HeaderReference(), new PaperSource());
            errorChild = sectPr.AppendChild( new PaperSource());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            sectPr.RemoveChild(errorChild);

            actual.Clear();
            // out of order error
            errorChild = sectPr.AppendChild(new SectionType());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            sectPr.RemoveChild(errorChild);

            actual.Clear();
            // out of order error
            sectPr.AppendChild(new SectionPropertiesChange());
            errorChild = sectPr.AppendChild(new SectionType());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Validates the specified element.
        /// </summary>
        /// <param name="openXmlElement">The target OpenXmlElement.</param>
        /// <returns>A set of validation erros.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the "openXmlElement" parameter is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the "openXmlElement" is type of OpenXmlUnknownElement, OpenXmlMiscNode, AlternateContent, AlternateContentChoice or AlternateContentFallback.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the "openXmlElement" is not defined in the specified FileFormat.</exception>
        public IEnumerable <ValidationErrorInfo> Validate(OpenXmlElement openXmlElement)
        {
            if (openXmlElement == null)
            {
                throw new ArgumentNullException(nameof(openXmlElement));
            }

            if (openXmlElement is OpenXmlUnknownElement)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateUnknownElement);
            }

            if (openXmlElement is OpenXmlMiscNode)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateMiscNode);
            }

            if (openXmlElement is AlternateContent ||
                openXmlElement is AlternateContentChoice ||
                openXmlElement is AlternateContentFallback)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateAcbElement);
            }

            if (!openXmlElement.IsInVersion(this.FileFormat))
            {
                switch (this.FileFormat)
                {
                case FileFormatVersions.Office2007:
                    throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2007);

                case FileFormatVersions.Office2010:
                    throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2010);

                case FileFormatVersions.Office2013:
                    throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2013);
                }
            }

            // TODO: if the FileFormat is Office2007, and the element is only in Office2010 and O15.
            // then this method should throw exceptions.

            var validationResult = new ValidationResult();

            validationResult.Valid                          = true;
            validationResult.MaxNumberOfErrors              = this._settings.MaxNumberOfErrors;
            validationResult.MaxNumberOfErrorsEventHandler += this.SchemaValidator.OnCancel;
            var validationContext = new ValidationContext();

            // this.ValidationContext.Settings = new ValidationSettings(this.FileFormat, this.SchemaOnly);
            validationContext.FileFormat = this.FileFormat;
            validationContext.ValidationErrorEventHandler += validationResult.OnValidationError;
            validationContext.Element = openXmlElement;
            // Do NOT use "yield return" in this method, as "yield return" are deferred executed.
            // Otherwise, the null check is not performed when the method is called, but rather, when the returned enumerator is moved for the first time.
            // That means that the exception isn't thrown until possibly far, far away from the actual site of the error, which is potentially confusing.

            this.SchemaValidator.Validate(validationContext);

            validationContext.Element = openXmlElement;
            this.FullSemanticValidator.Validate(validationContext);

            return(this.YieldResult(validationResult));
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Validates the specified content in the OpenXmlPart.
        /// </summary>
        /// <param name="openXmlPart">The target OpenXmlPart.</param>
        /// <returns>A set of validation erros.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the "openXmlPart" parameter is null.</exception>
        /// <exception cref="InvalidOperationException">Throw when the specified part is not a defined part in the specified FileFormat version.</exception>
        public IEnumerable <ValidationErrorInfo> Validate(OpenXmlPart openXmlPart)
        {
            if (openXmlPart == null)
            {
                throw new ArgumentNullException(nameof(openXmlPart));
            }

            var openXmlPackage = openXmlPart.OpenXmlPackage;

            if (openXmlPackage.OpenSettings.MarkupCompatibilityProcessSettings.ProcessMode != MarkupCompatibilityProcessMode.NoProcess &&
                openXmlPackage.OpenSettings.MarkupCompatibilityProcessSettings.TargetFileFormatVersions != this.FileFormat)
            {
                string exceptionMessage = string.Format(System.Globalization.CultureInfo.CurrentUICulture,
                                                        ExceptionMessages.DocumentFileFormatVersionMismatch,
                                                        openXmlPackage.OpenSettings.MarkupCompatibilityProcessSettings.TargetFileFormatVersions, this.FileFormat);

                throw new InvalidOperationException(exceptionMessage);
            }

            if (!openXmlPart.IsInVersion(this.FileFormat))
            {
                if (openXmlPart is ExtendedPart)
                {
                    throw new InvalidOperationException(ExceptionMessages.PartNotInVersion);
                }
                else
                {
                    string strMessage;

                    // All Office 2007 and 2010 parts are allowed in Office 2013.

                    switch (this.FileFormat)
                    {
                    case FileFormatVersions.Office2007:
                        strMessage = ExceptionMessages.PartIsNotInOffice2007;
                        break;

                    case FileFormatVersions.Office2010:
                        strMessage = ExceptionMessages.PartIsNotInOffice2010;
                        break;

                    case FileFormatVersions.Office2013:     // Falls through...
                    default:
                        strMessage = ExceptionMessages.PartIsNotInOffice2013;
                        break;
                    }

                    throw new InvalidOperationException(strMessage);
                }
            }

            // Do NOT use "yield return" in this method, as "yield return" are deferred executed.
            // Otherwise, the null check is not performed when the method is called, but rather, when the returned enumerator is moved for the first time.
            // That means that the exception isn't thrown until possibly far, far away from the actual site of the error, which is potentially confusing.

            OpenXmlPackage package = openXmlPart.OpenXmlPackage;

            Debug.Assert(package != null);

            ValidationResult validationResult = null;

            switch (DocumentTypeDetector.GetDocumentType(package))
            {
            case OpenXmlDocumentType.Spreadsheet:
                validationResult = this.SpreadsheetDocumentValidator.Validate(openXmlPart);
                break;

            case OpenXmlDocumentType.Wordprocessing:
                validationResult = this.WordprocessingDocumentValidator.Validate(openXmlPart);
                break;

            case OpenXmlDocumentType.Presentation:
                validationResult = this.PresentationDocumentValidator.Validate(openXmlPart);
                break;

            default:
                throw new System.IO.InvalidDataException(ExceptionMessages.UnknownPackage);
            }

            return(this.YieldResult(validationResult));
        }
        /// <summary>
        /// Validates the specified element.
        /// </summary>
        /// <param name="openXmlElement">The target OpenXmlElement.</param>
        /// <returns>A set of validation erros.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the "openXmlElement" parameter is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException">Thrown when the "openXmlElement" is type of OpenXmlUnknownElement, OpenXmlMiscNode, AlternateContent, AlternateContentChoice or AlternateContentFallback.</exception>
        /// <exception cref="InvalidOperationException">Thrown when the "openXmlElement" is not defined in the specified FileFormat.</exception>
        public IEnumerable<ValidationErrorInfo> Validate(OpenXmlElement openXmlElement)
        {
            if (openXmlElement == null)
            {
                throw new ArgumentNullException("openXmlElement");
            }

            if (openXmlElement is OpenXmlUnknownElement)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateUnknownElement);
            }

            if (openXmlElement is OpenXmlMiscNode)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateMiscNode);
            }

            if (openXmlElement is AlternateContent ||
                openXmlElement is AlternateContentChoice ||
                openXmlElement is AlternateContentFallback)
            {
                throw new ArgumentOutOfRangeException("openXmlElement", ExceptionMessages.CannotValidateAcbElement);
            }

            if (! openXmlElement.IsInVersion(this.FileFormat))
            {
                switch (this.FileFormat)
                {
                    case FileFormatVersions.Office2007:
                        throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2007);

                    case FileFormatVersions.Office2010:
                        throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2010);

                    case FileFormatVersions.Office2013:
                        throw new InvalidOperationException(ExceptionMessages.ElementIsNotInOffice2013);
                }
            }

            // TODO: if the FileFormat is Office2007, and the element is only in Office2010 and O15.
            // then this method should throw exceptions.

            var validationResult = new ValidationResult();
            validationResult.Valid = true;
            validationResult.MaxNumberOfErrors = this._settings.MaxNumberOfErrors;
            validationResult.MaxNumberOfErrorsEventHandler += this.SchemaValidator.OnCancel;
            var validationContext = new ValidationContext();
            // this.ValidationContext.Settings = new ValidationSettings(this.FileFormat, this.SchemaOnly);
            validationContext.FileFormat = this.FileFormat;
            validationContext.ValidationErrorEventHandler += validationResult.OnValidationError;
            validationContext.Element = openXmlElement;
            // Do NOT use "yield return" in this method, as "yield return" are deferred executed.
            // Otherwise, the null check is not performed when the method is called, but rather, when the returned enumerator is moved for the first time. 
            // That means that the exception isn't thrown until possibly far, far away from the actual site of the error, which is potentially confusing.

            this.SchemaValidator.Validate(validationContext);

            validationContext.Element = openXmlElement;
            this.FullSemanticValidator.Validate(validationContext);
            
            return this.YieldResult(validationResult);
        }
        private void TestSimpleChoice4(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            RevisionRowColumn rRowColumn = new RevisionRowColumn();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(rRowColumn).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ChoiceParticleValidator;
            validationContext.Element = rRowColumn;
            var expected = rRowColumn;
              
              //<xsd:complexType name="CT_RevisionRowColumn">
              //  <xsd:choice minOccurs="0" maxOccurs="unbounded">
              //    <xsd:element name="undo" type="CT_UndoInfo" minOccurs="0" maxOccurs="unbounded">
              //    <xsd:element name="rcc" type="CT_RevisionCellChange" minOccurs="0" maxOccurs="unbounded">
              //    <xsd:element name="rfmt" type="CT_RevisionFormatting" minOccurs="0" maxOccurs="unbounded">
              //  </xsd:choice>   
              //</xsd:complexType>

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            rRowColumn.AppendChild(new RevisionCellChange());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // dup is ok
            rRowColumn.AppendChild(new RevisionCellChange());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more is ok
            rRowColumn.AppendChild(new RevisionFormat());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // more is ok
            rRowColumn.AppendChild(new Undo());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            //first is invalid
            errorChild = rRowColumn.PrependChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":undo"));
            Assert.True(actual.Errors[0].Description.Contains(":rfmt"));

            actual.Clear();
            //invalid child in middle
            rRowColumn.RemoveChild(errorChild);
            errorChild = rRowColumn.InsertBefore(new Paragraph(), rRowColumn.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":undo"));
            Assert.True(actual.Errors[0].Description.Contains(":rfmt"));

            actual.Clear();
            //invalid child in last
            rRowColumn.RemoveChild(errorChild);
            errorChild = rRowColumn.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":undo"));
            Assert.True(actual.Errors[0].Description.Contains(":rfmt"));

        }
        ///// <summary>
        ///// Validate the specified document.
        ///// </summary>
        ///// <param name="stream">The document stream.</param>
        ///// <returns>A set of validation erros.</returns>
        //private IEnumerable<ValidationErrorInfo> ValidateCore(Stream stream)
        //{
        //    yield break;
        //}

        ///// <summary>
        ///// Validate the specified document.
        ///// </summary>
        ///// <param name="openXmlPackage">The target OpenXmlPackage.</param>
        ///// <returns>A set of validation erros.</returns>
        //private IEnumerable<ValidationErrorInfo> ValidateCore(OpenXmlPackage openXmlPackage)
        //{
        //    yield break;
        //}

        ///// <summary>
        ///// Validate the specified content in the OpenXmlPart.
        ///// </summary>
        ///// <param name="OpenXmlPart">The target OpenXmlPart.</param>
        ///// <returns>A set of validation erros.</returns>
        //private IEnumerable<ValidationErrorInfo> ValidateCore(OpenXmlPart openXmlPart)
        //{
        //    yield break;
        //}


        ///// <summary>
        ///// Validate the specified element.
        ///// </summary>
        ///// <param name="openXmlElement">The target OpenXmlElement.</param>
        ///// <returns>A set of validation erros.</returns>
        //private IEnumerable<ValidationErrorInfo> ValidateCore(OpenXmlElement openXmlElement)
        //{
        //    var validationResult = this.SchemaValidator.Validate(openXmlElement);
        //    return this.YieldResult(validationResult);
        //}

        private IEnumerable<ValidationErrorInfo> YieldResult(ValidationResult validationResult)
        {
            if (validationResult != null && validationResult.Valid == false)
            {
                foreach (var error in validationResult.Errors)
                {
                    yield return error;
                }
            }
        }
        private void ValidateBody(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            Body body = new Body();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(body).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ParticleValidator;
            validationContext.Element = body;
            var expected = body;

              //<xsd:complexType name="CT_Body">
              //  <xsd:sequence>
              //    <xsd:group ref="EG_BlockLevelElts" minOccurs="0" maxOccurs="unbounded" />
              //    <xsd:element name="sectPr" minOccurs="0" maxOccurs="1" type="CT_SectPr">
              //  </xsd:sequence>
              //</xsd:complexType>

              //<xs:group name="EG_BlockLevelEltsBase">
              //  <xs:choice>
              //    <xs:element name="altChunk" type="CT_AltChunk" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_BlockLevelElts">
              //  <xs:choice>
              //    <xs:group ref="EG_BlockLevelEltsBase" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_BlockLevelChunkElts" minOccurs="0" maxOccurs="unbounded" />
              //  </xs:choice>
              //</xs:group>
      
              //<xsd:group name="EG_BlockLevelChunkElts">
              //  <xsd:choice>
              //    <xsd:group ref="EG_ContentBlockContent" minOccurs="0" maxOccurs="unbounded" />
              //  </xsd:choice>
              //</xsd:group>

              //<xs:group name="EG_ContentBlockContent">
              //  <xs:choice>
              //    <xs:group ref="EG_ContentBlockContentBase" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_RunLevelElts" minOccurs="0" maxOccurs="unbounded" />
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_ContentBlockContentBase">
              //  <xs:choice>
              //    <xs:element name="customXml" type="CT_CustomXmlBlock"></xs:element>
              //    <xs:element name="sdt" type="CT_SdtBlock"></xs:element>
              //    <xs:element name="p" type="CT_P" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //    <xs:element name="tbl" type="CT_Tbl" minOccurs="0" maxOccurs="unbounded"></xs:element>
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_RunLevelElts">
              //  <xs:choice>
              //    <xs:group ref="EG_RunLevelEltsBase" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_RangeMarkupElements" minOccurs="0" maxOccurs="unbounded"></xs:group>
              //    <xs:element name="ins" type="CT_RunTrackChange" minOccurs="0">
              //    <xs:element name="del" type="CT_RunTrackChange" minOccurs="0">
              //    <xs:element name="moveFrom" type="CT_RunTrackChange">
              //    <xs:element name="moveTo" type="CT_RunTrackChange">
              //    <xs:element name="contentPart" type="CT_ContentPart" minOccurs="0" maxOccurs="unbounded" ofapi:available="o14" />
              //    <xs:group ref="w14:EG_RunLevelConflicts" minOccurs="0" />
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_RunLevelEltsBase">
              //  <xs:choice>
              //    <xs:element name="proofErr" minOccurs="0" type="CT_ProofErr"></xs:element>
              //    <xs:element name="permStart" minOccurs="0" type="CT_PermStart"></xs:element>
              //    <xs:element name="permEnd" minOccurs="0" type="CT_Perm"></xs:element>
              //  </xs:choice>
              //</xs:group>

              //<xs:group name="EG_RangeMarkupElements">
              //  <xs:choice>
              //    <xs:group ref="EG_RangeMarkupElementsNoRev" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:group ref="EG_RangeMarkupElementsRev" minOccurs="0" maxOccurs="unbounded" />
              //    <xs:element ref="w14:customXmlConflictInsRangeStart" minOccurs="0" />
              //    <xs:element ref="w14:customXmlConflictInsRangeEnd" minOccurs="0" />
              //    <xs:element ref="w14:customXmlConflictDelRangeStart" minOccurs="0" />
              //    <xs:element ref="w14:customXmlConflictDelRangeEnd" minOccurs="0" />
              //  </xs:choice>
              //</xs:group>

              //<xsd:group name="EG_MathContent">
              //  <xsd:choice>
              //    <xsd:element ref="m:oMathPara"></xsd:element>
              //    <xsd:element ref="m:oMath"></xsd:element>
              //  </xsd:choice>
              //</xsd:group>

            // ################ the above schema has been changed by EcmaD ##############

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // 
            body.AppendChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.PrependChild(new AltChunk());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // multiple AltChunk is ok
            body.PrependChild(new AltChunk());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.InsertAfter(new Paragraph(), body.FirstChild);
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.PrependChild(new MoveFromRangeStart());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.PrependChild(new MoveFromRun());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            //body.PrependChild(new DocumentFormat.OpenXml.Math.OfficeMath());
            //target.Validate(validationContext);
            //Assert.True(actual.Valid);

            //body.PrependChild(new DocumentFormat.OpenXml.Math.OfficeMath());
            //target.Validate(validationContext);
            //Assert.True(actual.Valid);

            body.PrependChild(new MoveFromRun());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.PrependChild(new MoveFromRangeStart());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            body.InsertAfter(new Paragraph(), body.FirstChild);
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******
            // sectProperties can not be the first
            errorChild = body.FirstChild;
            body.PrependChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            body.RemoveChild(body.FirstChild);

            actual.Clear();
            // can only have one sectProperties at last
            errorChild = body.AppendChild(new SectionProperties());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            body.RemoveChild(errorChild);

            actual.Clear();
            // paragrap can be after sectProperties at last
            errorChild = body.AppendChild(new Paragraph());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_UnexpectedElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            body.RemoveChild(errorChild);

            actual.Clear();
            // first is invalid
            errorChild = body.PrependChild(new Run());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":altChunk"));
            body.RemoveChild(errorChild);

            actual.Clear();
            // invalid child in middle
            errorChild = body.InsertBefore(new Run(), body.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            body.RemoveChild(errorChild);
        }
        private void TestSimpleAny(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            TextBox textBox = new TextBox();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(textBox).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as ChoiceParticleValidator;
            validationContext.Element = textBox;
            var expected = textBox;
              //<xsd:complexType name="CT_Textbox">
              //  <xsd:choice>
              //    <xsd:element ref="w:txbxContent" minOccurs="0" />
              //    <xsd:any namespace="##local" processContents="skip" />
              //  </xsd:choice>
              //</xsd:complexType>

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any element without namespace is ok
            errorChild = textBox.AppendChild(new OpenXmlUnknownElement("test"));
            Assert.True(string.IsNullOrEmpty(errorChild.NamespaceUri));
            target.Validate(validationContext);
            Assert.True(actual.Valid);
            textBox.RemoveChild(errorChild);

            // ***** error case ******

            // any element with namespace is invlaid
            errorChild = textBox.AppendChild(new TextBox());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":txbxContent"));
            Assert.True(actual.Errors[0].Description.Contains("##local"));
            textBox.RemoveChild(errorChild);

            actual.Clear();
            // any element with namespace is invlaid
            errorChild = textBox.AppendChild(new OpenXmlUnknownElement("", "test", "http://test"));
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":txbxContent"));
            Assert.True(actual.Errors[0].Description.Contains("##local"));
            textBox.RemoveChild(errorChild);

            actual.Clear();
            // any element with namespace is invlaid
            errorChild = textBox.AppendChild(new OpenXmlUnknownElement("t", "test", "http://test"));
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":txbxContent"));
            Assert.True(actual.Errors[0].Description.Contains("##local"));
            textBox.RemoveChild(errorChild);

            actual.Clear();
            // only one element without namespace is allowed
            textBox.AppendChild(new OpenXmlUnknownElement("test"));
            errorChild = textBox.AppendChild(new OpenXmlUnknownElement("errorElement"));
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            textBox.RemoveAllChildren();

            actual.Clear();
            // only one element without namespace is allowed
            textBox.AppendChild(new OpenXmlUnknownElement("test"));
            errorChild = textBox.AppendChild(new OpenXmlUnknownElement("test"));
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.False(actual.Errors[0].Description.Contains(ValidationErrorStrings.Fmt_ListOfPossibleElements));
            textBox.RemoveAllChildren();
        }
        private void TestSimpleAll2(SdbSchemaDatas sdbSchemaDatas)
        {
            ValidationContext validationContext = new ValidationContext();
            ValidationResult actual = new ValidationResult();
            validationContext.ValidationErrorEventHandler += actual.OnValidationError;
            OpenXmlElement errorChild;

            ShapeLayout shapeLayout = new ShapeLayout();
            var particleConstraint = sdbSchemaDatas.GetSchemaTypeData(shapeLayout).ParticleConstraint;
            var target = particleConstraint.ParticleValidator as AllParticleValidator;
            validationContext.Element = shapeLayout;
            var expected = shapeLayout;

            //<xsd:complexType name="CT_ShapeLayout">
            //  <xsd:all>
            //    <xsd:element name="idmap" type="CT_IdMap" minOccurs="0">
            //    <xsd:element name="regrouptable" type="CT_RegroupTable" minOccurs="0">
            //    <xsd:element name="rules" type="CT_Rules" minOccurs="0">
            //  </xsd:all>
            //  <xsd:attributeGroup ref="v:AG_Ext" />
            //</xsd:complexType>

            // ***** good case ******

            // empty is ok
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any one is ok
            shapeLayout.AppendChild(new RegroupTable());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any order is ok
            shapeLayout.AppendChild(new ShapeIdMap());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // any order is ok
            shapeLayout.AppendChild(new Rules());
            target.Validate(validationContext);
            Assert.True(actual.Valid);

            // ***** error case ******

            // first is invlaid
            errorChild = shapeLayout.PrependChild(new Paragraphs());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":idmap"));
            Assert.True(actual.Errors[0].Description.Contains(":rules"));
            shapeLayout.RemoveChild(errorChild);

            actual.Clear();
            //invalid child in middle
            errorChild = shapeLayout.InsertBefore(new Paragraphs(), shapeLayout.LastChild);
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_InvalidElementContentExpectingComplex", actual.Errors[0].Id);
            Assert.True(actual.Errors[0].Description.Contains(":rules"));
            shapeLayout.RemoveChild(errorChild);

            actual.Clear();
            // dup 
            errorChild = shapeLayout.FirstChild;
            shapeLayout.PrependChild(new RegroupTable());
            target.Validate(validationContext);
            Assert.False(actual.Valid);
            Assert.Equal(1, actual.Errors.Count);
            Assert.Same(expected, actual.Errors[0].Node);
            Assert.Equal(ValidationErrorType.Schema, actual.Errors[0].ErrorType);
            Assert.Equal("Sch_AllElement", actual.Errors[0].Id);
            Assert.Same(errorChild, actual.Errors[0].RelatedNode);
            shapeLayout.RemoveChild(errorChild);

        }