2011-11-02 11 views
7

Sto lavorando a un progetto in cui ho bisogno di generare file XML basati su XSD nidificati. per esempio. L'ORDINE ha un riferimento a PERSON, PERSONA ha un riferimento a INDIRIZZO, ecc.Come posso risolvere l'attributo schemaLocation di un file .XSD quando tutti i file .XSD sono archiviati come risorse?

Sto creando un'istanza `XmlReaderSettings 'per convalidare l'XSD, oltre a convalidare l'XML dopo che è stato generato.

Ho aggiunto gli XSD come risorse al mio assieme. Quindi creo un'istanza XmlSchema per ogni risorsa, dal più basso al più alto e la aggiungo alla raccolta XmlReaderSettings.Schemas.

Tuttavia, questo non riesce a tentare di aggiungere uno schema che fa riferimento a un altro schema. Ricevo una XmlSchemaException: "Per la dichiarazione dell'elemento, devono essere presenti il ​​nome o l'attributo ref."

Ho incluso esempio di codice sorgente di sotto di XSD e:

ADDRESS.xsd - riferisce a Person.xsd

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema id="ADDRESS.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:element name="ADDRESS" > 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="ADDRESS1" type="xs:string"/> 
     <xs:element name="ADDRESS2" type="xs:string"/> 
     <xs:element name="CITY" type="xs:string"/> 
     <xs:element name="STATE" type="xs:string"/> 
     <xs:element name="ZIP" type="xs:string"/> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

Person.xsd

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema id="PERSON.xsd" attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xs:include schemaLocation="ADDRESS.xsd"/> 
    <xs:element name="PERSON" > 
    <xs:complexType> 
     <xs:sequence> 
     <xs:element name="L_NAME" type="xs:string"/> 
     <xs:element name="F_NAME" type="xs:string"/> 
     <xs:element name="Addresses"> 
      <xs:complexType> 
      <xs:sequence> 
       <xs:element ref="ADDRESS" minOccurs="0" maxOccurs="unbounded"/> 
      </xs:sequence> 
      </xs:complexType> 
     </xs:element> 
     </xs:sequence> 
    </xs:complexType> 
    </xs:element> 
</xs:schema> 

Campione Codice - Carica e convalida XSD's

using System; 
using System.IO; 
using System.Text; 
using System.Xml; 
using System.Xml.Schema; 
using SchemaTest.Properties; 

namespace SchemaTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      // create validation settings instance 
      var xmlReaderSettings = new XmlReaderSettings 
      { 
       ValidationType = ValidationType.Schema, 
       ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | 
            XmlSchemaValidationFlags.ProcessSchemaLocation | 
            XmlSchemaValidationFlags.ReportValidationWarnings 
      }; 

      xmlReaderSettings.ValidationEventHandler += SchemaValidationEventHandler; 

      // added XmlResourceResolver, per the accepted answer below 
      xMLReaderSettings.Schemas.XmlResolver = new XmlResourceResolver(); 

      // load schemas into validation settings instance 
      LoadSchema(xmlReaderSettings, Resources.PERSON); 

      // validate schemas 
      xmlReaderSettings.Schemas.Compile(); 

      Console.WriteLine("Press any key to continue..."); 
      Console.ReadKey(); 
     } 

     private static void LoadSchema(XmlReaderSettings xmlReaderSettings, string schemaString) 
     { 
      using (var schemaStream = new MemoryStream(Encoding.Default.GetBytes(schemaString))) 
      { 
       var schema = XmlSchema.Read(schemaStream, null); 

       try 
       { 
        xmlReaderSettings.Schemas.Add(schema); 
       } 
       catch (Exception ex) 
       { 
        Console.WriteLine("EXCEPTION: {0}", ex.Message); 
       } 
      } 
     } 

     private static void SchemaValidationEventHandler(object sender, ValidationEventArgs e) 
     { 
      Console.WriteLine("{0}: {1}", e.Severity, e.Message); 
     } 
    } 
} 

io non sono sicuro se questo ha qualcosa a che fare con il ValidationFlags, ma ho provato a rimuovere XmlSchemaValidationFlags.ProcessSchemaLocation e ancora ricevuto lo stesso errore. Ho anche provato a passare SchemaValidationEventHandler al metodo XmlSchema.Read (invece di null nel codice di esempio), e lo schema sembra essere stato creato correttamente, ma getta ancora l'eccezione quando tentano di aggiungerlo alla raccolta XmlReaderSettings.Schemas.

EDIT - 2011.11.03

ho risolto questo problema (gioco di parole) per creare il mio XmlUrlResolver discendente chiamato XmlResourceResolver, sull'esempio XmlResolver classe nella risposta accettato di seguito.

risposta

12

Per eliminare l'errore, modificare type = "Indirizzi" per nome = "Indirizzi" nel file PERSON.xsd.

È meglio utilizzare il codice seguente per ottenere gli schemi compilati. Le cose importanti sono assicurarsi di stabilire un uri di base (visto che stai leggendo da uno stream), di usare invece un XmlSchemaSet e un resolver personalizzato (per leggere i file come risorse incorporate).

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

namespace ConsoleApplication3 
{ 
    class Program 
    { 
     class XmlResolver : XmlUrlResolver 
     { 
      internal const string BaseUri = "schema://"; 

      public override object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) 
      { 
       if (absoluteUri.Scheme == "schema") 
       { 
        switch (absoluteUri.LocalPath) 
        { 
         case "/ADDRESS.xsd": 
          return new MemoryStream(Encoding.UTF8.GetBytes(Resource.ADDRESS)); 
         case "/PERSON.xsd": 
          return new MemoryStream(Encoding.UTF8.GetBytes(Resource.PERSON)); 
        } 
       } 
       return base.GetEntity(absoluteUri, role, ofObjectToReturn); 
      } 
     } 

     static void Main(string[] args) 
     { 
      using (XmlReader reader = XmlReader.Create(new StringReader(Resource.PERSON), new XmlReaderSettings(), XmlResolver.BaseUri)) 
      { 
       XmlSchemaSet xset = RetrieveSchemaSet(reader); 
       Console.WriteLine(xset.IsCompiled); 
      } 
     } 

     private static XmlSchemaSet RetrieveSchemaSet(XmlReader reader) 
     { 
      XmlSchemaSet xset = new XmlSchemaSet() { XmlResolver = new XmlResolver() }; 
      xset.Add(XmlSchema.Read(reader, null)); 
      xset.Compile(); 
      return xset; 
     } 
    } 
} 
+0

il 'XmlResolver' ha fatto il trucco. Ho usato il tuo esempio per creare il mio resolver personalizzato e ho rifattorizzato il mio codice per assegnare il resolver al mio set di schemi 'xmlReaderSettings.Schemas'. –

Problemi correlati