5

Suponiendo un XML como esto:valor del elemento Deserialize como cadena aunque contiene contenido mixto

<my:Root xmlns:my="http://foo/bar"> 
    <my:FieldBasic>content</my:FieldBasic> 
    <my:FieldComplex> 
     <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml"> 
      <div><h1>content</h1></div> 
     </html> 
    </my:FieldComplex> 
<my:Root> 

y una clase como:

[Serializable] 
[XmlType(AnonymousType = true, Namespace = "http://foo/bar")] 
[XmlRoot(ElementName = "Root", Namespace = "http://foo/bar", IsNullable = false)] 
public class MyRoot 
{ 
    public string FieldBasic { get; set; } 
    public string FieldComplex { get; set; } 
} 

¿Cómo Deserialize <my:FieldComplex> a una cadena dentro de FieldComplex? Falla cuando encuentra el HTML dentro. Quiero que sea dame una cadena con este contenido:

<html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml"> 
    <div><h1>content</h1></div> 
</html> 

Si Declaro FieldComplex como public object FieldComplex (es decir xsd:anyType) que funciona un poco y me da una XMLNode[] dentro de la cual puedo usar.

pero necesito el FieldComplex a ser de tipo cadena para la serialización como para la serialización XML no contendrá HTML, que será como:

<my:Root xmlns:my="http://foo/bar"> 
    <my:FieldBasic>content</my:FieldBasic> 
    <my:FieldComplex>content</my:FieldComplex> 
<my:Root> 

Declarar FieldComplex como objeto insertará estos atributos en la <my:FieldComplex> elemento:

xmlns:q1="http://www.w3.org/2001/XMLSchema" p3:type="q1:string" xmlns:p3="http://www.w3.org/2001/XMLSchema-instance 

y no quiero eso. Tampoco quiero usar diferentes clases para serialización y deserialización.

Entonces, ¿es posible?

Para hacer una larga historia corta, es posible tener esta clase:

public class MyRoot 
{ 
    public string FieldBasic { get; set; } 
    public string FielComplex { get; set; } 
} 

Serialize a esto:

<my:Root xmlns:my="http://foo/bar"> 
    <my:FieldBasic>content</my:FieldBasic> 
    <my:FieldComplex>content</my:FieldComplex> 
<my:Root> 

y deserializar de esto:

<my:Root xmlns:my="http://foo/bar"> 
    <my:FieldBasic>content</my:FieldBasic> 
    <my:FieldComplex> 
     <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml"> 
      <div><h1>content</h1></div> 
     </html> 
    </my:FieldComplex> 
<my:Root> 

?

P.S. Solo para explicar "¿por qué?". Tengo una bruja de clase que se serializa. El XML serializado luego viaja a través de múltiples nodos en la aplicación y eventualmente regresa pero se altera como se muestra arriba. Las capas realizan alguna validación XML y al tener atributos o elementos adicionales en la entrada falla la validación y detiene el flujo. Quiero asignar el XML de devolución a la misma clase. El contenido es sólo cuerdas desde su punto de vista, pero, por supuesto, no es lo mismo para la serialización/deserialización :(

Respuesta

3

Esto no ha terminado porque no puedo recordar si puede/cómo agregar el prefijo del espacio de nombres al elemento raíz en Serialización Xml.Pero si se implementa la interfaz IXmlSerializable en su clase MiRaiz así:

[XmlRoot("Root", Namespace="http://foo/bar")] 
public class MyRoot : IXmlSerializable 

luego escribir los métodos de serialización XML ti mismo, algo como esto:

 void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) 
     { 
      reader.MoveToContent(); 
      var outerXml = reader.ReadOuterXml(); 
      XElement root = XElement.Parse(outerXml); 

      this.FieldBasic = root.Elements(XName.Get("FieldBasic", "http://foo/bar")).First().Value; 
      this.FieldComplex = root.Elements(XName.Get("FieldComplex", "http://foo/bar")).First().Elements().First().Value.Trim(); 
     } 



     void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) 
     { 
      writer.WriteRaw(String.Format("\r\n\t<my:FieldBasic>\r\n\t\t{0}\r\n\t</my:FieldBasic>", this.FieldBasic)); 
      writer.WriteRaw(String.Format("\r\n\t<my:FieldComplex>\r\n\t\t{0}\r\n\t</my:FieldComplex>\r\n", this.FieldComplex)); 
     } 

(Retorno nula a partir del método GetSchema)

Esto debería hacerte, por lo menos, bastante cercano a lo que buscas.

También puede encontrar estos enlaces útiles.

IXmlSerializable

Namespaces

+0

Muchas gracias por esta solución :). Esto es exactamente lo que estaba buscando. – Beniamin

3

usted podría utilizar CDATA en el XML para indicar que el contenido es una cadena literal:

<my:Root xmlns:my="http://foo/bar"> 
    <my:FieldBasic>content</my:FieldBasic> 
    <my:FieldComplex> 
    <![CDATA[ 
     <html xml:space="preserve" xmlns="http://www.w3.org/1999/xhtml"> 
     <div><h1>content</h1></div> 
     </html> 
    ]]> 
    </my:FieldComplex> 
</my:Root> 
+1

Lamentablemente no tengo el control sólo en lo que se mete en el flujo, lo que no se sale. No puedo agregar . – JohnDoDo

Cuestiones relacionadas