Десериализовать мыльное сообщение

у меня есть один внешний провайдер, который присылает мне этот 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 для создания класса С#

2) Создайте новую библиотеку классов проекта с помощью класса generate.

Структура

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 я вижу, что доступность существует, поэтому я думаю, какая доступность обернута вavailabilitydetail (реальный запрос), который является объектом, который я не могу удалить тег доступности, потому что он имеет пространство имен для дочерних тегов

что об этом думаете?

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


person Carlos Cocom    schedule 26.04.2011    source источник


Ответы (2)


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

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

person John Saunders    schedule 26.04.2011
comment
извините, я не могу добавить веб-ссылку, потому что существуют общие объекты для этой работы. Я использую 5 и 8 сервисов, и это вызывает конфликт, поэтому я создал один прокси-сервер с wsdl, который генерирует весь класс. Ну, что ж, спасибо - person Carlos Cocom; 27.04.2011
comment
Если вы создали прокси с помощью WSDL, вы сделали то же самое, что и Add Web Reference. Это означает, что вам не нужно выполнять собственную сериализацию. - person John Saunders; 27.04.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 и вам нужно его восстановить.

person Cheeso    schedule 29.04.2011
comment
спасибо Cheeso, это был провайдер, дайте мне одну папку с этим корнем -- WSDL_XSD | |-XSD (файлы с расширением .xsd) | --WS (файлы с расширением .wsdl) |-- XMLSamples (файлы с расширением xml, которые содержат мыльные сообщения) извините, если я ошибаюсь, но моя идея заключается в создании класса С# с веткой xsd get сразу после тела для запроса на получение xml и после de -сериализатор, чтобы исправить класс С# и немного поиграть с отражением. я пытаюсь и пробую и пробую одним, двумя и многими способами, но я даже не мог признать, что я новичок в этом xml. - person Carlos Cocom; 30.04.2011