2010-12-07 20 views
5

Tengo un esquema define como sigue:C# serializar xsi: type y 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> 

El uso de este esquema y xsd.exe, I generar las clases que se utilizarán durante la serialización. La clase generada por el esquema anterior produce el siguiente XML cuando serializado:

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

este XML se utiliza en una petición SOAP y el servicio en el otro extremo espera el siguiente código XML:

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

Cómo ¿Puedo editar mi esquema para que el atributo xsi: type se incluya en el xml serializado?

Respuesta

5

Utilice un tipo derivado y un atributo XmlInclude. Por ejemplo:

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

La ejecución de este produce esta salida:

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

Dado que está utilizando una petición SOAP, estoy asumiendo ASMX, lo que significa que la serialización sucede de manera implícita. Deberá aplicar [XmlInclude] a lo que contenga la colección de libros. Esto podría ser un parámetro en un método web, por ejemplo.

Puede generar automáticamente el atributo XmlInclude apropiado, comenzando por XSD y WSDL, si define los tipos en XSD, con la relación de herencia que ilustré en el código C#.

En WSDL, el mensaje de solicitud puede tomar un tipo Books, que es una colección de Book. Por separado, defina un MyBookType que se deriva de Libro pero no lo extiende.