2009-09-09 21 views
6

Ho problemi serializzazione una sezione CDATA utilizzando C#serializzazione XML - XmlCDataSection come Serialization.XmlText

ho bisogno di serializzare proprietà dell'oggetto XmlCDataSection come InnerText dell'elemento.

il risultato che sto cercando è questo:

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

Per produrre questo, sto usando questo oggetto:

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

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

Quando si utilizza l'annotazione xmltext sulla proprietà di valore il seguente errore è gettato.

System.InvalidOperationException: C'è stato un errore che riflette proprietà 'valore'. ---> System.InvalidOperationException: Impossibile serializzare il "valore" membro di tipo System.Xml.XmlCDataSection. XmlAttribute/XmlText non può essere utilizzato per codificare tipi complessi

Se commento fuori l'annotazione, la serializzazione funzionerà ma la sezione CDATA viene inserito in un elemento di valore che non va bene per quello che sto cercando di fare :

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

Qualcuno può indicarmi la direzione giusta per farlo funzionare.

Grazie, Adam

+0

Che cosa succede se si rimuove '[XmlText]'? –

risposta

5

Grazie Richard, solo ora ha avuto la possibilità di tornare a questo. Penso di aver risolto il problema usando il tuo suggerimento. Ho creato un oggetto CDataField utilizzando il seguente:

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

getta 'A.CDataField non può essere serializzato perché non ha un errore di costruttore senza parametri' – tchelidze

2

Il modo Test è definito, i dati è un oggetto DatiC. Quindi il sistema di serializzazione sta cercando di preservare l'oggetto CData.

Ma si desidera serializzare alcuni dati di testo come una sezione CData.

Quindi, per prima cosa, il tipo di Test.value deve essere String.

È quindi necessario controllare il modo in quel campo è serializzato, ma non sembra essere un metodo integrato o di un attributo per controllare come le stringhe vengono serializzati (come stringa, magari con enti per caratteri riservati, o come CDATA). (Dal momento che, dal punto di vista infoset XML, tutti questi sono gli stessi, questo non è sorprendente.)

Ovviamente è possibile implementare IXmlSerializable e codificare semplicemente la serializzazione del tipo Test da soli che offre un controllo completo.

0

Ho avuto lo stesso problema di Adam. Tuttavia questa risposta non mi ha aiutato al 100% :) ma mi dà un indizio. Quindi ho creato un codice come di seguito.Esso genera XML come questo:

<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> 

Codice:

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

appena trovato un'alternativa da 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; 
       } 
      } 
     } 
Problemi correlati