如何使用XmlSerializer将string序列化为CDATA?

是否有可能通过某种属性使用.Net XmlSerializer将string序列化为CDATA?

 [XmlRoot("root")] public class Sample1Xml { internal Sample1Xml() { } [XmlElement("node")] public NodeType Node { get; set; } #region Nested type: NodeType public class NodeType { [XmlAttribute("attr1")] public string Attr1 { get; set; } [XmlAttribute("attr2")] public string Attr2 { get; set; } [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)); } Content = value[0].Value; } } } #endregion } 

除了John Saunders发布的方式之外,您可以直接使用XmlCDataSection作为types,尽pipe它归结为几乎相同的东西:

  private string _message; [XmlElement("CDataElement")] public XmlCDataSection Message { get { XmlDocument doc = new XmlDocument(); return doc.CreateCDataSection( _message); } set { _message = value.Value; } } 
 [Serializable] public class MyClass { public MyClass() { } [XmlIgnore] public string MyString { get; set; } [XmlElement("MyString")] public System.Xml.XmlCDataSection MyStringCDATA { get { return new System.Xml.XmlDocument().CreateCDataSection(MyString); } set { MyString = value.Value; } } } 

用法:

 MyClass mc = new MyClass(); mc.MyString = "<test>Hello World</test>"; XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); StringWriter writer = new StringWriter(); serializer.Serialize(writer, mc); Console.WriteLine(writer.ToString()); 

输出:

 <?xml version="1.0" encoding="utf-16"?> <MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <MyString><![CDATA[<test>Hello World</test>]]></MyString> </MyClass> 

在要序列化的类中:

 public CData Content { get; set; } 

和CData类:

 public class CData : IXmlSerializable { private string _value; /// <summary> /// Allow direct assignment from string: /// CData cdata = "abc"; /// </summary> /// <param name="value"></param> /// <returns></returns> public static implicit operator CData(string value) { return new CData(value); } /// <summary> /// Allow direct assigment to string /// string str = cdata; /// </summary> /// <param name="cdata"></param> /// <returns></returns> public static implicit operator string(CData cdata) { return cdata._value; } public CData() : this(string.Empty) { } public CData(string value) { _value = value; } public override string ToString() { return _value; } public System.Xml.Schema.XmlSchema GetSchema() { return null; } public void ReadXml(System.Xml.XmlReader reader) { _value = reader.ReadElementString(); } public void WriteXml(System.Xml.XmlWriter writer) { writer.WriteCData(_value); } } 

这个实现能够在你编码的string中处理嵌套的CDATA(基于John Saunders的原始答案)。

例如,假设您想将以下文字string编码为CDATA:

 I am purposefully putting some <![CDATA[ cdata markers right ]]> in here!! 

你会希望得到的输出看起来像这样:

 <![CDATA[I am purposefully putting some <![CDATA[ cdata markers right ]]]]><![CDATA[> in here!!]]> 

下面的实现将遍历string,将...]]>...实例拆分为...]]>...并为每个创build单独的CDATA节。

 [XmlRoot("root")] public class Sample1Xml { internal Sample1Xml() { } [XmlElement("node")] public NodeType Node { get; set; } #region Nested type: NodeType public class NodeType { [XmlAttribute("attr1")] public string Attr1 { get; set; } [XmlAttribute("attr2")] public string Attr2 { get; set; } [XmlIgnore] public string Content { get; set; } [XmlText] public XmlNode[] CDataContent { get { XmlDocument dummy = new XmlDocument(); List<XmlNode> xmlNodes = new List<XmlNode>(); int tokenCount = 0; int prevSplit = 0; for (int i = 0; i < Content.Length; i++) { char c = Content[i]; //If the current character is > and it was preceded by ]] (ie the last 3 characters were ]]>) if (c == '>' && tokenCount >= 2) { //Put everything up to this point in a new CData Section string thisSection = Content.Substring(prevSplit, i - prevSplit); xmlNodes.Add(dummy.CreateCDataSection(thisSection)); prevSplit = i; } if (c == ']') { tokenCount++; } else { tokenCount = 0; } } //Put the final part of the string into a CData section string finalSection = Content.Substring(prevSplit, Content.Length - prevSplit); xmlNodes.Add(dummy.CreateCDataSection(finalSection)); return xmlNodes.ToArray(); } set { if (value == null) { Content = null; return; } if (value.Length != 1) { throw new InvalidOperationException( String.Format( "Invalid array length {0}", value.Length)); } Content = value[0].Value; } } } 

在我的情况下,我使用混合字段,一些CDATA有些不,至less对我来说,下面的解决scheme正在工作….

通过总是阅读价值领域,我得到的内容,无论是CDATA还是纯文本。

  [XmlElement("")] public XmlCDataSection CDataValue { get { return new XmlDocument().CreateCDataSection(this.Value); } set { this.Value = value.Value; } } [XmlText] public string Value; 

迟到总比不到好。

干杯

我有一个类似的需求,但需要不同的输出格式 – 我想在包含CDATA的节点属性。 我从上面的解决scheme中获得了一些灵感来创造我自己的。 也许这将有助于未来的人

 public class EmbedScript { [XmlAttribute("type")] public string Type { get; set; } [XmlText] public XmlNode[] Script { get; set; } public EmbedScript(string type, string script) { Type = type; Script = new XmlNode[] { new XmlDocument().CreateCDataSection(script) }; } public EmbedScript() { } } 

在要序列化的父对象中,我有以下属性:

  [XmlArray("embedScripts")] [XmlArrayItem("embedScript")] public List<EmbedScript> EmbedScripts { get; set; } 

我得到以下输出:

 <embedScripts> <embedScript type="Desktop Iframe"> <![CDATA[<div id="play_game"><iframe height="100%" src="http://www.myurl.com" width="100%"></iframe></div>]]> </embedScript> <embedScript type="JavaScript"> <![CDATA[]]> </embedScript> </embedScripts>