Comment sérialiser une chaîne en tant que CDATA en utilisant XmlSerializer?

Est-il possible, via un atsortingbut quelconque, de sérialiser une chaîne en tant que CDATA en utilisant .Net XmlSerializer?

 [XmlRoot("root")] public class Sample1Xml { internal Sample1Xml() { } [XmlElement("node")] public NodeType Node { get; set; } #region Nested type: NodeType public class NodeType { [XmlAtsortingbute("attr1")] public ssortingng Attr1 { get; set; } [XmlAtsortingbute("attr2")] public ssortingng Attr2 { get; set; } [XmlIgnore] public ssortingng 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( Ssortingng.Format( "Invalid array length {0}", value.Length)); } Content = value[0].Value; } } } #endregion } 

En plus de la manière affichée par John Saunders, vous pouvez utiliser directement un type XmlCDataSection , même si cela revient presque à la même chose:

 private ssortingng _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 ssortingng MySsortingng { get; set; } [XmlElement("MySsortingng")] public System.Xml.XmlCDataSection MySsortingngCDATA { get { return new System.Xml.XmlDocument().CreateCDataSection(MySsortingng); } set { MySsortingng = value.Value; } } } 

Usage:

 MyClass mc = new MyClass(); mc.MySsortingng = "Hello World"; XmlSerializer serializer = new XmlSerializer(typeof(MyClass)); SsortingngWriter writer = new SsortingngWriter(); serializer.Serialize(writer, mc); Console.WriteLine(writer.ToSsortingng()); 

Sortie:

 < ?xml version="1.0" encoding="utf-16"?>  < ![CDATA[Hello World]]>  

Dans la classe à sérialiser:

 public CData Content { get; set; } 

Et la classe CData:

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

Cette implémentation a la capacité de traiter les CDATA nesteds dans la chaîne que vous encodez (basée sur la réponse originale de John Saunders).

Par exemple, supposons que vous vouliez encoder la chaîne littérale suivante dans CDATA:

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

Vous voulez que la sortie résultante ressemble à ceci:

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

L’implémentation suivante passera en boucle sur la chaîne, divisera les instances de ...]]>... dans ...]] et >... et créera des sections CDATA distinctes pour chacune.

 [XmlRoot("root")] public class Sample1Xml { internal Sample1Xml() { } [XmlElement("node")] public NodeType Node { get; set; } #region Nested type: NodeType public class NodeType { [XmlAtsortingbute("attr1")] public ssortingng Attr1 { get; set; } [XmlAtsortingbute("attr2")] public ssortingng Attr2 { get; set; } [XmlIgnore] public ssortingng Content { get; set; } [XmlText] public XmlNode[] CDataContent { get { XmlDocument dummy = new XmlDocument(); List xmlNodes = new List(); 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 ssortingng thisSection = Content.Subssortingng(prevSplit, i - prevSplit); xmlNodes.Add(dummy.CreateCDataSection(thisSection)); prevSplit = i; } if (c == ']') { tokenCount++; } else { tokenCount = 0; } } //Put the final part of the ssortingng into a CData section ssortingng finalSection = Content.Subssortingng(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( Ssortingng.Format( "Invalid array length {0}", value.Length)); } Content = value[0].Value; } } } 

Dans mon cas, j’utilise des champs mixtes, certains CDATA certains, du moins pour moi la solution suivante fonctionne …

En lisant toujours le champ Valeur, j’obtiens le contenu, que ce soit CDATA ou simplement du texte.

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

Mieux vaut tard que jamais.

À votre santé

J’avais un besoin similaire mais nécessitait un format de sortie différent – je voulais un atsortingbut sur le nœud qui contient le CDATA. Je me suis inspiré des solutions ci-dessus pour créer les miennes. Peut-être que ça aidera quelqu’un dans le futur …

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

Dans l’object parent à sérialiser, j’ai la propriété suivante:

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

J’obtiens la sortie suivante:

   < ![CDATA[
]]> < ![CDATA[]]>