4

I have multiple Xsd schema files (small ones) and would like to somehow combine them into 1 big file, I was thinking of an xml file with 1 node for each Xsd schema content, in the C# code selecting the corresponding section and validating against it. The problem is I can see a warning "The global element 'xxx' has already been declared. " when opening the Xml file using Visual studio (I'm definitely not an Xsd expert; I indeed have the same element repeated).

Any ideas of the correctness of this approach ? Shall I use CData for Xsd content may be instead ?

Examples of Xml files:

Xml 1:

<resource xmlns="">
  <identifier>5401902302111</identifier>
  <product>printer</product>
  <requestedby />
</resource>

Xml 2:

<resource xmlns="">
  <identifier>5401902302112</identifier>
  <email>someone@em.com</email>
</resource>

Xsd 1:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="resource">
              <xs:complexType>
                <xs:sequence>
                  <xs:element type="xs:long" name="identifier"/>
                  <xs:element type="xs:string" name="requestedby"/>
                  <xs:element type="xs:string" name="product"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:schema>

Xsd 2:

<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
            <xs:element name="resource">
              <xs:complexType>
                <xs:sequence>
                  <xs:element type="xs:long" name="identifier"/>
                  <xs:element type="xs:string" name="email"/>
                </xs:sequence>
              </xs:complexType>
            </xs:element>
          </xs:schema>

What I want to have in the end:

*<?xml version="1.0" encoding="utf-8"?>
<resource>
  <resourcedata type="acquisition">
    <details>
      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="resource">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:long" name="identifier"/>
              <xs:element type="xs:string" name="requestedby"/>
              <xs:element type="xs:string" name="product"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    </details>
  </resourcedata>
  <resourcedata type="warningletter">
    <details>
      <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:element name="resource">
          <xs:complexType>
            <xs:sequence>
              <xs:element type="xs:long" name="identifier"/>
              <xs:element type="xs:string" name="email"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:schema>
    </details>
  </resourcedata>
</data>*

C# code:

var xsdContent =
                xDoc.Element("resource").Elements("resourcedata")
                    .Where(
                        x =>                            
                            x.Attribute("type").Value == "acquisition")
                    .FirstOrDefault().Element("details").FirstNode.ToString();            


            var doc = new XDocument(xElementContent);

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

            Console.WriteLine("Validating doc");
            bool errors = false;
            doc.Validate(schemas, (o, e) =>
            {
                Console.WriteLine("{0}", e.Message);
                Console.WriteLine("{0}", e.Exception);
                errors = true;
            });

            Console.WriteLine("doc {0}", errors ? "did not validate" : "validated");

(xElementContent variable contains Xml content)

Thanks

aly
  • 373
  • 2
  • 7
  • 22
  • Why you do have multiple XSD documents if they are small? Why not have one single schema document? What do you mean by you repeated an element? Please show any relevant C# code and a minimal sample of all schema files, and an XML document to be validated. – Mathias Müller Mar 25 '15 at 15:17
  • You only show _one_ XSD document - all others are not schema files. Completely unclear what you are asking. – Mathias Müller Mar 25 '15 at 16:43
  • I agree with Mathias. That's an interesting approach that may, however, to be motivated more by misunderstanding than specific requirements demanding deviation from standard validation practices. Unless you have specific, compelling reasons for going down this path, I suggest you do things [more conventionally](http://stackoverflow.com/a/29261615/290085). – kjhughes Mar 25 '15 at 16:51

2 Answers2

4

Unlike others, I would think that the only problem with your question is that it fails to illustrate a good example as to why would one create an XML file format as described by you. In fact, I was involved in an interesting discussion here on SO, for which C. M. Sperberg-McQueen even put together a demo, concluding:

It thus illustrates that multiple spec-conformant schema documents can be embedded in the same XML document. (Since this appears to be an issue for some interested parties, it should apparently also be noted that WSDL is not involved here.)

I felt compelled to link C. M. Sperberg-McQueen's answer, since you said I was thinking of an xml file rather than an XSD file (which would be kjhughes point).

Why I think you didn't show a good scenario, is because the following single schema would satisfy very well your XMLs.

<?xml version="1.0" encoding="utf-8"?>
<!--XML Schema generated by QTAssistant/XML Schema Refactoring (XSR) Module (http://www.paschidev.com)-->
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="resource">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="identifier" type="xs:unsignedLong"/>
                <xs:choice>
                    <xs:element minOccurs="0" name="email" type="xs:string"/>
                    <xs:sequence>
                        <xs:element minOccurs="0" name="product" type="xs:string"/>
                        <xs:element minOccurs="0" name="requestedby" type="xs:string"/>                             
                    </xs:sequence>
                </xs:choice>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

Let's go through some scenarios (please update your question if you have something else):

  • Your root element might have a different name. In this case, simply create another global element, matching that name.
  • Your root element might be in a different namespace. In this case, simply create another XSD file, with a targetNamespace matching your XML's namespace. Then add all your XSDs to an XmlSchemaSet, and validate away.
  • For the same element, your content models may be different, yet reconcilable in terms of what an XSD 1.0 (since you're showing stock .NET code, I assume you're stuck with what .NET supports). This would be the case with the schema I've created above.
  • You can't use XSD 1.0; it may, or not, work with features in XSD 1.1 (such as co-constraints, type alternatives, etc.) - point is, XSD 1.1 is not employable here. Then your proposal to put together multiple XSDs in one XML file will work like a charm. In fact, I would call it a poor man's alternative for XSD 1.1 in the .NET world...

For the latter, I would recommend a slightly different approach. I would use XInclude to link the XSDs toghether in one file - if that's what your processing model requires; there's a NET library here. This would allow to author the XSDs independently, thus making sure each one is valid, and using common editors (including your Visual Studio).

Community
  • 1
  • 1
Petru Gardea
  • 21,373
  • 2
  • 50
  • 62
2

Rather than invent your own, ad-hoc way to combine XSDs, you should use standard methods based on xsd:include or xsd:import.

See also: What's the difference between xsd:include and xsd:import?

And unless you have a very specific reason to dispatch your validation using ad hoc methods in code, you should validate at the document level and let the parser do the work of locating the appropriate declarations for you.

Community
  • 1
  • 1
kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • I understand this is a "deviation from standard validation practices" - I edited the question accordingly. I just wanted to try eliminating somehow the overhead of having > 20 Xsd files - I can have about 20 types of Xml as valid requests and for each I need a separate Xsd file. I think I can go with the alternative of having Xsd content into CData section. – aly Mar 25 '15 at 17:18
  • 3
    Still, "eliminating somehow the overhead of having > 20 Xsd files" does not really justify such an unorthodox approach. (I've seen clients use hundreds of XSDs working smoothly together.) Further, having to resort to CDATA should signal to you that you're swimming upstream. Either you're failing to motivate your design decisions here or you're making it harder than it has to be. All indications so far point toward the latter. Not trying to criticize, but sometimes the best help has to suggest a change of direction. – kjhughes Mar 25 '15 at 17:52
  • The main question was if this is possible\technically correct (me saying I am not an Xsd expert), and from your answers I see that basically not, so thank you for the replies. Unfortunately what I have told so far is all the information I can provide from the design point of view. – aly Mar 25 '15 at 18:33