tags:

views:

145

answers:

1

As a follow up to my issue transforming large Xml files, I now need to validate the schema.

I was using this extension method, which can clearly be improved upon as it's not working correctly either

public static XElement ValidateXsd(this XElement source, string xsdPath)
{
    var errors = new XElement("Errors");

    // Reference: http://msdn.microsoft.com/en-us/library/bb358456.aspx
    var xsd = XDocument.Load(xsdPath);
    var xml = XDocument.Load(source.CreateReader());

    var schemas = new XmlSchemaSet();
    schemas.Add("", xsd.CreateReader());

    if (xml.Document != null)
    {
        xml.Document.Validate(schemas,
            // Validation Event/Error Handling
            (sender, e) =>
                {
                    var message = e.Message
                        .Replace(
                            "element is invalid - The value '' is invalid according to its datatype 'requiredString' - The actual length is less than the MinLength value.",
                            "cannot be blank.")
                        .Replace(
                            "is invalid according to its datatype 'size' - The Pattern constraint failed.",
                            "must be numeric.")
                        .Replace(
                            "element is invalid",
                            "is invalid.");

                    errors.Add(new XElement("Error", message));
                }
            );
    }

    // If there were errors return them, otherwise return null
    return errors.Elements().Count() > 0 ? errors : null;
}
+2  A: 

Try this instead:

public static XElement ValidateXsd(this XElement source, string xsdPath)
{
    var errors = new XElement("Errors");

    // Reference: http://msdn.microsoft.com/en-us/library/bb358456.aspx 

    var schemas = new XmlSchemaSet();
    using (var reader = XmlReader.Create(xsdPath))
    {
        schemas.Add("", reader);
    }

    {
        source.Document.Validate(
            schemas,
            // Validation Event/Error Handling 
            (sender, e) =>
            {
                var message =
                    e.Message.Replace(
                        "element is invalid - The value '' is invalid according to its datatype 'requiredString' - The actual length is less than the MinLength value.",
                        "cannot be blank.").Replace(
                        "is invalid according to its datatype 'size' - The Pattern constraint failed.",
                        "must be numeric.").Replace("element is invalid", "is invalid.");

                errors.Add(new XElement("Error", message));
            });
    }

    // If there were errors return them, otherwise return null 
    return errors.Elements().Count() > 0 ? errors : null;
} 

Try this instead:

using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Schema;

    static class Extensions
    {
        public static XElement ValidateXsd(this XElement source, string xsdPath)
        {
            var errors = new XElement("Errors");

            // Reference: http://msdn.microsoft.com/en-us/library/bb358456.aspx 

            var schemas = new XmlSchemaSet();
            using (var reader = XmlReader.Create(xsdPath))
            {
                schemas.Add("", reader);
            }

            var sourceQualifiedName = new XmlQualifiedName(source.Name.LocalName, source.Name.NamespaceName);
            source.Validate(
                schemas.GlobalElements[sourceQualifiedName],
                schemas,
                // Validation Event/Error Handling 
                (sender, e) =>
                {
                    var message =
                        e.Message.Replace(
                            "element is invalid - The value '' is invalid according to its datatype 'requiredString' - The actual length is less than the MinLength value.",
                            "cannot be blank.").Replace(
                            "is invalid according to its datatype 'size' - The Pattern constraint failed.",
                            "must be numeric.").Replace("element is invalid", "is invalid.");

                    errors.Add(new XElement("Error", message));
                });

            // If there were errors return them, otherwise return null 
            return errors.Elements().Count() > 0 ? errors : null;
        } 
    }
John Saunders
Would this work if you xsd is based on the element which is a subset of the source?
David Basarab
It will work or not, depending on whether it's valid to have a schema inside your source.
John Saunders
@John, the problem I have with this is source.Document is null
Chad
@John, Uh...which one?
Chad
@Sorry, I seem to have posted it twice.
John Saunders