C # сериализация xsi: тип и xsd - PullRequest
       22

C # сериализация xsi: тип и xsd

5 голосов
/ 07 декабря 2010

У меня есть схема, определенная следующим образом:

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

Используя эту схему и xsd.exe, я генерирую классы, которые будут использоваться во время сериализации. Класс, сгенерированный вышеприведенной схемой, при сериализации выдает следующий xml:

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

Этот xml используется в запросе SOAP, а служба на другом конце ожидает следующий xml:

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

Как мне отредактировать мою схему так, чтобы атрибут xsi: type был включен в сериализованный xml?

1 Ответ

5 голосов
/ 09 декабря 2010

Используйте производный тип и атрибут XmlInclude. Например:

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

Выполнение этого приводит к выводу:

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

Поскольку вы используете запрос SOAP, я предполагаю, что ASMX означает, что сериализация происходит неявно. Вам нужно будет применить [XmlInclude] к тому, что содержит коллекцию книг. Это может быть параметр в веб-методе, например.

Вы можете автоматически генерировать соответствующий атрибут XmlInclude, начиная с XSD и WSDL, если вы определяете типы в XSD с отношением наследования, которое я иллюстрировал в коде C #.

В WSDL сообщение запроса может иметь тип Books, который является набором Book. Отдельно определите MyBookType, который происходит от Book, но не расширяет его.

...