Question

I am trying to validate the following Xml.

string xml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
                    <ROOT xmlns:bk=""urn:samples"">
                        <RandomName1>
                            <Element1>v</Element1>
                            <Element2>v</Element2>
                            <Element3>v</Element3>
                            <Element4>v</Element4>
                    </RandomName1>
                        <RandomName2>
                            <Element1>v</Element1>
                            <Element2>v</Element2>
                            <Element3>v</Element3>
                            <Element4>v</Element4>
                    </RandomName2>
                    </ROOT>";

RandomNameN is any string. I am interested in ensuring that Element1 - Element4 are present and named correctly and that the schema matches.

I have tried the following

string xsdMarkup =
                @"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
                   <xsd:element name='ROOT'>
                    <xsd:complexType>
                     <xsd:sequence>
                      <xsd:any>
                        <xsd:complexType>
                            <xsd:sequence>
                                <xsd:element name ='Element1'/>
                                <xsd:element name ='Element2'/>
                                <xsd:element name ='Element3'/>
                                <xsd:element name ='Element4'/>
                            </xsd:sequence>
                        </xsd:complexType>
                        </xsd:any>
                     </xsd:sequence>
                    </xsd:complexType>
                   </xsd:element>
                  </xsd:schema>";

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(new StringReader(xsdMarkup)));

var xDoc = XDocument.Parse(xml);

bool errors = false;
string msg = string.Empty;

xDoc.Validate(schemas, (o, e) =>
    {
        msg = e.Message;
        errors = true;
    });

I am getting System.Xml.Schema.XmlSchemaException

The 'http://www.w3.org/2001/XMLSchema:complexType' element is not supported in this context.

I need to also know how to make the RandomName1 nodes not require a name but be present. I've tried to acheieve this via </xsd:any> instead of </xsd:element>

Was it helpful?

Solution

As I mentioned in my comment, the usage of <xsd:any> is incorrect.

Furthermore, <xsd:sequence> also cannot contain a complexType. See: http://msdn.microsoft.com/en-us/library/ms256089.aspx

I would also suggest not using patterns like RandomNameN to identify your elements but more like: <RandomName id='N'>. Speaking OO, you could think of your XSD as your Class definitions, with the complexTypes being the classes, and elements being references to instances of the complexTypes classes, therefore for elements you should also define their type.

Your XML document will then represent your Objects. Where the type of the Object is represented in the Tag.

Your complexType could be wrapped inside of an element. And since you have a variable number of elements in the sequence, you should set maxOccurs to unbounded. Your resulting Schema should look like this:

    <xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
       <xsd:element name='ROOT'>
          <xsd:complexType>
            <xsd:sequence>
               <xsd:element name="RandomName" maxOccurs='unbounded'>
                  <xsd:complexType>
                     <xsd:sequence>
                       <xsd:element name="Element" minOccurs='4' maxOccurs='4' type="xsd:string" />
                    </xsd:sequence>
                  </xsd:complexType>
               </xsd:element>
            </xsd:sequence>
          </xsd:complexType>
       </xsd:element>
    </xsd:schema>>

In which case your XML could look like this:

<ROOT >
     <RandomName>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
     </RandomName>
     <RandomName>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
        <Element>v</Element>
     </RandomName>
 </ROOT> 

Finally, if RandomName1 - RandonNameN are from the same type (or Class if we're speaking OO) then the tags in the XML file should also be the same. Same goes for Element1-Element4.

However, if they are of different types but have common elements, you could use inheritance.

Element1 could look like this for example:

<complexType name="Element1">
    <complexContent>
        <extension base="Element">
            <sequence>
                <xs:element type="xs:string" name="additionalField"/>
            </sequence>
        </extension>
    </complexContent>
</complexType>

OTHER TIPS

I don't know if the xml producer is under your control. If it is you could solve it e.g. using element with fixed name with some attribute containing random name, smth like <FixedNameElement randomName="...">.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top