如何在xsd.exe生成的C#类中正确使用CDATA?
解决XML序列化中CDATA被自动转义的问题
问题描述
我正在尝试给一个映射为xs:string的字段赋值并写入XML。一开始直接赋值字符串是正常的:
rawdata.data = generatedString;
但当我尝试把内容包裹在CDATA标签里,写成<![CDATA[" + generatedString + "]]>时,最终输出里的CDATA部分被转义成了&lt;![CDATA[这类形式,完全不是预期的CDATA块。
问题根源
你现在用的DataFilesRawdata类里的data字段是普通string类型,默认的XML序列化会把所有特殊字符(比如<、>)都转义,所以你手动加的CDATA标签会被当成普通文本处理,自然就被转义了。
解决方案
要让序列化器识别并生成CDATA块,你需要修改data字段的序列化逻辑,这里有两种实用方法:
方法1:改用XmlCDataSection类型
这是最直接的方式,把data字段的类型换成XmlCDataSection,同时调整对应的序列化属性:
/// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class DataFilesRawdata { private string idField; private System.Xml.XmlCDataSection dataField; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] public string ID { get { return this.idField; } set { this.idField = value; } } /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] public System.Xml.XmlCDataSection data { get { return this.dataField; } set { this.dataField = value; } } }
赋值的时候需要通过XmlDocument创建CDATA节点:
XmlDocument doc = new XmlDocument(); rawdata.data = doc.CreateCDataSection(generatedString);
这样序列化时就会自动生成正确的CDATA块,不会被转义。
方法2:自定义序列化逻辑(保留string类型)
如果你不想修改字段类型,可以通过添加辅助属性来控制序列化:
给类新增一个用于序列化的辅助属性,同时把原来的data字段标记为忽略序列化:
/// <remarks/> [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)] public partial class DataFilesRawdata { private string idField; private string dataField; /// <remarks/> [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)] public string ID { get { return this.idField; } set { this.idField = value; } } // 用于序列化的辅助属性,生成CDATA [System.Xml.Serialization.XmlAnyElementAttribute("data")] public XmlNode[] DataCData { get { XmlDocument doc = new XmlDocument(); return new XmlNode[] { doc.CreateCDataSection(dataField) }; } set { if (value == null || value.Length == 0) { dataField = null; return; } dataField = value[0].Value; } } // 原来的data字段排除序列化 [System.Xml.Serialization.XmlIgnoreAttribute] public string data { get { return this.dataField; } set { this.dataField = value; } } }
这样你还是可以像之前一样给rawdata.data赋值普通字符串,序列化时会自动转换成CDATA块。
小提示
如果这个类是用xsd工具自动生成的,下次重新生成会覆盖你的修改,建议把自定义逻辑放在单独的部分类文件里,比如新建DataFilesRawdata.Extensions.cs:
public partial class DataFilesRawdata { [System.Xml.Serialization.XmlAnyElementAttribute("data")] public XmlNode[] DataCData { get { XmlDocument doc = new XmlDocument(); return new XmlNode[] { doc.CreateCDataSection(dataField) }; } set { if (value == null || value.Length == 0) { dataField = null; return; } dataField = value[0].Value; } } [System.Xml.Serialization.XmlIgnoreAttribute] public new string data { get { return this.dataField; } set { this.dataField = value; } } }
这样既保留自动生成的代码,又不会丢失自定义逻辑。
内容的提问来源于stack exchange,提问作者Geesh_SO
相关产品推荐
相关产品推荐

