balint
balint

Reputation: 3431

Xsd validation problem

I have the following (errorous) Xml:

<jobs>
    <job>
        <id>1</id>
        <state><![CDATA[IL]]></state>
    </job>
    <job>
        <id>2</id>
    </job>
</jobs>

both the id and the state node are reqired items. I wrote an Xsd for it:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    targetNamespace="http://foo.org/importvalidator.xsd"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="jobs">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="job" minOccurs="1" maxOccurs="unbounded">
              <xs:complexType>
                <xs:all>
                  <xs:element name="id" type="xs:string" minOccurs="1"/>
                  <xs:element name="state" type="xs:string" minOccurs="1"/>
                </xs:all>
              </xs:complexType>
            </xs:element>
          </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

And it still validates as a structurally valid Xml. What am I missing here?

Update1: the code I'm using is in C#:

        XmlSchemaSet schemas = new XmlSchemaSet();
        schemas.Add("http://foo.org/importvalidator.xsd", "validator.xsd");

        XDocument doc = XDocument.Load(fileName);
        if (doc == null | doc.Root == null)
        {
            throw new ApplicationException("xml error: the referenced stream is not xml.");
        }

        doc.Validate(schemas, (o, e) =>
        {
            throw new ApplicationException("xsd validation error: xml file has structural problems");
        });

Upvotes: 3

Views: 6354

Answers (3)

13ren
13ren

Reputation: 12187

Please format your xml so it's easier to read - like this:

<jobs>
  <job>
    <id>1</id>
    <state><![CDATA[IL]]></state>
  </job>
  <job>
    <id>2</id>
  </job>
</jobs>

I think you're not actually validating it - the namespaces mean that that XML does not validate, even with a "<state>" in the second "<job>". Specifically, the XSD has a target namespace of "http://foo.org/importvalidator.xsd", but the XML has no namespace given.

Set up a trivial test case of XSD and XML, that you definitely know will fail - use that to track down why you aren't validating.

Also, your XSD is missing the close tags for element and schema, so it should give an error - or it's just a mis-paste :-)


You can remove the targetNamespace from the schema:

<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    targetNamespace="http://foo.org/importvalidator.xsd    ← DELETE THIS"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

So it looks like this:

<xs:schema id="importvalidator"
    elementFormDefault="qualified"
    xmlns="http://foo.org/importvalidator.xsd"
    xmlns:mstns="http://foo.org/importvalidator.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">

PS: anyone know if/how you can highlight parts of source code with SO's markdown?

Upvotes: 3

John Saunders
John Saunders

Reputation: 161773

@13ren has the correct answer. It is not an error if a node does not match any schema. It's only a warning. I can see the warnings in the code below:

private static void ValidateDocument(XmlSchemaSet schemas, string uri)
{
    var settings = new XmlReaderSettings
                       {
                           Schemas = schemas,
                           ValidationFlags =
                               XmlSchemaValidationFlags.
                                   ProcessIdentityConstraints |
                               XmlSchemaValidationFlags.
                                   ReportValidationWarnings,
                           ValidationType = ValidationType.Schema
                       };
    settings.ValidationEventHandler += OnValidationEventHandler;
    using (var validatingReader = XmlReader.Create(uri, settings))
    {
        XDocument.Load(
            validatingReader,
            LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
    }
    return;
}

This produces the following:

Warning: Could not find schema information for the element 'jobs'. Warning: Could not find schema information for the element 'job'. Warning: Could not find schema information for the element 'id'. Warning: Could not find schema information for the element 'state'. Warning: Could not find schema information for the element 'job'. Warning: Could not find schema information for the element 'id'.

Changing your XML and running again:

<?xml version="1.0" encoding="utf-8" ?>
<jobs xmlns="http://foo.org/importvalidator.xsd">
  <job>
    <id>1</id>
    <state><![CDATA[IL]]></state>
  </job>
  <job>
    <id>2</id>
  </job>
</jobs>

produces the error you expected:

Error: The element 'job' in namespace 'http://foo.org/importvalidator.xsd' has incomplete content. List of possible elements expected: 'state' in namespace 'http://foo.org/importvalidator.xsd'.

Upvotes: 2

duffymo
duffymo

Reputation: 308743

Which parser/language are you using? It used to be be that you'd have to tell the Xerces parser that you'd like XSD validation if you're using Java. But after checking the latest release docs, I see that validation is built-in now. So it seems that the version is important. If you're a .NET developer, best to check what its settings need to be.

Just curious - why the CDATA surrounding the state in your example? There's no need for that, AFAIK. You can even embed a restriction in your XSD to ensure that you only get valid US state codes.

But first things first - get the schema validating.

Upvotes: 0

Related Questions