Reputation: 907
I am looking at something to validate XML we are sent against the XSD for it. I have come across these three but only one seems to 'work' I'm guessing there is a reason for one flagging and issue where others don't but wondering what is the best method to use and the difference, apart from the way it is done, with these three.
XML
<?xml version="1.0" encoding="UTF-8"?>
<Person>
<Forename>John</Forename>
</Person>
XSD
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" version="0.2">
<xs:annotation>
<xs:documentation>
</xs:documentation>
</xs:annotation>
<xs:element name ="Person">
<xs:complexType>
<xs:sequence>
<xs:element name="Forename" type="xs:string"/>
<xs:element name="Surname" type="xs:string"/>
<xs:element name="Middlename" type="xs:string" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The first one flag's an error that the surname element is expected but isn't in the XML which I would expect.
class XPathValidation
{
static void Main()
{
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add("", XmlReader.Create(@"C:\test\test.xsd"));
XDocument doc = XDocument.Load(@"C:\test\test.xml");
Console.WriteLine("Validating doc1");
bool errors = false;
doc.Validate(schemas, (o, e) =>
{
Console.WriteLine("{0}", e.Message);
errors = true;
});
Console.WriteLine("doc1 {0}", errors ? "did not validate" : "validated");
Console.ReadKey();
}
}
These two both just run and return nothing.
class XmlSchemaSetExample
{
static void Main()
{
XmlReaderSettings booksSettings = new XmlReaderSettings();
booksSettings.Schemas.Add("http://www.w3.org/2001/XMLSchema", @"C:\test\test.xsd");
booksSettings.ValidationType = ValidationType.Schema;
booksSettings.ValidationEventHandler += new ValidationEventHandler(booksSettingsValidationEventHandler);
XmlReader books = XmlReader.Create(@"C:\test\test.xml", booksSettings);
while (books.Read()) { }
Console.ReadKey();
}
static void booksSettingsValidationEventHandler(object sender, ValidationEventArgs e)
{
if (e.Severity == XmlSeverityType.Warning)
{
Console.Write("WARNING: ");
Console.WriteLine(e.Message);
}
else if (e.Severity == XmlSeverityType.Error)
{
Console.Write("ERROR: ");
Console.WriteLine(e.Message);
}
}
}
and
class XPathValidation
{
static void Main()
{
try
{
XmlReaderSettings settings = new XmlReaderSettings();
settings.Schemas.Add("http://www.w3.org/2001/XMLSchema", @"C:\test\test.xsd");
settings.ValidationType = ValidationType.Schema;
XmlReader reader = XmlReader.Create(@"C:\test\test.xml", settings);
XmlDocument document = new XmlDocument();
document.Load(reader);
ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler);
// the following call to Validate succeeds.
document.Validate(eventHandler);
// the document will now fail to successfully validate
document.Validate(eventHandler);
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void ValidationEventHandler(object sender, ValidationEventArgs e)
{
switch (e.Severity)
{
case XmlSeverityType.Error:
Console.WriteLine("Error: {0}", e.Message);
break;
case XmlSeverityType.Warning:
Console.WriteLine("Warning {0}", e.Message);
break;
}
}
}
thanks for the info, still learning all this.
Upvotes: 0
Views: 501
Reputation: 26213
I would imagine the second two do not work because you're supplying an incorrect value for targetNamespace
when you add the schema to your XmlReaderSettings
. This should be an empty string, as your XML has no namespace (or null
, as per the docs, this will infer the namespace from the schema).
As to which is better, it depends what your requirement is. If simply to validate it, option 2 using the XmlReader
is preferred because it doesn't go to the expense of loading the entire XML into a DOM which you'd then throw away.
If you do need to query the XML using a DOM, the XDocument
/ LINQ to XML API (option 1) is a much better, more modern API than the old XmlDocument
API (option 3).
Upvotes: 1