1

I'm trying to validate an xml string with a schema and am running into an issue where it's not recognizing restrictions in the xsd using facets. I've created a unit test where I'm serializing an object into an xml, validating the xml using my schema and deserializing the xml back to the object. Everything works great, but for some reason I'm not getting an error when my latitude is within the range specified in the schema. I've defined a latitude to be within -90 to 90 however I'm not getting an error when I'm exceeding the bound. Here's the xml I get after serializing:

<?xml version="1.0" encoding="utf-8"?>
<Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Message>    
    <Blocks>
      <Location>
        <Latitude>110.5</Latitude>
        <Longitude>11.5</Longitude>
        <IsValid>true</IsValid>
        <PrecisionKilometers>1</PrecisionKilometers>
      </Location>      
    </Blocks>
  </Message>  
</Messages>

The schema that I'm using is shown below. The relevant part with the latitude is in the middle. (I know it's a bit ugly and I'm trying to get them to optimize their schema generation code)

<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns:VL="http://customUri" elementFormDefault="qualified" targetNamespace="http://customUri" id="MessageList" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Messages">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="unbounded" name="Message" nillable="true">
          <xs:complexType>
            <xs:sequence>
              <xs:element minOccurs="1" maxOccurs="unbounded" name="Blocks">
                <xs:complexType>
                  <xs:all>

                    <xs:element minOccurs="0" maxOccurs="1" name="Location" nillable="true">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element minOccurs="1" maxOccurs="1" name="Latitude">
                            <xs:simpleType>
                              <xs:restriction base="xs:double">
                                <xs:minInclusive value="-90" />
                                <xs:maxExclusive value="90" />
                              </xs:restriction>
                            </xs:simpleType>
                          </xs:element>
                          <xs:element minOccurs="1" maxOccurs="1" name="Longitude">
                            <xs:simpleType>
                              <xs:restriction base="xs:double">
                                <xs:minInclusive value="-180" />
                                <xs:maxExclusive value="180" />
                              </xs:restriction>
                            </xs:simpleType>
                          </xs:element>
                          <xs:element minOccurs="1" maxOccurs="1" name="IsValid" type="xs:boolean" />
                          <xs:element minOccurs="0" maxOccurs="1" name="PrecisionKilometers" nillable="true" type="xs:double" />
                        </xs:sequence>
                      </xs:complexType>
                    </xs:element>

                  </xs:all>
                </xs:complexType>
              </xs:element>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>

My settings for reading the xml are: (notice I'm specifying flags for ReportValidationWarnings and ProcessIdentityContraints as well as using a validation handler to detect warnings)

    var settings = new XmlReaderSettings
          {
            ValidationType = ValidationType.Schema,
            ValidationFlags =         
              XmlSchemaValidationFlags.ReportValidationWarnings |
              XmlSchemaValidationFlags.ProcessInlineSchema |
              XmlSchemaValidationFlags.ProcessSchemaLocation |
              XmlSchemaValidationFlags.ProcessIdentityConstraints |
              XmlSchemaValidationFlags.AllowXmlAttributes,
            IgnoreWhitespace = true,
            IgnoreComments = true,
          };
settings.ValidationEventHandler += (o, ex) =>
          {            
            if (ex.Severity == XmlSeverityType.Warning || ex.Severity == XmlSeverityType.Error)
            {
              //do something
            }
          };
    settings.Schemas.Add(mySchemaSet);

The code I'm using to deserialize is pretty standard.

XmlReader reader = XmlReader.Create(memoryStreamContainingXml, settings);
var serializer = new XmlSerializer(typeof(MessageList));
MessageList returned = ser.Deserialize(reader) as MessageList;

I also tried doing a while(reader.read(){}) instead of deserializing to see if a validation error is thrown but I'm not getting any issue.

arviman
  • 5,087
  • 41
  • 48
  • Where do you specify which schema to use? – Vadim Jan 21 '14 at 08:35
  • 1
    Also, if you specify targetNamespace in your schema, shouldn't the elements in the XML be inside that namespace? – Vadim Jan 21 '14 at 08:39
  • The schema to use is given in the settings part. I'm adding a 'mySchemaSet' to which I'm adding the schema. I just omitted it here since I didn't want to clutter the question. As for the namespace, since I'm not specifying a xmlns:target prefix to my xml elements, they will revert to using the default xmlns http://www.w3.org/2001/XMLSchema" – arviman Jan 21 '14 at 08:54
  • But you specify a target namespace of `http://customUri` in your XSD document. So the `Message` elements in the default namespace in your XML aren't the `Message` elements in the `http://customUri` namespace of your XSD. – Damien_The_Unbeliever Jan 21 '14 at 08:57
  • And FYI, you're missing the element declaration for `http://customUri:Messages` (plural) in your `XSD`. – IronGeek Jan 21 '14 at 09:02
  • @IronGeek - sorry, but I again omitted that for brevity. I've updated the question to remove the confusion. – arviman Jan 21 '14 at 09:51
  • @Damien_The_Unbeliever - Please check this link. http://stackoverflow.com/questions/4126919/what-is-the-difference-between-targetnamespace-and-xmlnstarget. It says that xmlns="" defines the default namespace within the current document for all non-prefixed elements. Since my xml elements are non-prefixed it shouldn't matter if they refer to my target-namespace. – arviman Jan 21 '14 at 10:31
  • It doesn't matter if they are prefixed or non-prefixed. The fact is you need to include the xmlns. The (updated) xml in my answer validates according to the schema definition, and now gives the validation error Validation error: The 'http://customUri:Latitude' element is invalid - The value '110.0' is invalid according to its datatype 'Double' - The MaxExclusive constraint failed. – tom redfern Jan 21 '14 at 11:38
  • @Vadim - You could put this comment as an answer if you want. Deserves a +1. – arviman Jan 22 '14 at 06:46

1 Answers1

1

Try your code with the following XML:

<ns0:Messages xmlns:ns0="http://customUri">
  <ns0:Message>
    <ns0:Blocks>
      <ns0:Location>
        <ns0:Latitude>110.0</ns0:Latitude>
        <ns0:Longitude>11.5</ns0:Longitude>
        <ns0:IsValid>true</ns0:IsValid>
        <ns0:PrecisionKilometers>1</ns0:PrecisionKilometers>
      </ns0:Location>
    </ns0:Blocks>
  </ns0:Message>
</ns0:Messages>

As Vadim says in the comments, you need to tell the validator that the types in your XML are those defined in the schema. And the way to do that is to include the target namespace of the schema in your XML instance.

Without this, all the validator can do is check if the XML is well formed. This is why it is returning a valid result.

UPDATE

enter image description here

enter image description here

tom redfern
  • 30,562
  • 14
  • 91
  • 126
  • No, it doesn't work when i try this. It throws an exception {" was not expected."} – arviman Jan 21 '14 at 10:23
  • Yeah, I tried it on a schema generated based on just the Message. I retried this on the MessageList but am getting a similar error. – arviman Jan 21 '14 at 11:37
  • When I validate the above against your schema I get: `Validation error: The 'http://customUri:Latitude' element is invalid - The value '110.0' is invalid according to its datatype 'Double' - The MaxExclusive constraint failed`, which is what you wanted no? – tom redfern Jan 21 '14 at 11:39
  • No I'm getting a `{" was not expected."}`. I tried adding\removing the xmlns:xsi and xmlns:xsd attributes to the root as well, but no change. – arviman Jan 21 '14 at 11:42
  • *Then you are doing it wrong*. Are you sure your XSD is exactly how it is above? I just cut and pasted it again, and it works. Go to http://www.utilities-online.info/xsdvalidation and try it. I have updated my answer with screenshots. – tom redfern Jan 21 '14 at 11:51
  • Strangely, it seems to work fine on the site(I just copy-pasted the xml and schema from the debugger so they're new) but I'm getting an error while I deserialize using XmlReader. I guess the issue's likely outside the scope of this question. Thanks for your help though! – arviman Jan 21 '14 at 11:59
  • No probs. Any chance you could award me the answer? – tom redfern Jan 21 '14 at 12:03
  • I was thinking of awarding you the answer on the way back home :) Done. Another alternative, just for interest would be for me to generate the XML from the schema using xsd.exe to generate a class and then serializing it (which would guarantee right namespacing) and then changing the latitude value. Since, this is just for testing purposes it should work fine. – arviman Jan 21 '14 at 15:25