Why my xsd is not automatically raising required field exception in C#

56 views Asked by At

This is my XML

<?xml version="1.0" encoding="utf-8"?>
<Zones xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.keaneaustralia.com/Nts" xsi:schemaLocation="http://schemas.keaneaustralia.com/Nts Zones.xsd" version="1" major_version="434" minor_version="0" start_date="2023-07-09T00:00:00+10:00">
<Record long_desc="City Saver Zone"/>
<Record logical="2" physical="1" short_desc="Zone 1" long_desc="Zone 1" is_city_saver="Yes" />
<Record logical="3" physical="2" short_desc="Zone 2" long_desc="Zone 2" is_city_saver="false" />
<Record logical="dt" physical="3" short_desc="Zone 3" long_desc="Zone 3" is_city_saver="false" />
<Record logical="5" physical="4" short_desc="Zone 4" long_desc="Zone 4" is_city_saver="false" />
<Record logical="6" physical="5" short_desc="Zone 5" long_desc="Zone 5" is_city_saver="false" />
</Zones>

This is my XSD

<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:tns="http://schemas.keaneaustralia.com/Nts" elementFormDefault="qualified" targetNamespace="http://schemas.keaneaustralia.com/Nts" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Zones" nillable="true" type="tns:ZoneCollection" />
<xs:complexType name="ZoneCollection">
<xs:complexContent mixed="false">
<xs:extension base="tns:DataElementOfZone" />
</xs:complexContent>
</xs:complexType>
<xs:complexType name="DataElementOfZone">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="unbounded" name="Record" type="tns:Zone" />
</xs:sequence>
<xs:attribute name="version" type="xs:int" use="required" />
<xs:attribute name="major_version" type="xs:int" use="required" />
<xs:attribute name="minor_version" type="xs:int" use="required" />
<xs:attribute name="start_date" type="xs:dateTime" use="required" />
<xs:attribute default="false" name="is_delta" type="xs:boolean" />
<xs:attribute default="0" name="delta_major_version" type="xs:int" />
<xs:attribute default="0" name="delta_minor_version" type="xs:int" />
</xs:complexType>
<xs:complexType name="Zone">
<xs:attribute name="logical" type="xs:unsignedByte" use="required" />
<xs:attribute name="physical" type="xs:unsignedByte" use="required" />
<xs:attribute name="short_desc" type="xs:string" />
<xs:attribute name="long_desc" type="xs:string" />
<xs:attribute name="is_city_saver" type="xs:boolean" use="required" />
</xs:complexType>
</xs:schema>

The file is passing validation and it is not raising any error. When I check on debug mode, there is a null reference exception for attributeSchemaInfo.Below is the function to validate the xml. It is not raising the required exception for logical attribute and type error for field is_city_saver which is expecting only boolean :true and false instead of yes and no.


 private static bool ValidateXmlAgainstXsd(string xmlFilePath, string xsdFilePath, ILogger fileLogger)
        {
            try
            {
                int numErreur = 0;
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                schemaSet.Add(null, xsdFilePath);
                schemaSet.Compile();

 

                XmlReaderSettings settings = new XmlReaderSettings();
                settings.Schemas.Add(schemaSet);
                settings.ValidationType = ValidationType.Schema;
                settings.ValidationFlags =
                XmlSchemaValidationFlags.ReportValidationWarnings |
                XmlSchemaValidationFlags.ProcessIdentityConstraints |
                XmlSchemaValidationFlags.ProcessInlineSchema;
                settings.ValidationEventHandler += (sender, e) =>
                {
                   LogValidationError(xmlFilePath, e.Message, e.Exception, e.Exception.LineNumber, e.Exception.LinePosition, e.Severity, fileLogger, ref numErreur);
                };

 

                using (XmlReader reader = XmlReader.Create(xmlFilePath, settings))
                {
                    while (reader.Read())
                    {
                        //process code
                     }
                }
                return numErreur > 0 ? false : true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error validating XML '{xmlFilePath}' against XSD '{xsdFilePath}': {ex.Message}");
                return false;
            }
        }

 
       

1

There are 1 answers

4
Yitzhak Khabinsky On

I slightly modified your code, and commented out/removed the LogValidationError() call.

The XSD validation is working! Please see below.

My guess is that the issue is with the commented out LogValidationError().

c#

void Main()
{   
    string xmlFilePath = @"e:\Temp\Zones.xml";
    string xsdFilePath = @"e:\Temp\Zones.xsd";
    
    ValidateXmlAgainstXsd(xmlFilePath, xsdFilePath);
}

private static bool ValidateXmlAgainstXsd(string xmlFilePath, string xsdFilePath)
{
    try
    {
        int numErreur = 0;
        XmlSchemaSet schemaSet = new XmlSchemaSet();
        schemaSet.Add(null, xsdFilePath);
        schemaSet.Compile();



        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(schemaSet);
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags =
        XmlSchemaValidationFlags.ReportValidationWarnings |
        XmlSchemaValidationFlags.ProcessIdentityConstraints |
        XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationEventHandler += (sender, e) =>
        {
            //LogValidationError(xmlFilePath, e.Message, e.Exception, e.Exception.LineNumber, e.Exception.LinePosition, e.Severity, fileLogger, ref numErreur);
            Console.WriteLine(e.Message);
        };



        using (XmlReader reader = XmlReader.Create(xmlFilePath, settings))
        {
            while (reader.Read())
            {
                //process code
            }
        }
        return numErreur > 0 ? false : true;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Error validating XML '{xmlFilePath}' against XSD '{xsdFilePath}': {ex.Message}");
        return false;
    }
}

Output

The required attribute 'logical' is missing.
The required attribute 'physical' is missing.
The required attribute 'is_city_saver' is missing.
The 'is_city_saver' attribute is invalid - The value 'Yes' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:boolean' - The string 'Yes' is not a valid Boolean value.
The 'logical' attribute is invalid - The value 'dt' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:unsignedByte' - The string 'dt' is not a valid Byte value.