Validate XML against an XSD in C#
This is how .NET produces the messages above. With no schema it only checks that the XML is well-formed:
Without a ValidationEventHandler, the first validation error throws an XmlSchemaValidationException instead of being collected. XDocument.Validate(schemas, handler) from System.Xml.Schema.Extensions is the LINQ to XML version.
Why a document can look valid when it is not
- Wrong or missing namespace. If the root element's namespace is not a target namespace in the schema set, there is nothing to validate it against.
XmlReaderreports only warnings ("Could not find schema information for the element"), and warnings are off unless you setXmlSchemaValidationFlags.ReportValidationWarnings. Load the "Missing namespace" example and untick "Report warnings" to see an invoice with noxmlnspass without a single message. - One error per element. After an element's children fail to match the schema (a wrong, extra or out-of-order child),
XmlReaderstops checking the rest of that element and does not report missing children. Fix the first error and run it again. - Lax wildcards. Content allowed by
xs:any processContents="lax", and everything under an element of typexs:anyType, is only checked when a global declaration exists for it.
Reading the messages
- Positions are where the reader was: an invalid value is reported at the element's end tag, a missing child at the end tag, an unexpected child at its start tag, and an attribute error at the attribute name. Click a message to jump to it.
- Datatype names show the built-in type as
http://www.w3.org/2001/XMLSchema:int, a named type by its name, and an anonymous restriction by its base type's short name (String,Decimal). - A DOCTYPE is refused ("For security reasons DTD is prohibited"), because
XmlReader.CreateusesDtdProcessing.Prohibitby default. - An error in the schema itself (an invalid default or fixed value, two ID attributes on one type) is reported as
XmlSchemaSetreports it, and the document is not checked.
What this page does not check
The schema must be one file. xs:import, xs:include, derived complex types (xs:complexContent), xs:list and xs:union, substitution groups, identity constraints (xs:key, xs:unique, xs:keyref) and xsi:type in the document are reported as not supported instead of guessed; .NET supports them all, so run the C# above for those. If the XML is not well-formed, the page shows that error only; XmlReader would also report the validation errors it found before that point.
FAQ
What is the difference between well-formed and valid XML?
Well-formed XML follows the XML syntax rules: one root element, matching tags, quoted attributes, escaped & and <. Valid XML is well-formed and also matches a schema: the right elements in the right order, with values of the right type.
Can I validate against a DTD instead?
Yes, in .NET: set DtdProcessing = DtdProcessing.Parse and ValidationType = ValidationType.DTD. This page validates against XSD only.
How do I stop at the first error?
Leave out the ValidationEventHandler. The first error then throws an XmlSchemaValidationException with LineNumber and LinePosition.
How do I validate XML against an XSD in C#?
Add the schema to XmlReaderSettings.Schemas, set ValidationType = ValidationType.Schema, handle ValidationEventHandler, and read the whole document with XmlReader.Create(input, settings). Without a handler, the first error throws an XmlSchemaValidationException.
Why does my XML pass validation when it is in the wrong namespace?
If the root element's namespace is not in the schema set, XmlReader has nothing to validate it against and only reports warnings ("Could not find schema information"). Warnings are off unless you add XmlSchemaValidationFlags.ReportValidationWarnings, so the document looks valid.
Why do I get only one error for an element with several mistakes?
After an element's content fails to match the schema, XmlReader stops checking the rest of that element's children and does not report missing ones. Fix the first error and validate again.
Is my XML uploaded?
No. The validator runs in your browser.