XmlSerializer Serializar variable vacía para usar ambas etiquetas?
-
05-07-2019 - |
Pregunta
Quiero poder cargar una clase xml serializada en un Soap Envelope. Estoy empezando, así que no estoy llenando las entrañas, por lo que parece que:
<Envelope
xmlns="http://schemas.xmlsoap.org/soap/envelope/" />
Quiero que aparezca como:
<Envelope
xmlns="http://schemas.xmlsoap.org/soap/envelope/" ></Envelope>`
La clase que escribí es esta:
[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`
Estoy usando esto como ejemplo, ya que otras personas pueden quererlo en un elemento individual. Estoy seguro de que esto debe ser simple, pero lamentablemente no sé la palabra clave correcta para esto.
Como siempre, gracias por su ayuda.
[Editar] El error aparece cuando intento usar esta instrucción
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);
Me da error " Elemento raíz no encontrado " ;.
[Editar] Solucioné el error, el problema era que después de serializar el objeto no configuré memOut.Position = 0. Aún así, espero que esta pregunta ayude a otras personas que quieran hacer esto.
Solución
El problema principal aquí es que XmlSerializer
llama a WriteEndElement()
en XmlWriter
cuando escribiría una etiqueta final. Sin embargo, esto genera la forma abreviada <tag/>
cuando no hay contenido. WriteFullEndElement()
escribe la etiqueta final por separado.
Puede inyectar su propio XmlTextWriter
en el medio que el serializador usaría para exhibir esa funcionalidad.
Dado que serializer
es el <=> apropiado, intente esto:
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);
[Editar] para el caso de su código agregado, agregue constructores de fachada para:
public XmlTextWriterFull(Stream stream, Encoding enc) : base(stream, enc) { }
public XmlTextWriterFull(String str, Encoding enc) : base(str, enc) { }
Luego, use la secuencia de memoria como su secuencia interna en el constructor como antes:
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);
Otros consejos
Nota para el registro: El OP estaba usando el *** Microsoft . *** Clase Web.Services.SoapEnvelope , que forma parte del producto WSE 1.0 extremadamente obsoleto. Esta clase deriva de la clase XmlDocument, por lo que es posible que se hayan visto los mismos problemas con XmlDocument.
Bajo ninguna circunstancia se debe usar WSE para ningún desarrollo nuevo, y si ya está en uso, el código debe migrarse lo antes posible. WCF o ASP.NET Web API son las únicas tecnologías que deberían usarse para los servicios web .NET en el futuro.
Las dos representaciones son equivalentes. ¿Por qué necesita que aparezca en la última forma?