2009-09-09 37 views
6

我有序列化使用C#XML序列化 - XmlCDataSection作爲Serialization.XmlText

我需要序列XmlCDataSection對象屬性作爲元素的innerText CDATA節問題。

我找的結果是這樣的:

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

爲了生產這一點,我使用這個對象:

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

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

在使用上的價值屬性XMLTEXT註釋以下錯誤是拋出。

System.InvalidOperationException: 有反射性 '值' 的誤差。 ---> System.InvalidOperationException: 無法序列化 類型System.Xml.XmlCDataSection的成員'值'。 XmlAttribute/XMLTEXT不能用於 編碼複雜類型

如果我註釋掉的註釋,序列化工作,但CDATA部分被放入這是沒有良好的什麼,我試圖做一個值元素:

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

任何人都可以指出我正確的方向來獲得這個工作。

謝謝,亞當

+0

如果刪除'[XMLTEXT]'會發生什麼? – 2009-09-09 10:03:42

回答

5

謝謝理查德,現在纔有機會回到這個。我想我已經通過使用你的建議解決了這個問題。我使用以下方法創建了一個CDataField對象:

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

它拋出'A.CDataField無法序列化,因爲它沒有無參數構造函數的錯誤 – tchelidze 2017-02-18 15:32:56

2

方式Test定義,你的數據是一個CDATA對象。所以序列化系統試圖保留CData對象。

但是您想要將一些文本數據作爲CData節序列化。

所以首先,Test.value的類型應該是String。

然後您需要控制該字段是如何序列化的,但似乎沒有任何內置的方法或屬性來控制字符串是如何序列化的(如字符串,可能包含實體的保留字符或CDATA)。 (因爲從XML Infoset的角度來看,所有這些都是一樣的,所以這並不奇怪。)

您當然可以實現IXmlSerializable,並且自己編寫Test類型的序列化,它可以讓您完全控制。

0

我的問題與Adam非常相似。然而,這個答案並沒有幫助我100%:)但給了我一個線索。所以我創建了一個如下所示的代碼。它產生這樣的XML:

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

代碼:

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

剛剛發現從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; 
       } 
      } 
     }