Возможно ли с помощью какого-либо атрибута сериализовать строку как CDATA с помощью .Net XmlSerializer?
c#
.net
xml-serialization
Джеймсахарви
источник
источник
CDataContent
если вы только читаете XML.XmlSerializer.Deserialize
автоматически превратит его в текст.Ответы:
[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 }
источник
[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>
источник
XmlDocument().CreateCDataSection(MyString ?? String.Empty);
В дополнение к способу, опубликованному Джоном Сондерсом, вы можете напрямую использовать XmlCDataSection в качестве типа, хотя это сводится почти к тому же:
private string _message; [XmlElement("CDataElement")] public XmlCDataSection Message { get { XmlDocument doc = new XmlDocument(); return doc.CreateCDataSection( _message); } set { _message = value.Value; } }
источник
В сериализуемом классе:
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">The string being cast to CData.</param> /// <returns>A CData object</returns> public static implicit operator CData(string value) { return new CData(value); } /// <summary> /// Allow direct assignment to string: /// string str = cdata; /// </summary> /// <param name="cdata">The CData being cast to a string</param> /// <returns>A string representation of the CData object</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); } }
источник
У меня была аналогичная потребность, но требовался другой формат вывода - мне нужен атрибут на узле, который содержит CDATA. Я черпал вдохновение из приведенных выше решений, чтобы создать свое собственное. Может, это кому-то поможет в будущем ...
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>
источник
В моем случае я использую смешанные поля, некоторые CDATA некоторые нет, по крайней мере, для меня работает следующее решение ...
Всегда читая поле «Значение», я получаю содержимое, независимо от того, является ли он CDATA или просто текстом.
[XmlElement("")] public XmlCDataSection CDataValue { get { return new XmlDocument().CreateCDataSection(this.Value); } set { this.Value = value.Value; } } [XmlText] public string Value;
Лучше поздно, чем никогда.
Ура
источник
Эта реализация имеет возможность обрабатывать вложенные CDATA в кодируемой вами строке (на основе исходного ответа Джона Сондерса).
Например, предположим, что вы хотите закодировать следующую буквальную строку в 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!!]]>
Следующая реализация будет перебирать строку, разделять экземпляры
...]]>...
на...]]
и>...
и создавать отдельные разделы 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 ]] (i.e. 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; } } }
источник