Xác thực XML dựa trên XSD được tham chiếu trong C #


161

Tôi có một tệp XML với một vị trí lược đồ được chỉ định như thế này:

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

Tôi muốn xác nhận trong C #. Visual Studio, khi tôi mở tệp, xác nhận nó dựa vào lược đồ và liệt kê các lỗi một cách hoàn hảo. Tuy nhiên, bằng cách nào đó, tôi dường như không thể xác thực nó tự động trong C # mà không chỉ định lược đồ để xác thực như vậy:

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

Tôi có thể tự động xác thực với lược đồ được chỉ định trong tệp XML không? Tôi đang thiếu gì?


1
Tham khảo mẫu MSDN: msdn.microsoft.com/en-us/l

Câu trả lời:


167

Bạn cần tạo một cá thể XmlReaderSinstall và chuyển nó cho XmlReader của bạn khi bạn tạo nó. Sau đó, bạn có thể đăng ký ValidationEventHandlervào phần cài đặt để nhận lỗi xác thực. Mã của bạn sẽ trông như thế này:

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 mặc dù nên cập nhật để sử dụng usingmệnh đề cho hoàn chỉnh :)
Tôi chấp nhận

55
Nếu bạn đang tìm cách so sánh với tệp XSD, hãy thêm dòng sau vào đoạn mã trên: settings.Soolas.Add ("YourDomainHere", "yourXSDFile.xsd");
Jeff Fol

5
Để nhận Dòng # và vị trí # của lỗi, chỉ cần sử dụng: args.Exception.LineNumber ... trong ValidationCallBack
user610064

1
Điều gì xảy ra nếu lược đồ tôi không có không gian tên?
cây

1
Sử dụng lambda , IMHO tốt hơn, mã rõ ràng hơnsettings.ValidationEventHandler += (o, args) => { errors = true; // More code };
Kiquenet

107

Một cách đơn giản hơn, nếu bạn đang sử dụng .NET 3.5, là sử dụng XDocumentXmlSchemaSetxác nhận.

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

Xem tài liệu MSDN để được hỗ trợ thêm.


2
Phương pháp đó yêu cầu bạn biết trước lược đồ thay vì lấy lược đồ nội tuyến từ xml.
Lankymart

điều này hoạt động tốt nhưng sẽ xuất hiện lỗi khi tài liệu xml chứa một số thẻ html như <catalog> danh mục <i> mới </ i> của tôi .... </ catalog> trong trường hợp các thẻ html như "<i>" tạo ra một vấn đề như đó là giá trị của "<catalog>" ... làm thế nào để xác nhận nó
Anil Purswani

6
@AnilPurswani: Nếu bạn muốn đưa HTML vào tài liệu XML, bạn cần phải bọc nó trong CDATA. <catalog><![CDATA[my <i> new </i> catalog....]]></catalog>là cách chính xác để làm điều đó.
p0lar_bear

Đơn giản và thanh lịch! Điều này hoạt động rất tốt khi xác thực với một bộ lược đồ cố định (đó là trường hợp của chúng tôi và một lược đồ lớn có nhiều thư mục và tệp). Tôi đã suy nghĩ về việc lưu trữ XmlSchemaSet để được sử dụng lại giữa các cuộc gọi đến Trình xác thực. Cảm ơn rất nhiều!
Adail Retamal

20

Ví dụ sau xác thực một tệp XML và tạo ra lỗi hoặc cảnh báo thích hợp.

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

    }
}

Ví dụ trước sử dụng các tệp đầu vào sau.

<?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>

sách.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

cá nhân tôi ủng hộ xác nhận mà không cần gọi lại:

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

(xem bài đăng của Timiz0r trong Xác thực Lược đồ XML đồng bộ? .NET 3.5 )


9
Cuộc gọi lại cung cấp cho bạn một số thông tin bổ sung về dòng nào trong xml của bạn không chính xác. Phương pháp này rất nhị phân, đúng hoặc sai :)
FrankyHollywood

13

Tôi đã thực hiện loại xác nhận tự động này trong VB và đây là cách tôi đã thực hiện (được chuyển đổi thành C #):

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

Sau đó, tôi đăng ký vào settings.ValidationEventHandlersự kiện trong khi đọc các tập tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.