การตรวจสอบ XML กับ XSD ที่อ้างอิงใน C #


161

ฉันมีไฟล์ XML พร้อมตำแหน่งสคีมาที่ระบุเช่นนี้:

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

ฉันต้องการตรวจสอบใน C # Visual Studio เมื่อฉันเปิดไฟล์ตรวจสอบมันกับ schema และแสดงรายการข้อผิดพลาดอย่างสมบูรณ์ อย่างไรก็ตามอย่างใดฉันไม่สามารถตรวจสอบได้โดยอัตโนมัติใน C # โดยไม่ต้องระบุสคีมาเพื่อตรวจสอบเช่น:

XmlDocument asset = new XmlDocument();

XmlTextReader schemaReader = new XmlTextReader("relativeSchemaPath");
XmlSchema schema = XmlSchema.Read(schemaReader, SchemaValidationHandler);

asset.Schemas.Add(schema);

asset.Load(filename);
asset.Validate(DocumentValidationHandler);

ฉันไม่ควรตรวจสอบกับสคีมาที่ระบุในไฟล์ XML โดยอัตโนมัติหรือไม่ ฉันพลาดอะไรไป


1
ดูตัวอย่าง MSDN: msdn.microsoft.com/en-us/library/…

คำตอบ:


167

คุณต้องสร้างอินสแตนซ์ XmlReaderSettings และส่งผ่านไปยัง XmlReader ของคุณเมื่อคุณสร้าง จากนั้นคุณสามารถสมัครสมาชิกValidationEventHandlerในการตั้งค่าเพื่อรับข้อผิดพลาดในการตรวจสอบ รหัสของคุณจะมีลักษณะดังนี้:

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);

    }
}

4
+1 แม้ว่าควรอัปเดตเพื่อใช้usingส่วนคำสั่งเพื่อความสมบูรณ์ :)
IAbstract

55
หากคุณต้องการเปรียบเทียบกับไฟล์ XSD ให้เพิ่มบรรทัดต่อไปนี้ลงในโค้ดด้านบน: settings.Schemas.Add ("YourDomainHere", "yourXSDFile.xsd");
Jeff Fol

5
ในการรับบรรทัด # และตำแหน่ง # ของข้อผิดพลาดให้ใช้: args.Exception.LineNumber ... ใน ValidationCallBack
user610064

1
เกิดอะไรขึ้นถ้าคีมาที่ฉันไม่มีเนมสเปซ
ต้นไม้

1
การใช้แลมบ์ดา IMHO ที่ดียิ่งขึ้นรหัสความคมชัดที่ settings.ValidationEventHandler += (o, args) => { errors = true; // More code };
Kiquenet

107

วิธีที่ง่ายกว่าถ้าคุณใช้. NET 3.5 คือการใช้XDocumentและXmlSchemaSetการตรวจสอบความถูกต้อง

XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(schemaNamespace, schemaFileName);

XDocument doc = XDocument.Load(filename);
string msg = "";
doc.Validate(schemas, (o, e) => {
    msg += e.Message + Environment.NewLine;
});
Console.WriteLine(msg == "" ? "Document is valid" : "Document invalid: " + msg);

ดูเอกสารประกอบ MSDNสำหรับความช่วยเหลือเพิ่มเติม


2
วิธีการนั้นต้องการให้คุณรู้สคีมาล่วงหน้าแทนที่จะรับสคีอินแบบอินไลน์จาก xml
Lankymart

สิ่งนี้ทำงานได้ดี แต่มีข้อผิดพลาดเมื่อเอกสาร xml มีแท็ก html บางอย่างเช่น <catalog> แคตตาล็อก <i> ใหม่ </i> ของฉัน .... </catalog> ในแท็ก html ของกรณีข้างต้นเช่น "<i>" สร้างปัญหาเป็น มันคือค่าของ "<catalog>" ... วิธีการตรวจสอบ
Anil Purswani

6
@AnilPurswani: หากคุณต้องการใส่ HTML ลงในเอกสาร XML คุณจะต้องล้อมด้วย CDATA <catalog><![CDATA[my <i> new </i> catalog....]]></catalog>เป็นวิธีที่ถูกต้องในการทำเช่นนั้น
p0lar_bear

เรียบง่ายและสง่างาม! สิ่งนี้ทำงานได้ดีมากเมื่อตรวจสอบความถูกต้องกับชุดสคีมาคงที่ (ซึ่งเป็นกรณีของเราและชุดใหญ่ที่มีหลายโฟลเดอร์และไฟล์) ฉันกำลังคิดเกี่ยวกับการแคช XmlSchemaSet เพื่อนำมาใช้ซ้ำระหว่างการโทรไปยัง Validator ขอบคุณมาก!
Adail Retamal

20

ตัวอย่างต่อไปนี้ตรวจสอบความถูกต้องของไฟล์ XML และสร้างข้อผิดพลาดหรือคำเตือนที่เหมาะสม

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

public class Sample
{

    public static void Main()
    {
        //Load the XmlSchemaSet.
        XmlSchemaSet schemaSet = new XmlSchemaSet();
        schemaSet.Add("urn:bookstore-schema", "books.xsd");

        //Validate the file using the schema stored in the schema set.
        //Any elements belonging to the namespace "urn:cd-schema" generate
        //a warning because there is no schema matching that namespace.
        Validate("store.xml", schemaSet);
        Console.ReadLine();
    }

    private static void Validate(String filename, XmlSchemaSet schemaSet)
    {
        Console.WriteLine();
        Console.WriteLine("\r\nValidating XML file {0}...", filename.ToString());

        XmlSchema compiledSchema = null;

        foreach (XmlSchema schema in schemaSet.Schemas())
        {
            compiledSchema = schema;
        }

        XmlReaderSettings settings = new XmlReaderSettings();
        settings.Schemas.Add(compiledSchema);
        settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack);
        settings.ValidationType = ValidationType.Schema;

        //Create the schema validating reader.
        XmlReader vreader = XmlReader.Create(filename, settings);

        while (vreader.Read()) { }

        //Close the reader.
        vreader.Close();
    }

    //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);

    }
}

ตัวอย่างก่อนหน้านี้ใช้ไฟล์อินพุตต่อไปนี้

<?xml version='1.0'?>
<bookstore xmlns="urn:bookstore-schema" xmlns:cd="urn:cd-schema">
  <book genre="novel">
    <title>The Confidence Man</title>
    <price>11.99</price>
  </book>
  <cd:cd>
    <title>Americana</title>
    <cd:artist>Offspring</cd:artist>
    <price>16.95</price>
  </cd:cd>
</bookstore>

books.xsd

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="urn:bookstore-schema"
    elementFormDefault="qualified"
    targetNamespace="urn:bookstore-schema">

 <xsd:element name="bookstore" type="bookstoreType"/>

 <xsd:complexType name="bookstoreType">
  <xsd:sequence maxOccurs="unbounded">
   <xsd:element name="book"  type="bookType"/>
  </xsd:sequence>
 </xsd:complexType>

 <xsd:complexType name="bookType">
  <xsd:sequence>
   <xsd:element name="title" type="xsd:string"/>
   <xsd:element name="author" type="authorName"/>
   <xsd:element name="price"  type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute name="genre" type="xsd:string"/>
 </xsd:complexType>

 <xsd:complexType name="authorName">
  <xsd:sequence>
   <xsd:element name="first-name"  type="xsd:string"/>
   <xsd:element name="last-name" type="xsd:string"/>
  </xsd:sequence>
 </xsd:complexType>

</xsd:schema>

18

ส่วนตัวฉันชอบการตรวจสอบโดยไม่ต้องโทรกลับ:

public bool ValidateSchema(string xmlPath, string xsdPath)
{
    XmlDocument xml = new XmlDocument();
    xml.Load(xmlPath);

    xml.Schemas.Add(null, xsdPath);

    try
    {
        xml.Validate(null);
    }
    catch (XmlSchemaValidationException)
    {
        return false;
    }
    return true;
}

(ดูโพสต์ของ Timiz0r ในการตรวจสอบความถูกต้อง XML Schema หรือไม่. NET 3.5 )


9
การโทรกลับให้ข้อมูลเพิ่มเติมเกี่ยวกับบรรทัดใน xml ที่ไม่ถูกต้อง วิธีนี้เป็นวิธีไบนารีมากทั้งที่ถูกหรือผิด :)
FrankyHollywood

13

ฉันได้ทำการตรวจสอบอัตโนมัติใน VB และนี่คือวิธีที่ฉันทำ (แปลงเป็น C #):

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.ValidationFlags = settings.ValidationFlags |
                           Schema.XmlSchemaValidationFlags.ProcessSchemaLocation;
XmlReader XMLvalidator = XmlReader.Create(reader, settings);

จากนั้นฉันสมัครรับข้อมูลsettings.ValidationEventHandlerกิจกรรมในขณะที่อ่านไฟล์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.