C # 'da referans alınan XSD'ye göre XML doğrulama


161

Böyle bir şema konumu olan bir XML dosyası var:

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

C # ile doğrulamak istiyorum. Visual Studio, dosyayı açtığımda, şemaya karşı doğrular ve hataları mükemmel bir şekilde listeler. Her nasılsa, yine de, böyle doğrulamak için şema belirtmeden C # otomatik olarak doğrulamak gibi görünmüyor:

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 dosyasında belirtilen şema ile otomatik olarak doğrulayamamam gerekir mi? Neyi kaçırıyorum ?


1
MSDN örneğine bakın: msdn.microsoft.com/en-us/library/…

Yanıtlar:


167

Bir XmlReaderSettings örneği oluşturmanız ve bunu oluştururken bunu XmlReader'ınıza geçirmeniz gerekir. Ardından ValidationEventHandler, doğrulama hatalarını almak için ayarlardaki öğesine abone olabilirsiniz . Kodunuz şöyle görünecektir:

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 olmasına rağmen usingtamlık için madde kullanmak üzere güncellenmelidir :)
IAbstract

55
Bir XSD dosyasıyla karşılaştırmak istiyorsanız yukarıdaki kodu aşağıdaki satırı ekleyin: settings.Schemas.Add ("YourDomainHere", "yourXSDFile.xsd");
Jeff Fol

5
Hatanın Satır # ve konum #larını almak için sadece şunu kullanın: args.Exception.LineNumber ... ValidationCallBack
user610064 21:12

1
Sahip olduğum şemanın bir ad alanı yoksa ne olur?
ağaç

1
Kullanılması lambda , daha iyi IMHO, daha netlik kodu settings.ValidationEventHandler += (o, args) => { errors = true; // More code };
Kiquenet

107

.NET 3.5 kullanıyorsanız, basit bir yöntem kullanmak XDocumentve XmlSchemaSetdoğrulamaktır.

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

Daha fazla yardım için MSDN belgelerine bakın .


2
Bu yöntem, satır içi şemayı xml'den almak yerine önceden şemayı bilmenizi gerektirir.
Lankymart

Bu iyi çalışır ama xml belgesi <ca>> benim <i> yeni </i> katalog .... </catalog> gibi bazı html etiketi içerdiğinde hata atar yukarıdaki durumda "<i>" gibi html etiketleri bir sorun oluşturur "<catalog>" ... değeri nasıl doğrulanır
Anil Purswani

6
@AnilPurswani: HTML'yi bir XML belgesine koymak istiyorsanız, bunu CDATA içine sarmanız gerekir. <catalog><![CDATA[my <i> new </i> catalog....]]></catalog>bunu yapmanın doğru yoludur.
p0lar_bear

Basit ve zarif! Bu, sabit bir şema kümesine (bizim durumumuz ve birden çok klasör ve dosya içeren büyük bir küme) doğrularken çok iyi çalışır. Zaten Validator çağrıları arasında yeniden kullanılmak üzere XmlSchemaSet önbelleğe düşünüyorum. Çok teşekkürler!
Adail Retamal

20

Aşağıdaki örnek bir XML dosyasını doğrular ve uygun hata veya uyarıyı oluşturur.

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

    }
}

Yukarıdaki örnekte aşağıdaki girdi dosyaları kullanılmaktadır.

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

Şahsen ben bir geri arama olmadan doğrulama lehine:

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

( Eşzamanlı XML Şeması Doğrulaması? .NET 3.5'teki Timiz0r'ın gönderisine bakın )


9
Geri arama, xml'nizdeki hangi satırın doğru olmadığı hakkında bazı ek bilgiler sağlar. Bu yöntem çok ikili, doğru ya da yanlış :)
FrankyHollywood

13

VB otomatik doğrulama bu tür yaptım ve bu nasıl (C # dönüştürülür) yaptım:

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

Sonra settings.ValidationEventHandlerdosyayı okurken etkinliğe abone oldum .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.