2010-12-07 26 views
5

J'ai un schéma défini comme suit:C# sérialisation xsi: type et xsd

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema id="Books" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> 
    <xs:element name="Books" msdata:IsDataSet="true" msdata:Locale="en-US"> 
    <xs:complexType> 
     <xs:choice minOccurs="0" maxOccurs="unbounded"> 
     <xs:element name="Book" type="MyBookType"></xs:element> 
     </xs:choice> 
    </xs:complexType> 
    </xs:element> 

    <xs:complexType name="MyBookType"> 
    ... 
    </xs:complexType> 

</xs:schema> 

En utilisant ce schéma et xsd.exe, je générer les classes qui seront utilisées pendant la sérialisation. La classe générée par le schéma ci-dessus produit le code XML suivant lorsque sérialisé:

<Books> 
    <Book> 
    ... 
    </Book> 
</Books> 

Ce fichier XML est utilisé dans une requête SOAP et le service à l'autre bout attend le code XML suivant:

<Books> 
    <Book xsi:type="MyBookType"> 
    ... 
    </Book> 
</Books> 

Comment puis-je modifier mon schéma de sorte que l'attribut xsi: type soit inclus dans le xml sérialisé?

Répondre

5

Utilisez un type dérivé et un attribut XmlInclude. Par exemple:

public class Book 
{ 
    public string Title; 
    public string Author; 
} 

public class MyBookType : Book { } 

[XmlInclude(typeof(MyBookType))] 
[XmlRoot("Books")] 
public class Books : List<Book> { } 

public void Run() 
{ 
    var b = new Books(); 
    b.Add(new MyBookType 
     { 
      Title = "The Art of War", 
      Author = "Sun Tzu" 
     }); 
    b.Add(new MyBookType 
     { 
      Title = "Great Expectations", 
      Author = "Charles Dickens" 
     }); 

    var s = new XmlSerializer(typeof(Books)); 
    s.Serialize(Console.Out, b); 
} 

L'exécution de ce produit cette sortie:

<?xml version="1.0" encoding="IBM437"?> 
<Books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Book xsi:type="MyBookType"> 
    <Title>The Art of War</Title> 
    <Author>Sun Tzu</Author> 
    </Book> 
    <Book xsi:type="MyBookType"> 
    <Title>Great Expectations</Title> 
    <Author>Charles Dickens</Author> 
    </Book> 
</Books> 

Puisque vous utilisez une requête SOAP, je suppose ASMX, ce qui signifie que la sérialisation arrive implicitement. Vous devrez appliquer [XmlInclude] à tout ce qui détient la collection de livres. Cela pourrait être un paramètre dans un webmethod, par exemple.

Vous pouvez générer automatiquement l'attribut XmlInclude approprié, à partir de XSD et WSDL, si vous définissez les types dans XSD, avec la relation d'héritage que j'ai illustrée dans le code C#.

En WSDL, le message de demande peut prendre un type Books, qui est une collection de Book. Séparément, définissez un MyBookType qui dérive de Book mais ne l'étend pas.