Десериализовать мыльное сообщение - PullRequest
3 голосов
/ 26 апреля 2011

у меня есть один провайдер extern, который отправляет мне этот xml для теста

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
   <AVCabeza transactionID="000032" xmlns="http://webservices.patito/Core/">
   <Solicitor entityID="WEST" systemType="WEB" />   
  </AVCabeza>
</soap:Header>
<soap:Body>
    <Availability xmlns:a="http://webservices.patito/Availability/" 
      xmlns:hc="http://webservices.patito/Common/" summaryOnly="true" 
      xmlns="http://webservices.patito/og/Availability.wsdl">
     <a:AvailabilityDetail availReqType="Room">
       <a:Estadia>
        <hc:StartDate>2009-01-05T00:00:00.0000000-05:00</hc:StartDate>
          <hc:EndDate>2009-01-06T00:00:00.0000000-05:00</hc:EndDate>
       </a:Estadia>
       <a:HotelSearchCriteria>              
            <a:HotelRef chainCode="WC"/>            
       </a:HotelSearchCriteria>
      </a:AvailabilityDetail>
     </Availability>
  </soap:Body>
</soap:Envelope>

Я хочу десериализатор, поэтому я сделал это

1) я использовал xsd для генерации класса c #

2) Создайте новую библиотеку классов проекта с генерацией классов.

Структура

WebServicesExterns (Проект) -> Услуги (Папка) ---> все класс

пример

namespace WebServicesExterns.Services

<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42"), _
 System.SerializableAttribute(), _
 System.Diagnostics.DebuggerStepThroughAttribute(), _
 System.ComponentModel.DesignerCategoryAttribute("code"), _
 System.Xml.Serialization.XmlTypeAttribute([Namespace]:="http://webservices.patito/Availability.wsdl")> _
Partial Public Class Availability




'''<comentarios/>
<System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42"),  _
System.SerializableAttribute(),  _
System.Diagnostics.DebuggerStepThroughAttribute(),  _
System.ComponentModel.DesignerCategoryAttribute("code"),  _
System.Xml.Serialization.XmlTypeAttribute([Namespace]:="http://webservices.patito/Core/"),  _
System.Xml.Serialization.XmlRootAttribute([Namespace]:="http://webservices.patito/Core/", IsNullable:=false)>  _
Partial Public Class AVCabeza

3) После создания тестового класса попробуйте десериализатор

using WebServicesExterns.Services;
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Runtime.Remoting;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
using NUnit.Framework;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Soap;


    [Test()]
    public void ShouldDeserializerSoapMessage()
    {
        var message = SoapToFromFile(@"C:\rq\Availability.xml");
        Assert.IsNotNull(message);
    }


    public object SoapToFromFile(string filePath)
    {
        IFormatter formatter;
        FileStream fileStream = null;
        Object objectFromSoap = null;            

        try
        {
            fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            formatter = new SoapFormatter();
            objectFromSoap = formatter.Deserialize(fileStream);
        }
        catch (Exception exception)
        {
            throw exception;
        }
        finally
        {
            if (fileStream != null) fileStream.Close();
        }
        return objectFromSoap;
    }

Итак, верните эту ошибку

Ошибка разбора, сборка, связанная с ключом Xml, "AVCabeza" "_P1"

отсутствует

Отладка Я обнаружил, что _P1 равно "http://webservices.patito/Core/"

Видимо не найдено "Типа" класса AVCabeza

Что не так?

Новое обновление

Смотри, что провайдер дал мне

одна папка с такой структурой

root
|
--  WSDL_XSD
|    |-XSD
|    |   files with extension .xsd
|    | 
|    --WS
|        files with extension .wsdl
|-- XMLSamples
     |-files with xml extension that contain soap messsages

хорошо, я удаляю xml (предыдущий пример) голову

<?xml version="1.0" encoding="utf-8"?>
<Availability xmlns:a="http://webservices.patito/Availability/" 
      xmlns:hc="http://webservices.patito/Common/" summaryOnly="true" 
      xmlns="http://webservices.patito/og/Availability.wsdl">
     <a:AvailabilityDetail availReqType="Room">
       <a:Estadia>
        <hc:StartDate>2009-01-05T00:00:00.0000000-05:00</hc:StartDate>
          <hc:EndDate>2009-01-06T00:00:00.0000000-05:00</hc:EndDate>
       </a:Estadia>
       <a:HotelSearchCriteria>              
            <a:HotelRef chainCode="WC"/>            
       </a:HotelSearchCriteria>
      </a:AvailabilityDetail>
</Availability>

и попытается получить десериализуемый объект доступности, но потеряет эту отметку

not expected "<Availability .."

теперь в wsdl_xsd -> ws -> ws, я вижу, что доступность существует, поэтому я думаю, что доступность переносится в деталь доступности (реальный запрос), который является объектом, который я не могу удалить тег доступности, потому что у него есть пробелы пространства имен для дочерних тегов

что думаете по этому поводу?

возможно, если я удаляю доступность и вставляю пространства имен (каким-то образом), я мог бы получить свой десериализаторный объект

Ответы [ 2 ]

3 голосов
/ 26 апреля 2011

SoapFormatter не является сериализатором XML.Вы должны использовать класс XmlSerializer.

Кроме того, это полное сообщение SOAP.Было бы лучше, если бы они дали вам WSDL и использовали «Add Service Reference».Это даст вам классы, которые будут выполнять сериализацию и десериализацию для вас.

2 голосов
/ 29 апреля 2011

Когда вы используете xsd.exe для генерации классов C # из этого XML-документа, на первом шаге вы получите 5 отдельных файлов .xsd, предоставляя схему XSD, "выведенную" из сообщения.(Существует множество XSD-файлов, поскольку в этом сообщении вы используете множество пространств имен XML)

В частности, XSD.exe сгенерирует код для описания конверта SOAP, включая тело и заголовок.Вероятно, это не то, что вы хотите или должны делать, но инструмент xsd.exe выводит типы для всего XML-документа.

Кроме того, механизм вывода в xsd.exe является неточным.Например, дочерние элементы StartDate и EndDate элемента Estadia выглядят как даты.Но xsd.exe не сделает этого предположения;он сгенерирует схему XML, которая помечает эти вещи как строки .Существуют и другие подобные предположения, которые делает xsd.exe при выводе.Во всех случаях вы, вероятно, захотите изменить сгенерированные файлы xsd, чтобы они соответствовали вашим ожиданиям.В случае StartDate и EndDate вы хотите изменить тип с xs:string на xs:dateTime.

В этот момент вы можете снова запустить xsd.exe в файлах .xsd, используя ключ / c, для генерации исходного кода .cs.Скомпилируйте , что , чтобы получить классы, которые можно использовать в сериализации.

Чтобы десериализовать с использованием этого сгенерированного кода, вы должны сделать что-то вроде этого:

  XmlSerializer s1 = new XmlSerializer(typeof(Carlos.Envelope));
  Envelope envelope = null;
  using(var reader= System.IO.File.OpenText("SampleMessage.xml"))
  {
      envelope = (Envelope) s1.Deserialize(reader);
  }

Затем вы можете открыть этот объект Envelope и получить различные данные в нем.


Отступая, вы можете видеть, что вам, вероятно, не следует этого делать.Полезно и удобно видеть пример сообщения, чтобы показать вам, как все должно выглядеть на проводе.Но при создании кода для обработки классов, которые сериализуются в эти сообщения, лучше начинать с исходного XSD - который, вероятно, доступен на стороне службы.Это то, что сказал Джон Сондерс в своем ответе.

Если ваши сотрудники могут создать пример сообщения, у них, вероятно, есть XSD (или WSDL, что эквивалентно) для этого сообщения.Это избавит вас от необходимости выводить xsd, а затем изменить его, чтобы изменить неверные предположения, через неточный процесс, который я описал выше.

Единственный раз, когда вам нужно будет это сделать, - это если вы каким-то образомпотерял оригинальный XSD / WSDL, и вам нужно было его восстановить.

...