views:

519

answers:

2

I have an XML file which is being uploaded to an ASP.Net page via the normal file upload control. When it gets up, I am attempting to validate and deserialize the XML. However, the code below is really very handy for validating an XML file which references it's XSD like this:

xsi:schemaLocation="someurl ..\localSchemaPath.xsd"

However, if I upload this XML file, only the XML file gets uploaded, so ..\localSchemaPath.xsd doesn't exist, so it can't validate.

Even if I stored the XSD locally, it still wouldn't be quite right as the XML file could be written with a schema location like:

xsi:schemaLocation="someurl ..\localSchemaPath.xsd"

or xsi:schemaLocation="someurl localSchemaPath.xsd" or xsi:schemaLocation="someurl ..................\localSchemaPath.xsd" if it so wished.

Dilemma!

(For the purposes of this question, I have pinched the code below from: http://stackoverflow.com/questions/751511/validating-an-xml-against-referenced-xsd-in-c)

using System.Xml;
using System.Xml.Schema;
using System.IO;

public class ValidXSD
{
    public static void Main()
    {
        // Set the validation settings.
        XmlReaderSettings settings = new XmlReaderSettings();
        settings.ValidationType = ValidationType.Schema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation;
        settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings;
        settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);

        // Create the XmlReader object.
        XmlReader reader = XmlReader.Create("inlineSchema.xml", settings);

        // Parse the file. 
        while (reader.Read()) ;
    }

    // Display any warnings or errors.
    private static void ValidationCallBack(object sender, ValidationEventArgs args)
    {
        if (args.Severity == XmlSeverityType.Warning)
            Console.WriteLine("\tWarning: Matching schema not found.  No validation occurred." + args.Message);
        else
            Console.WriteLine("\tValidation error: " + args.Message);
    }
}
+1  A: 

I can't quite make out whether you are attempting a generic validate-against-any-referenced-schema, or if you have a specific schema that you validate against every time, and are just not sure how to handle the references.

If it's the latter, then make the schema public on the internet, and tell people to reference it by URI.

If it's the former, then I would suggest the following:

  • First the user uploads an XML file.
  • Parse the XML file for a schema reference. Tell them "References to yourSchema.xsd were found; please upload this file below" with a new upload box.
  • Then, validate the file against the uploaded schema. To do this, modify the Schemas property of your settings object, instead of modifying the ValidationFlags property.
Domenic
+1  A: 

Here is a chunk of code I use to validate xml with a local schema:

string errors = string.Empty;

try
{
    XmlSchemaSet schemas = new XmlSchemaSet();
    schemas.Add(string.Empty, Page.MapPath("~/xml/Schema.xsd"));
    XmlDocument doc = new XmlDocument();
    doc.Schemas = schemas;
    doc.Load(Page.MapPath("~/xml/sampleXML.xml"));
    //use this line instead of the one above for a string in memory.
    //doc.InnerXml = xmlToValidate;  
    ValidationEventHandler validator = delegate(object send, ValidationEventArgs ve)
                                           {
                                               errors += "\n" + ve.Severity + ": " + ve.Message;
                                           };

    doc.Validate(validator);
}
catch (XmlException xe)
{
    errors += "\n" + xe.Message;
}
catch (XmlSchemaValidationException xe)
{
    errors += "\n" + xe.Message;
}
Chris