C #에서 참조 된 XSD에 대해 XML 유효성 검사


161

다음과 같은 지정된 스키마 위치를 가진 XML 파일이 있습니다.

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

C #에서 유효성을 검사하고 싶습니다. Visual Studio는 파일을 열 때 스키마에 대해 파일의 유효성을 검사하고 오류를 완벽하게 나열합니다. 그러나 어떻게 든 스키마를 지정하지 않고 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 파일에 지정된 스키마로 자동으로 유효성을 검사 할 수 없습니까? 내가 무엇을 놓치고 있습니까?


답변:


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를 사용하는 경우 더 간단한 방법은 사용 XDocumentXmlSchemaSet유효성 검사입니다.

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 문서에 <catalog> my <i> new </ i> 카탈로그와 같은 html 태그가 포함되어 있으면 오류가 발생합니다. 위의 경우 "<i>"와 같은 html 태그는 다음과 같이 문제를 만듭니다. "<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;
}

( 동기 XML 스키마 유효성 검사? .NET 3.5 의 Timiz0r의 게시물 참조 )


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.