2009-09-09 13 views
6

estoy teniendo problemas serializar una sección CDATA mediante C#serialización XML - XmlCDataSection como Serialization.XmlText

necesito para serializar propiedad de objeto XmlCDataSection como el InnerText del elemento.

El resultado Busco es la siguiente:

<Test value2="Another Test"> 
    <![CDATA[<p>hello world</p>]]> 
</Test> 

Para producir este, estoy usando este objeto:

public class Test 
{ 
    [System.Xml.Serialization.XmlText()] 
    public XmlCDataSection value { get; set; } 

    [System.Xml.Serialization.XmlAttributeAttribute()] 
    public string value2 { get; set; } 
} 

Cuando se usa la anotación xmltext en la propiedad valor de error de seguimiento es arrojado.

System.InvalidOperationException: Hubo un error que refleja la propiedad 'valor'. ---> System.InvalidOperationException: No se puede serializar el 'valor' de miembro de escriba System.Xml.XmlCDataSection. XmlAttribute/xmltext no puede ser utilizado para tipos complejos codificar

Si comento a cabo la anotación, la serialización funcionará pero la sección CDATA se coloca en un elemento de valor que no es bueno para lo que yo estoy tratando de hacer :

<Test value2="Another Test"> 
    <value><![CDATA[<p>hello world</p>]]></value> 
</Test> 

¿Alguien puede indicarme la dirección correcta para hacer que esto funcione?

Gracias, Adam

+0

¿Qué pasa si se quita '[xmltext]'? –

Respuesta

5

Gracias Richard, solo ahora tuve la oportunidad de volver a esto. Creo que he resuelto el problema usando su sugerencia. He creado un objeto CDataField usando lo siguiente:

public class CDataField : IXmlSerializable 
    { 
     private string elementName; 
     private string elementValue; 

     public CDataField(string elementName, string elementValue) 
     { 
      this.elementName = elementName; 
      this.elementValue = elementValue; 
     } 

     public XmlSchema GetSchema() 
     { 
      return null; 
     } 

     public void WriteXml(XmlWriter w) 
     { 
      w.WriteStartElement(this.elementName); 
      w.WriteCData(this.elementValue); 
      w.WriteEndElement(); 
     } 

     public void ReadXml(XmlReader r) 
     {      
      throw new NotImplementedException("This method has not been implemented"); 
     } 
    } 
+0

arroja 'A.CDataField no se puede serializar porque no tiene un error de constructor sin parámetros' – tchelidze

2

La forma Test se define, sus datos es un objeto programable CData. Entonces, el sistema de serialización intenta preservar el objeto CData.

Pero desea serializar algunos datos de texto como una sección de CData.

Primero, el tipo de Test.value debería ser String.

Luego debe controlar cómo se serializa ese campo, pero no parece haber ningún método o atributo incorporado para controlar cómo se serializan las cadenas (como cadena, tal vez con entidades para caracteres reservados o como CDATA). (Dado que, desde una perspectiva XML infoset, todos estos son los mismos, esto no es sorprendente.)

Por supuesto, puede implementar IXmlSerializable y simplemente codificar la serialización del tipo Test, lo que le otorga control total.

0

Tuve el mismo problema que Adam. Sin embargo, esta respuesta no me ayudó al 100% :) pero me da una pista. Así que he creado un código como a continuación.Genera XML como esto:

<Actions> 
    <Action Type="reset"> 
     <![CDATA[ 
     <dbname>longcall</dbname> 
     <ontimeout> 
     <url>http://[IPPS_ADDRESS]/</url> 
     <timeout>10</timeout> 
     </ontimeout> 
     ]]> 
    </Action> 
    <Action Type="load"> 
     <![CDATA[ 
     <dbname>longcall</dbname> 
     ]]> 
    </Action> 
</Actions> 

Código:

public class ActionsCDataField : IXmlSerializable 
{ 
    public List<Action> Actions { get; set; } 

    public ActionsCDataField() 
    { 
     Actions = new List<Action>(); 
    } 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void WriteXml(XmlWriter w) 
    { 
     foreach (var item in Actions) 
     { 
      w.WriteStartElement("Action"); 
      w.WriteAttributeString("Type", item.Type); 
      w.WriteCData(item.InnerText);     
      w.WriteEndElement(); 
      w.WriteString("\r\n"); 
     } 
    } 

    public void ReadXml(XmlReader r) 
    { 
     XmlDocument xDoc = new XmlDocument(); 
     xDoc.Load(r); 

     XmlNodeList nodes = xDoc.GetElementsByTagName("Action"); 
     if (nodes != null && nodes.Count > 0) 
     { 
      foreach (XmlElement node in nodes) 
      { 
       Action a = new Action(); 
       a.Type = node.GetAttribute("Type"); 
       a.InnerText = node.InnerXml; 
       if (a.InnerText != null && a.InnerText.StartsWith("<![CDATA[") && a.InnerText.EndsWith("]]>")) 
        a.InnerText = a.InnerText.Substring("<![CDATA[".Length, a.InnerText.Length - "<![CDATA[]]>".Length); 

       Actions.Add(a); 
      } 
     } 
    } 
} 

public class Action 
{ 
    public String Type { get; set; } 
    public String InnerText { get; set; } 
} 
1

acaba de encontrar una alternativa de here:

 [XmlIgnore] 
      public string Content { get; set; } 

    [XmlText] 
      public XmlNode[] CDataContent 
      { 
       get 
       { 
        var dummy = new XmlDocument(); 
        return new XmlNode[] {dummy.CreateCDataSection(Content)}; 
       } 
       set 
       { 
        if (value == null) 
        { 
         Content = null; 
         return; 
        } 

        if (value.Length != 1) 
        { 
         throw new InvalidOperationException(
          String.Format(
           "Invalid array length {0}", value.Length)); 
        } 

        var node0 = value[0]; 
        var cdata = node0 as XmlCDataSection; 
        if (cdata == null) 
        { 
         throw new InvalidOperationException(
          String.Format(
           "Invalid node type {0}", node0.NodeType)); 
        } 

        Content = cdata.Data; 
       } 
      } 
     }