C# 如何使用 XmlSerializer 将字符串序列化为 CDATA?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1379888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you serialize a string as CDATA using XmlSerializer?
提问by jamesaharvey
Is it possible via an attribute of some sort to serialize a string as CDATA using the .Net XmlSerializer?
是否可以通过某种属性使用 .Net XmlSerializer 将字符串序列化为 CDATA?
采纳答案by John Saunders
[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
}
回答by Philip Rieck
In addition to the way posted by John Saunders, you can use an XmlCDataSectionas the type directly, although it boils down to nearly the same thing:
除了 John Saunders 发布的方式之外,您还可以直接使用XmlCDataSection作为类型,尽管它归结为几乎相同的事情:
private string _message;
[XmlElement("CDataElement")]
public XmlCDataSection Message
{
get
{
XmlDocument doc = new XmlDocument();
return doc.CreateCDataSection( _message);
}
set
{
_message = value.Value;
}
}
回答by pr0gg3r
[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;
}
}
}
Usage:
用法:
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());
Output:
输出:
<?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>
回答by sagis
In the class to be serialized:
在要序列化的类中:
public CData Content { get; set; }
And the CData class:
和 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);
}
}
回答by Iain Fraser
This implementation has the ability to process nested CDATA within the string you're encoding (based on John Saunders original answer).
此实现能够处理您正在编码的字符串中的嵌套 CDATA(基于 John Saunders 的原始答案)。
For example, suppose you wanted to encode the following literal string into CDATA:
例如,假设您想将以下文字字符串编码为 CDATA:
I am purposefully putting some <![CDATA[ cdata markers right ]]> in here!!
You would want the resultant output to look something like this:
您希望结果输出如下所示:
<![CDATA[I am purposefully putting some <![CDATA[ cdata markers right ]]]]><![CDATA[> in here!!]]>
The following implementation will loop over the string, split up instances of ...]]>...
into ...]]
and >...
and create separate CDATA sections for each.
下面的实现将遍历字符串,将 的实例拆分...]]>...
为...]]
和>...
并为每个实例创建单独的 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;
}
}
}
回答by Coderookie
In my case I'm using mixed fields, some CDATA some not, at least for me the following solution is working....
在我的情况下,我使用的是混合字段,一些 CDATA 一些不是,至少对我来说,以下解决方案是有效的....
By always reading the Value field, I'm getting the contents, regardless whether CDATA or just plain text.
通过始终阅读 Value 字段,我得到了内容,无论是 CDATA 还是纯文本。
[XmlElement("")]
public XmlCDataSection CDataValue {
get {
return new XmlDocument().CreateCDataSection(this.Value);
}
set {
this.Value = value.Value;
}
}
[XmlText]
public string Value;
Better late than never.
迟到总比不到好。
Cheers
干杯
回答by Adam Hey
I had a similar need but required a different output format - I wanted an attribute on the node that contains the CDATA. I took some inspiration from the above solutions to create my own. Maybe it will help someone in the future...
我有类似的需求,但需要不同的输出格式 - 我想要包含 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()
{
}
}
In the parent object to be serialised, I have the following property:
在要序列化的父对象中,我具有以下属性:
[XmlArray("embedScripts")]
[XmlArrayItem("embedScript")]
public List<EmbedScript> EmbedScripts { get; set; }
I get the following output:
我得到以下输出:
<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>