Validating XML Via Embedded XSD Schema
January 17, 2008
Problem: You have some XML, and you need to validate it against a custom schema that you want to deploy with your .Net 2.0 assemblies. Issues addressed: opening the file and handling the schema validation.
XmlSchema class contains a Read method that takes a stream as a parameter. Nicely matching up to that, you can open a stream from an embedded resource (thank you, attilan.com).So, embed the schema. In Visual Studio's Solution Explorer, right-click the schema file and choose properties. Change the Build Action to "Embedded Resource".
Open the Embedded Resource Stream
The first thing to establish is the name of your embedded resource. For the Assembly that it is stored in, the name will be the Assembly's namespace to begin with. If the resource is in a sub-directory, add that directory's name. Then add the filename that is being embedded. Thus if you have an assembly called
MyCode.exe, a directory called Resources, and an embedded schema file called
MySchema.xsd, then the resource name will be
MyCode.Resources.MySchema.xsd. I think; I haven't found good documentation to back that up, but it should be something to that effect.
Now you need to execute
GetManifestResourceStream(string) on an Assembly. Which Assembly? Assuming it is the same Assembly where your code is written, you can use
System.Reflection to find the "executing" Assembly:
myStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(myResourceName);.
Creating the Schema and Validating
Creating the schema is simple:
XmlSchema mySchema = XmlSchema.Read(myStream, new ValidationEventHandler(myDelegateHandler));. This ValidationEventHandler is a delegate that handles any validation errors. Simply create a delegate method somewhere with a signature of
void myHandler(object sender, ValidationEventArgs e). In that method you'll have to decide what to do with the validation errors. There are two severities (Error and Warning), and the
ValidationEventArgs contains the detailed validation problem. In my case, I threw the problem into a custom exception class so that it could be handled downstream.