C# 如何使用XmlSerializer将字符串列表反序列化为CDATA
我需要将字符串列表序列化为CDATA,并认为我将遵循一个of 它就像连载的魅力。我的XML文件看起来符合要求:C# 如何使用XmlSerializer将字符串列表反序列化为CDATA,c#,serialization,xml-serialization,C#,Serialization,Xml Serialization,我需要将字符串列表序列化为CDATA,并认为我将遵循一个of 它就像连载的魅力。我的XML文件看起来符合要求: <?xml version="1.0" encoding="utf-8"?> <root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <tlist> <item><![CD
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<tlist>
<item><![CDATA[First string]]></item>
<item><![CDATA[Second string]]></item>
</tlist>
</root>
虽然简单代理使用单个值,但由于.NET XML序列化机制的工作方式,您必须对集合进行更深入的代理:
[XmlRootAttribute("root")]
public class TestConfig
{
public TestConfig()
{
TestList = new List<string>();
}
private List<string> testList;
[XmlIgnore]
public List<string> TestList
{
get
{
if (this.testList == null)
{
var newCollection = new List<string>();
if (this.cdataList != null)
{
foreach (var x in this.cdataList)
{
newCollection.Add(x.Value);
}
}
this.testList = newCollection;
this.cdataList = null;
}
return this.testList;
}
set
{
this.testList = value;
this.cdataList = null;
}
}
private List<XmlCDataSection> cdataList;
[XmlArray("tlist")]
[XmlArrayItem("item")]
public List<XmlCDataSection> CdataList
{
get
{
if (this.cdataList == null)
{
var newCollection = new List<XmlCDataSection>();
if (this.testList != null)
{
foreach (var x in this.testList)
{
newCollection.Add(new XmlDocument().CreateCDataSection(x));
}
}
this.cdataList = newCollection;
this.testList = null;
}
return this.cdataList;
}
set
{
this.cdataList = value;
this.testList = null;
}
}
public void Save(string path)
{
var serializer = new XmlSerializer(GetType());
using (var stream = new StreamWriter(path))
{
serializer.Serialize(stream, this);
}
}
public static TestConfig Load(string path)
{
var serializer = new XmlSerializer(typeof(TestConfig));
using (var stream = new StreamReader(path))
{
return (TestConfig)serializer.Deserialize(stream);
}
}
}
然后按如下方式使用它:
var serializer = new XmlSerializer(...));
using (var cdataWriter = new XmlCDataWriter(XmlWriter.Create("somepath.xml")))
{
serializer.Serialize(cdataWriter, myDocumentObject);
}
同样,只有当您想将所有内容都写为CDATA时,这个选项才有意义。我想我应该通过减少XMLWriter子类的长度来“改进”答案
/// <summary>
/// Custom XmlWriter.
/// Wraps up another XmlWriter to intercept string writes within
/// elements and writes them as CDATA instead.
/// </summary>
public class XmlCDataWriter : XmlTextWriter
{
public override void WriteString(string text)
{
if (WriteState == WriteState.Element)
{
WriteCData(text);
}
else
{
base.WriteString(text);
}
}
/// <summary>
/// Creates an instance of the XmlTextWriter class using the specified <see cref="T:System.IO.TextWriter"/>.
/// </summary>
/// <param name="w">The TextWriter to write to. It is assumed that the TextWriter is already set to the correct encoding. </param>
public XmlCDataWriter( [NotNull] TextWriter w ) : base( w )
{
}
}
到目前为止似乎对我有效,它是一个小得多的子类:)有没有一种紧凑的方法可以做到这一点,并且仍然允许使用XmlTextWriter XmlWriterSettings选项?XmlWriterSettings似乎只能通过XmlTextWriter.Create()静态方法使用。返回一个XmlWriter实例。无需。。。XmlWriter似乎已经包含了一个XmlWriterSettings成员变量,所以我刚刚添加了另一个构造函数,它接受XmlWriterSettings实例,并对我关心的所有内容进行深度复制。
/// <summary>
/// Custom XmlWriter.
/// Wraps up another XmlWriter to intercept string writes within
/// elements and writes them as CDATA instead.
/// </summary>
public class XmlCDataWriter : XmlWriter
{
XmlWriter w;
public XmlCDataWriter(XmlWriter baseWriter)
{
this.w = baseWriter;
}
public override void Close()
{
w.Close();
}
public override void Flush()
{
w.Flush();
}
public override string LookupPrefix(string ns)
{
return w.LookupPrefix(ns);
}
public override void WriteBase64(byte[] buffer, int index, int count)
{
w.WriteBase64(buffer, index, count);
}
public override void WriteCData(string text)
{
w.WriteCData(text);
}
public override void WriteCharEntity(char ch)
{
w.WriteCharEntity(ch);
}
public override void WriteChars(char[] buffer, int index, int count)
{
w.WriteChars(buffer, index, count);
}
public override void WriteComment(string text)
{
w.WriteComment(text);
}
public override void WriteDocType(string name, string pubid, string sysid, string subset)
{
w.WriteDocType(name, pubid, sysid, subset);
}
public override void WriteEndAttribute()
{
w.WriteEndAttribute();
}
public override void WriteEndDocument()
{
w.WriteEndDocument();
}
public override void WriteEndElement()
{
w.WriteEndElement();
}
public override void WriteEntityRef(string name)
{
w.WriteEntityRef(name);
}
public override void WriteFullEndElement()
{
w.WriteFullEndElement();
}
public override void WriteProcessingInstruction(string name, string text)
{
w.WriteProcessingInstruction(name, text);
}
public override void WriteRaw(string data)
{
w.WriteRaw(data);
}
public override void WriteRaw(char[] buffer, int index, int count)
{
w.WriteRaw(buffer, index, count);
}
public override void WriteStartAttribute(string prefix, string localName, string ns)
{
w.WriteStartAttribute(prefix, localName, ns);
}
public override void WriteStartDocument(bool standalone)
{
w.WriteStartDocument(standalone);
}
public override void WriteStartDocument()
{
w.WriteStartDocument();
}
public override void WriteStartElement(string prefix, string localName, string ns)
{
w.WriteStartElement(prefix, localName, ns);
}
public override WriteState WriteState
{
get { return w.WriteState; }
}
public override void WriteString(string text)
{
if (WriteState == WriteState.Element)
{
w.WriteCData(text);
}
else
{
w.WriteString(text);
}
}
public override void WriteSurrogateCharEntity(char lowChar, char highChar)
{
w.WriteSurrogateCharEntity(lowChar, highChar);
}
public override void WriteWhitespace(string ws)
{
w.WriteWhitespace(ws);
}
}
var serializer = new XmlSerializer(...));
using (var cdataWriter = new XmlCDataWriter(XmlWriter.Create("somepath.xml")))
{
serializer.Serialize(cdataWriter, myDocumentObject);
}
/// <summary>
/// Custom XmlWriter.
/// Wraps up another XmlWriter to intercept string writes within
/// elements and writes them as CDATA instead.
/// </summary>
public class XmlCDataWriter : XmlTextWriter
{
public override void WriteString(string text)
{
if (WriteState == WriteState.Element)
{
WriteCData(text);
}
else
{
base.WriteString(text);
}
}
/// <summary>
/// Creates an instance of the XmlTextWriter class using the specified <see cref="T:System.IO.TextWriter"/>.
/// </summary>
/// <param name="w">The TextWriter to write to. It is assumed that the TextWriter is already set to the correct encoding. </param>
public XmlCDataWriter( [NotNull] TextWriter w ) : base( w )
{
}
}
using (StringWriter textWriter = new StringWriter())
{
XmlSerializer serializer = new XmlSerializer( typeof( ... ) );
serializer.Serialize(new XmlCDataWriter(textWriter), ... );
return textWriter.ToString();
}