【C#】XmlDocument.Validateが動かないんやけど
皆さんXMLをXSDでValidateすることがたまにあると思うんですが、
すでにXSD的なエラーがXMLに存在する場合、XmlDocument.Validateがちゃんと動いてくれません。
例えば以下のような場合、「ISBN属性が無い」「不明なauthorr要素がある」「不明なbooks 要素がある」という3つのエラーが表示されてほしいわけです。
using System; using System.Xml; using System.Xml.Schema; using System.Xml.XPath; class XPathValidation { static void Main() { try { XmlReaderSettings settings = new XmlReaderSettings(); settings.Schemas.Add("http://www.contoso.com/books", "contosoBooks.xsd"); settings.ValidationType = ValidationType.Schema; XmlReader reader = XmlReader.Create("contosoBooks.xml", settings); XmlDocument document = new XmlDocument(); document.Load(reader); ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler); // the following call to Validate succeeds. document.Validate(eventHandler); } 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; } } }
<bookstore xmlns="http://www.contoso.com/books" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="test.xsd"> <book genre="autobiography" publicationdate="1981-03-22"> <title>The Autobiography of Benjamin Franklin</title> <author> <first-name>Benjamin</first-name> <last-name>Franklin</last-name> </author> <price>8.99</price> </book> <book genre="novel" publicationdate="1967-11-17" ISBN="0-201-63361-2"> <title>The Confidence Man</title> <authorr> <first-name>Herman</first-name> <last-name>Melville</last-name> </authorr> <price>11.99</price> </book> <books genre="philosophy" publicationdate="1991-02-15" ISBN="1-861001-57-6"> <title>The Gorgias</title> <author> <name>Plato</name> </author> <price>9.99</price> </books> </bookstore>
<?xml version="1.0" encoding="utf-8"?> <xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.contoso.com/books" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="bookstore"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" name="book"> <xs:complexType> <xs:sequence> <xs:element name="title" type="xs:string" /> <xs:element name="author"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="name" type="xs:string" /> <xs:element minOccurs="0" name="first-name" type="xs:string" /> <xs:element minOccurs="0" name="last-name" type="xs:string" /> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="price" type="xs:decimal" /> </xs:sequence> <xs:attribute name="genre" type="xs:string" use="required" /> <xs:attribute name="publicationdate" type="xs:date" use="required" /> <xs:attribute name="ISBN" type="xs:string" use="required" /> </xs:complexType> </xs:element> </xs:sequence> </xs:complexType> </xs:element> </xs:schema>
こういう場合はコードをちょちょっと書き換えて、XmlDocument.Load後にValidateしてやるとうまくいきます。
(Validateが動いていない原因はXmlDocument.Loadでエラーが発生していたから)
using System; using System.Xml; using System.Xml.Schema; namespace XmlSchemaValidate { class Program { static void Main(string[] args) { XmlDocument document = new XmlDocument(); document.Load("test.xml"); XmlTextReader reader = new XmlTextReader("test.xsd"); XmlSchema xmlschema = XmlSchema.Read(reader, null); XmlSchemaSet schemaSet = new XmlSchemaSet(); schemaSet.Add(xmlschema); document.Schemas.Add(schemaSet); try { ValidationEventHandler eventHandler = new ValidationEventHandler(ValidationEventHandler); document.Validate(eventHandler); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.Read(); } 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; } } } }
Error: 必要な属性 'ISBN' が見つかりません。 Error: 要素 名前空間 'http://www.contoso.com/books' の 'book' には無効な子要素 名前空間 'http://www.contoso.com/books' の 'authorr' が含まれています。必要とされる要素は 名前空間 'http://www.contoso.com/books' の 'author' です。 Error: 要素 名前空間 'http://www.contoso.com/books' の 'bookstore' には無効な子要素 名前空間 'http://www.contoso.com/books' の 'books' が含まれています。必要とされる要素は 名前空間 'http://www.contoso.com/books' の 'book' です。