2009-04-15 17 views
127

Ho un file XML con una posizione schema specificato come questo:Convalida di un XML contro XSD si fa riferimento in C#

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

voglio per convalidare in C#. Visual Studio, quando apro il file, lo convalida sullo schema e elenca perfettamente gli errori. In qualche modo, però, non posso sembra convalidare automaticamente in C# senza specificare lo schema per convalidare contro in questo modo:

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

non dovrei essere in grado di convalidare con lo schema specificato nel file XML automaticamente? Cosa mi manca?

+1

consultare il campione MSDN: http://msdn.microsoft.com/en -us/library/system.xml.schema.validationeventargs.severity.aspx –

risposta

143

È necessario creare un'istanza XmlReaderSettings e passarla a XmlReader quando viene creata. Quindi è possibile abbonarsi allo ValidationEventHandler nelle impostazioni per ricevere errori di convalida. Il tuo codice finirà per assomigliare a questo:

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

    } 
} 
+3

+1 anche se dovrebbe aggiornare per usare la clausola 'using' per completezza :) – IAbstract

+41

Se stai cercando di confrontarti con un file XSD aggiungi la seguente g linea al codice precedente: settings.Schemas.Add ("YourDomainHere", "yourXSDFile.xsd"); –

+5

Per ottenere la riga # e la posizione # dell'errore, utilizzare semplicemente: args.Exception.LineNumber ... in ValidationCallBack – user610064

13

ho avuto fare questo tipo di convalida automatica in VB e questo è come ho fatto (convertito in C#):

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

Poi ho sottoscritto alla manifestazione settings.ValidationEventHandler durante la lettura del file.

15

Il seguente example convalida un file XML e genera l'errore o avviso al riguardo.

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

    } 
} 

L'esempio precedente utilizza i seguenti file di input.

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

Uso il codice per _validate XML_. _permettere RCL.xml per fallire la convalida contro DCL.xsd, ma la convalida è OK_, non fallire. [Files (1 xsd, 2 xml)] (https://gist.github.com/kiquenet/86090779650975b7426a7f798174eef6) Ho aggiunto questo codice 'settings.ValidationFlags | = XmlSchemaValidationFlags.ReportValidationWarnings;' e ora *** funziona ** * – Kiquenet

78

Un modo più semplice, se si utilizza .NET 3.5, è quello di utilizzare XDocument e XmlSchemaSet convalida.

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

Vedere la MSDN documentation per ulteriore assistenza.

+2

Questo metodo richiede di conoscere lo schema in anticipo piuttosto che prendere lo schema in linea dal xml. – Lankymart

+5

Inoltre visualizza solo il * ultimo messaggio * sulla convalida - ho cambiato la convalida per concatenare loro: doc.Validate (schemi, (o, ep) => { msg + = + Environment.NewLine ep.Message; }); –

+0

questo funziona bene, ma genera un errore quando il documento XML contiene alcuni tag HTML come mia nuovo catalogo .... in cui sopra i tag html caso come "" crea un problema in quanto è il valore di "" ... come convalidarlo –

10

personalmente favorire la convalida senza un callback:

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

(vedi post del Timiz0r in Synchronous XML Schema Validation? .NET 3.5)

+2

Il callback fornisce alcune informazioni aggiuntive su quale riga nel tuo xml non è corretta. Questo metodo è molto binario, giusto o sbagliato :) – FrankyHollywood

+0

Io uso il tuo codice e [questo] (https://satalketo.com/2013/09/15/validating-xml-against-xsd) per validare XML. Mi aspetto *** *** RCL.xml per fallire la convalida contro *** DCL.xsd ***, ma la validazione è OK, non fallire. Provo a utilizzare 7 diversi metodi per *** convalidare XML usando XSD ***, ma non tutti funzionano per me. File (1 xsd, 2 xml) e codice C# completo qui: https://gist.github.com/kiquenet/86090779650975b7426a7f798174eef6 – Kiquenet

Problemi correlati