Daniel Green
Daniel Green

Reputation: 644

Validating XML documents with XSD correctly

As a developer with a good deal of XML consuming and producing experience, I've never really interacted with schemas before. For the first time this is actually occurring for me.

I've run across a "feature" that I consider more of a bug which is well documented.

When using XDocument.Validate() it seems that there are cases in which the document will be valid if it doesn't match the schema specified. I feel this is most likely a flaw in my understanding of the relationship between XSDs, XML namespaces, and expected validation processes.

Therefore I submit to you my XML sample, my XSD sample, and my validation code.

XML - this is INTENTIONALLY the wrong document.

<?xml version="1.0" encoding="utf-8" ?>
<SuppliesDefinitions 
  xmlns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Supplies.xsd">
  <Supply type="Common">
    <Information/>
    <Ritual/>
    <Weapon/>
    <Tool count="1"/>
    <Tool count="2"/>
    <Tool count="3"/>
  </Supply>
  <Supply type="Uncommon">
    <Information/>
    <Weapon/>
    <Tool count="1"/>
    <Tool count="2"/>
    <Tool count="3"/>
    <Tool count="4"/>
  </Supply>
  <Supply type="Rare">
    <Information/>
    <Rune/>
    <Weapon/>
    <Tool count="2"/>
    <Tool count="3"/>
    <Tool count="4"/>
  </Supply>
</SuppliesDefinitions>

The XSD used to validate it. (Again, this is intentionally the WRONG document for the above XML)

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Encounters"
    targetNamespace="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    elementFormDefault="qualified"
    xmlns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    xmlns:mstns="http://lavendersoftware.org/schemas/SteamGame/Data/Xml/Encounters.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
  <xs:complexType name="ToolType">
    <xs:attribute name="count" use="required" type="xs:int"/>
  </xs:complexType>

  <xs:complexType name="TaskType">
    <xs:choice maxOccurs="unbounded" minOccurs="1">
      <xs:element name="Weapon"/>
      <xs:element name="Information"/>
      <xs:element name="Tool" type="ToolType"/>
      <xs:element name="Ritual"/>
    </xs:choice>
  </xs:complexType>


  <xs:complexType name="EncounterType">
    <xs:sequence maxOccurs="unbounded" minOccurs="1">
      <xs:element name="Task" type="TaskType"/>
    </xs:sequence>
    <xs:attribute name="name" use="required" type="xs:string"/>
  </xs:complexType>

  <xs:element name="EncounterDefinitions">
    <xs:complexType>
      <xs:sequence maxOccurs="unbounded" minOccurs="1">
        <xs:element name="Encounter" type="EncounterType"/>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

And finally the validation code.

    private static void ValidateDocument(XDocument doc)
    {
        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add(null, XmlReader.Create(new StreamReader(XmlSchemaProvider.GetSchemaStream("Encounters.xsd"))));

        doc.Validate(schemas, (o, e) =>
        {
            //This is never hit!
            Console.WriteLine("{0}", e.Message);
            Assert.False(e.Severity == XmlSeverityType.Error);
        });
    }

I was wondering if someone can explain what I am doing wrong. I feel I'm making some incorrect assumptions about the way this SHOULD be working. It seems to me using one xsd against a completely unrelated XML document would be invalid.

Upvotes: 5

Views: 3928

Answers (1)

Alexei Levenkov
Alexei Levenkov

Reputation: 100537

There is no nodes in your XML that can be validated by the schema (namespaces are different). As result it does not report any errors. As far as I know behavior for nodes that are not matched to any schema is allow anything.

You also could set validation options in XmlReaderSettings to allow warnings:

ReportValidationWarnings - Indicates that events should be reported if a validation warning occurs. A warning is typically issued when there is no DTD or XML Schema to validate a particular element or attribute against. The ValidationEventHandler is used for notification.

Check out XmlSchemaSet.Add and HOW TO: Validate an XML Document by Using Multiple Schemas if you expect nodes from multiple namespaces to be present in the XML.

Upvotes: 4

Related Questions