2009-09-09 9 views
6

Je rencontre des problèmes sérialisation une section CDATA utilisant C#sérialisation XML - XmlCDataSection comme Serialization.XmlText

Je dois sérialisation propriété d'objet XmlCDataSection comme InnerText de l'élément.

Le résultat que je cherche est la suivante:

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

Pour produire, je suis en utilisant cet objet:

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

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

Lorsque vous utilisez l'annotation xmltext sur la propriété de valeur l'erreur suivante est jeté.

System.InvalidOperationException: Il y avait une erreur qui reflète la propriété 'valeur'. ---> System.InvalidOperationException: Impossible de sérialiser la 'valeur' ​​du membre de type System.Xml.XmlCDataSection. XmlAttribute/XmlText ne peut pas être utilisé pour encodent types complexes

Si je commente sur l'annotation, la sérialisation fonctionne, mais la section CDATA est placé dans un élément de valeur qui est pas bon pour ce que je suis en train de faire :

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

Quelqu'un peut-il me diriger dans la bonne direction pour que cela fonctionne.

Merci, Adam

+0

Qu'advient-il si vous supprimez '[XmlText]'? –

Répondre

5

Merci Richard, seulement maintenant eu l'occasion d'y revenir. Je pense que j'ai résolu le problème en utilisant votre suggestion. J'ai créé un objet CDataField en utilisant ce qui suit:

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

il lance 'A.CDataField ne peut pas être sérialisé car il n'a pas d'erreur de constructeur sans paramètre – tchelidze

2

La façon Test est définie, vos données est un objet CData. Le système de sérialisation tente donc de préserver l'objet CData.

Mais vous voulez sérialiser certaines données de texte sous la forme d'une section CData.

Donc d'abord, le type de Test.value doit être String. Vous devez ensuite contrôler la façon dont ce champ est sérialisé, mais il ne semble pas y avoir de méthode ou d'attribut intégré pour contrôler la façon dont les chaînes sont sérialisées (comme chaîne, avec des entités pour les caractères réservés ou comme CDATA). (Comme, d'un point de vue XML, tous ces éléments sont identiques, cela n'est pas surprenant.)

Vous pouvez bien sûr implémenter IXmlSerializable et simplement coder la sérialisation du type Test, ce qui vous donne un contrôle total.

0

J'ai eu le même problème que Adam. Cependant cette réponse ne m'a pas aidé à 100% :) mais me donne un indice. Donc je l'ai créé un code comme ci-dessous.Il génère du code XML comme ceci:

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

code:

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

Je viens de trouver une alternative 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; 
       } 
      } 
     } 
Questions connexes