Có thể thông qua một thuộc tính nào đó để tuần tự hóa một chuỗi dưới dạng CDATA bằng cách sử dụng .Net XmlSerializer không?
Có thể thông qua một thuộc tính nào đó để tuần tự hóa một chuỗi dưới dạng CDATA bằng cách sử dụng .Net XmlSerializer không?
Câu trả lời:
[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;
}
}
}
Sử dụng:
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());
Đầu ra:
<?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);
Ngoài cách được đăng bởi John Saunders, bạn có thể sử dụng một XmlCDataSection làm loại trực tiếp, mặc dù nó tổng hợp gần như giống nhau:
private string _message;
[XmlElement("CDataElement")]
public XmlCDataSection Message
{
get
{
XmlDocument doc = new XmlDocument();
return doc.CreateCDataSection( _message);
}
set
{
_message = value.Value;
}
}
Trong lớp được nối tiếp:
public CData Content { get; set; }
Và lớp 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);
}
}
Tôi cũng có nhu cầu tương tự nhưng yêu cầu định dạng đầu ra khác - tôi muốn có một thuộc tính trên nút chứa CDATA. Tôi đã lấy một số cảm hứng từ các giải pháp trên để tạo ra giải pháp của riêng mình. Có thể nó sẽ giúp ích cho ai đó trong tương lai ...
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()
{
}
}
Trong đối tượng cha được tuần tự hóa, tôi có thuộc tính sau:
[XmlArray("embedScripts")]
[XmlArrayItem("embedScript")]
public List<EmbedScript> EmbedScripts { get; set; }
Tôi nhận được kết quả sau:
<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>
Trong trường hợp của tôi, tôi đang sử dụng các trường hỗn hợp, một số CDATA một số thì không, ít nhất là đối với tôi, giải pháp sau đang hoạt động ....
Bằng cách luôn đọc trường Giá trị, tôi nhận được nội dung, bất kể là CDATA hay chỉ là văn bản thuần túy.
[XmlElement("")]
public XmlCDataSection CDataValue {
get {
return new XmlDocument().CreateCDataSection(this.Value);
}
set {
this.Value = value.Value;
}
}
[XmlText]
public string Value;
Muộn còn hơn không.
Chúc mừng
Việc triển khai này có khả năng xử lý CDATA lồng nhau trong chuỗi bạn đang mã hóa (dựa trên câu trả lời gốc của John Saunders).
Ví dụ: giả sử bạn muốn mã hóa chuỗi ký tự sau thành CDATA:
I am purposefully putting some <![CDATA[ cdata markers right ]]> in here!!
Bạn sẽ muốn kết quả đầu ra trông giống như sau:
<![CDATA[I am purposefully putting some <![CDATA[ cdata markers right ]]]]><![CDATA[> in here!!]]>
Việc triển khai sau đây sẽ lặp lại chuỗi, chia nhỏ các phiên bản ...]]>...
thành ...]]
và >...
và tạo các phần CDATA riêng biệt cho từng chuỗi .
[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;
}
}
}
CDataContent
nếu bạn chỉ đọc XML.XmlSerializer.Deserialize
sẽ tự động chuyển nó thành văn bản cho bạn.