Search code examples
c#xmlxsdxml-parsingxsd-validation

Issue while converting XSD with complextype to XML using MSDN Microsoft.Xml.XMLGen( XmlSampleGenerator API)


I am trying to convert an XSD with complex type into XML I could not getting the expected result. The xsd is shown below.

But only one of the node showing correct data but the second one not showing the correct result attaching the screenshot enter image description here any idea on this?? I can able to convert it through online, at that time it is working fine Do we have any limitation in samplegenerator to use same complex type in multiplenode?

Here is the XSD:

<xs:schema xmlns:xs="w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="XXX">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="Applicant">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element name="PrimaryEmployment" type="EmploymentType"/>
                        <xs:element name="SecondEmployment" type="EmploymentType"/>
                    </xs:sequence>
                    <xs:attribute name="type" type="xs:string"/>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>
<xs:complexType name="EmploymentType">
    <xs:sequence>
        <xs:element name="TimeAtEmployer">
            <xs:complexType>
                <xs:sequence> 
                    <xs:element name="Years" type="xs:int"/>
                    <xs:element name="Months" type="xs:int" maxOccurs="unbounded"/>
                </xs:sequence>
            </xs:complexType>
        </xs:element>
    </xs:sequence>
</xs:complexType>

Expected xml file

<Applicant>
<PrimaryEmployment>
  <TimeAtEmployer>
    <Years>123</Years>
    <Months>123</Months>
  </TimeAtEmployer>
</PrimaryEmployment>
<SecondEmployment>
  <TimeAtEmployer>
    <Years>123</Years>
    <Months>123</Months>
  </TimeAtEmployer>
</SecondEmployment>

Current XML

`<Applicant>
        <PrimaryEmployment>
          <TimeAtEmployer>
            <Years>123</Years>
            <Months>123</Months>
          </TimeAtEmployer>
        </PrimaryEmployment>
        <SecondEmployment>
          <TimeAtEmployer>      
          </TimeAtEmployer>
        </SecondEmployment>
      </Applicant>`

Sample code that i have tried

XmlTextWriter textWriter = new XmlTextWriter("po.xml", null);
        textWriter.Formatting = Formatting.Indented;
        XmlQualifiedName qname = new XmlQualifiedName("Loancontract", "http://tempuri.org");
        XmlSampleGenerator generator = new XmlSampleGenerator("sample.xsd", qname);
        generator.WriteXml(textWriter);

Example2

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlDocument xml;
            var rootElement = new XmlQualifiedName("sampledata");
            var XSD = @"<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema"" elementFormDefault=""qualified"" attributeFormDefault=""unqualified""> 
                <xs:element name = ""SampleData2"">

                <xs:complexType>

                <xs:sequence>

                <xs:element name = ""Applicant"">

                <xs:complexType>

                <xs:sequence>

                <xs:element name = ""PrimaryEmployment"" type = ""EmploymentType""/>

                <xs:element name = ""SecondEmployment"" type = ""EmploymentType""/>

                </xs:sequence>

                </xs:complexType>

                </xs:element>

                </xs:sequence>

                </xs:complexType>

                </xs:element>

                <xs:complexType name = ""EmploymentType"">

                <xs:sequence>

                <xs:element name = ""TimeAtEmployer"">

                <xs:complexType>

                <xs:sequence>

                <xs:element name = ""Years"" type = ""xs:int""/>

                <xs:element name = ""Months"" type = ""xs:int""/>

                </xs:sequence>

                </xs:complexType>

                </xs:element>

                </xs:sequence>
                </xs:complexType>
                </xs:schema>
                ";
            XmlElement serializedElement = Serialize(XSD);
        }
        public static XmlDocument GetXml(string xsd, XmlQualifiedName rootElem)
        {
            var reader = XmlReader.Create(new StringReader(xsd), new XmlReaderSettings
            {
                DtdProcessing = DtdProcessing.Prohibit
            });

            XmlSchema schema = XmlSchema.Read(reader, null);
            var generator = new XmlSampleGenerator(schema, rootElem);
            generator.MaxThreshold = 2;

            var xmlStringBuilder = new StringBuilder();
            var writer = XmlWriter.Create(xmlStringBuilder);
            generator.WriteXml(writer);

            var resultXmlDoc = new XmlDocument();
            resultXmlDoc.LoadXml(xmlStringBuilder.ToString());
            //BlankOutValues(resultXmlDoc.DocumentElement);
            return resultXmlDoc;
        }
        public static XmlElement Serialize(object transformObject)
        {
            XmlElement serializedElement = null;

            MemoryStream memStream = new MemoryStream();
            XmlSerializer serializer = new XmlSerializer(transformObject.GetType());
            serializer.Serialize(memStream, transformObject);
            memStream.Position = 0;
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(memStream);
            var reader = XmlReader.Create(new StringReader(new StreamReader(memStream).ReadToEnd().Replace("utf-8", "utf-16")), new XmlReaderSettings
            {
                DtdProcessing = DtdProcessing.Prohibit
            });
            XmlDocument xsd = new XmlDocument();
            var rootElement = new XmlQualifiedName("LoanContract");
            xsd = GetXml(transformObject.ToString(), rootElement);
            return serializedElement;

        }
    }
}

Solution

  • I think you need to change the XmlSampleGenerator.dll

    private bool GenerateElement(XmlSchemaElement e, bool root, InstanceGroup parentElem, XmlSchemaAny any) {
             XmlSchemaElement eGlobalDecl = e;
             bool flagCached = false;
             if (!e.RefName.IsEmpty) {
                   eGlobalDecl = (XmlSchemaElement)schemaSet.GlobalElements[e.QualifiedName];
             }
             if (!eGlobalDecl.IsAbstract) {
                   InstanceElement elem = (InstanceElement)elementTypesProcessed[eGlobalDecl];
                   if (elem != null) {
                       Debug.Assert(!root);
                       if (any == null && e.MinOccurs > 0) { //If not generating for any or optional ref to cyclic global element
                           decimal occurs = e.MaxOccurs;
                           if (e.MaxOccurs >= maxThreshold) {
                               occurs = maxThreshold;
                           }
                           if (e.MinOccurs > occurs) {
                               occurs = e.MinOccurs;
                           }
                           elem = elem.Clone(occurs);
                           parentElem.AddChild(elem);
                           flagCached = true;
                       }
                   }
                   else
                   {
                       elem = new InstanceElement(eGlobalDecl.QualifiedName);
                   }
                   if(root) {
                       instanceRoot = elem;
                   }
                   else {
                       if(!flagCached)
                       parentElem.AddChild(elem);
                       flagCached = false;
                   }
                   //Get minOccurs, maxOccurs alone from the current particle, everything else pick up from globalDecl
                   if (any != null) { //Element from any
                       elem.Occurs = any.MaxOccurs >= maxThreshold ? maxThreshold : any.MaxOccurs;
                       elem.Occurs = any.MinOccurs > elem.Occurs ? any.MinOccurs : elem.Occurs;
                   }
                   else {
                       elem.Occurs = e.MaxOccurs >= maxThreshold ? maxThreshold : e.MaxOccurs;
                       elem.Occurs = e.MinOccurs > elem.Occurs ? e.MinOccurs : elem.Occurs;
                   }
                   elem.DefaultValue = eGlobalDecl.DefaultValue;
                   elem.FixedValue = eGlobalDecl.FixedValue;
                   elem.IsNillable = eGlobalDecl.IsNillable;
                   if (eGlobalDecl.ElementSchemaType == AnyType) {
                       elem.ValueGenerator = XmlValueGenerator.AnyGenerator;
                   }
                   else {
                       XmlSchemaComplexType ct = eGlobalDecl.ElementSchemaType as XmlSchemaComplexType;
                       if (ct != null) {
                           if(!elementTypesProcessed.ContainsKey(eGlobalDecl)) elementTypesProcessed.Add(eGlobalDecl, elem);
                           if (!ct.IsAbstract) {
                               elem.IsMixed = ct.IsMixed;
                               ProcessComplexType(ct, elem);
                           }
                           else { // Ct is abstract, need to generate instance elements with xsi:type
                               XmlSchemaComplexType dt = GetDerivedType(ct);
                               if (dt != null) {
                                   elem.XsiType = dt.QualifiedName;
                                   ProcessComplexType(dt, elem);
                               }
                           }
                       }
                       else { //elementType is XmlSchemaSimpleType
                           elem.ValueGenerator = XmlValueGenerator.CreateGenerator(eGlobalDecl.ElementSchemaType.Datatype, listLength);
                       }
                   }
                   if (elem.ValueGenerator != null && elem.ValueGenerator.Prefix == null) {
                       elem.ValueGenerator.Prefix = elem.QualifiedName.Name;
                   }
                   return true;
             } // End of e.IsAbstract
             return false;
           }
    

    It is working for me,Please check