XmlSerializer Сериализует пустую переменную, чтобы использовать оба тега? - PullRequest
5 голосов
/ 31 октября 2008

Я хочу иметь возможность загружать сериализованный класс xml в Soap Envelope. Я начинаю, поэтому я не заполняю внутренности, поэтому это выглядит так:

<Envelope    
xmlns="http://schemas.xmlsoap.org/soap/envelope/" /> 

Я хочу, чтобы это выглядело как:

<Envelope    
xmlns="http://schemas.xmlsoap.org/soap/envelope/" ></Envelope>`


Класс, который я написал, таков:

[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/",ElementName="Envelope", IsNullable = true)]
public class TestXmlEnvelope
{
  [System.Xml.Serialization.XmlElement(ElementName="Body", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
  public System.Collections.ArrayList Body = new System.Collections.ArrayList();
} //class TestXmlEnvelope`

Я использую это в качестве примера, поскольку другие люди могут захотеть это в отдельном элементе. Я уверен, что это должно быть просто, но, к сожалению, я не знаю подходящего ключевого слова для этого.

Как всегда, спасибо за вашу помощь.

[Редактировать] Ошибка возникает, когда я пытаюсь использовать эту инструкцию

System.Xml.Serialization.XmlSerializer xmlout = new System.Xml.Serialization.XmlSerializer(typeof(TestXmlEnvelope));
System.IO.MemoryStream memOut = new System.IO.MemoryStream();
xmlout.Serialize(memOut, envelope, namespc);
Microsoft.Web.Services.SoapEnvelope soapEnv = new Microsoft.Web.Services.SoapEnvelope();
soapEnv.Load(memOut);

Это дает мне ошибку "Корневой элемент не найден".

[Edit] Я исправил ошибку, проблема в том, что после сериализации объекта я не установил memOut.Position = 0. Тем не менее, я надеюсь, что этот вопрос поможет другим людям, которые могут захотеть сделать это.

Ответы [ 3 ]

11 голосов
/ 31 октября 2008

Основная проблема заключается в том, что XmlSerializer вызывает WriteEndElement() на XmlWriter, когда записывается конечный тег. Это, однако, генерирует сокращенную форму <tag/>, когда нет содержимого. WriteFullEndElement() записывает конечный тег отдельно.

Вы можете вставить свой собственный XmlTextWriter в середину, который затем будет использовать сериализатор для демонстрации этой функциональности.

Учитывая, что serializer является подходящим XmlSerializer, попробуйте это:

public class XmlTextWriterFull : XmlTextWriter
{
    public XmlTextWriterFull(TextWriter sink) : base(sink) { }

    public override void WriteEndElement()
    {
        base.WriteFullEndElement();
    }
}

...

var writer = new XmlTextWriterFull(innerwriter);
serializer.Serialize(writer, obj);

[Edit] для случая добавленного вами кода, добавьте конструкторы фасадов для:

public XmlTextWriterFull(Stream stream, Encoding enc) : base(stream, enc) { }
public XmlTextWriterFull(String str, Encoding enc) : base(str, enc) { }

Затем используйте поток памяти в качестве внутреннего потока в конструкторе, как и раньше:

System.IO.MemoryStream memOut = new System.IO.MemoryStream();
XmlTextWriterFull writer = new XmlTextWriterFull(memOut, Encoding.UTF8Encoding); //Or the encoding of your choice
xmlout.Serialize(writer, envelope, namespc);
1 голос
/ 29 июля 2009

Примечание для записи: OP использовал класс *** Microsoft. *** Web.Services.SoapEnvelope , который является частью чрезвычайно устаревшего продукта WSE 1.0. Этот класс является производным от класса XmlDocument, поэтому возможно, что те же проблемы были бы замечены с XmlDocument.

Ни при каких обстоятельствах WSE не следует использовать для какой-либо новой разработки, и, если она уже используется, код должен быть перенесен как можно скорее. WCF или ASP.NET Web API - единственные технологии, которые следует использовать для веб-служб .NET в будущем.

0 голосов
/ 31 октября 2008

Два представления эквивалентны. Зачем вам нужно, чтобы оно появилось в последней форме?

...