如何在C#应用中将CRLF统一保存为XML十进制实体 而非十六进制
统一XML换行符为十进制实体的解决方案
问题根源
直接用Replace("\r\n", " ")无效,是因为XElement会自动转义字符串中的&符号,把 变成
,最终输出的不是预期的十进制实体。另外不同环境下XDocument.Save的换行编码差异,源于系统默认的换行处理逻辑不同。
解决方案
方法一:自定义XmlWriter处理换行实体
这是通用方案,不管XML结构复杂度如何,都能统一将\r\n替换为十进制实体:
1. 实现自定义XmlWriter
public class DecimalEntityXmlWriter : XmlWriter { private readonly XmlWriter _innerWriter; public DecimalEntityXmlWriter(XmlWriter innerWriter) { _innerWriter = innerWriter; } public override void WriteString(string text) { // 将\r\n替换为十进制实体,其他字符正常输出 string processedText = text.Replace("\r\n", " "); _innerWriter.WriteString(processedText); } // 以下方法直接委托给内部XmlWriter,无需修改 public override void Close() => _innerWriter.Close(); public override void Flush() => _innerWriter.Flush(); public override string LookupPrefix(string ns) => _innerWriter.LookupPrefix(ns); public override void WriteBase64(byte[] buffer, int index, int count) => _innerWriter.WriteBase64(buffer, index, count); public override void WriteCData(string text) => _innerWriter.WriteCData(text); public override void WriteCharEntity(char ch) => _innerWriter.WriteCharEntity(ch); public override void WriteChars(char[] buffer, int index, int count) => _innerWriter.WriteChars(buffer, index, count); public override void WriteComment(string text) => _innerWriter.WriteComment(text); public override void WriteDocType(string name, string pubid, string sysid, string subset) => _innerWriter.WriteDocType(name, pubid, sysid, subset); public override void WriteEndAttribute() => _innerWriter.WriteEndAttribute(); public override void WriteEndDocument() => _innerWriter.WriteEndDocument(); public override void WriteEndElement() => _innerWriter.WriteEndElement(); public override void WriteEntityRef(string name) => _innerWriter.WriteEntityRef(name); public override void WriteFullEndElement() => _innerWriter.WriteFullEndElement(); public override void WriteProcessingInstruction(string name, string text) => _innerWriter.WriteProcessingInstruction(name, text); public override void WriteRaw(string data) => _innerWriter.WriteRaw(data); public override void WriteRaw(char[] buffer, int index, int count) => _innerWriter.WriteRaw(buffer, index, count); public override void WriteStartAttribute(string prefix, string localName, string ns) => _innerWriter.WriteStartAttribute(prefix, localName, ns); public override void WriteStartDocument(bool standalone) => _innerWriter.WriteStartDocument(standalone); public override void WriteStartDocument() => _innerWriter.WriteStartDocument(); public override void WriteStartElement(string prefix, string localName, string ns) => _innerWriter.WriteStartElement(prefix, localName, ns); public override WriteState WriteState => _innerWriter.WriteState; public override void WriteSurrogateCharEntity(char lowChar, char highChar) => _innerWriter.WriteSurrogateCharEntity(lowChar, highChar); public override void WriteWhitespace(string ws) => _innerWriter.WriteWhitespace(ws); }
2. 使用自定义XmlWriter保存XML
XElement xelm = *******; // 包含带\r\n的XML文本 XDocument xdoc = new XDocument(xelm); var settings = new XmlWriterSettings { Encoding = new UTF8Encoding(false), Indent = true // 根据需求决定是否格式化XML }; using (var strWriter = new StreamWriter(path, false, settings.Encoding)) using (var xmlWriter = XmlWriter.Create(strWriter, settings)) using (var customWriter = new DecimalEntityXmlWriter(xmlWriter)) { xdoc.Save(customWriter); }
方法二:手动写入原始实体内容(适用于简单XML结构)
如果你的XML节点结构简单,没有复杂的子节点和属性,可以直接用XmlWriter.WriteRaw写入带实体的内容,避免自动转义:
XElement xelm = *******; string processedText = xelm.Value.Replace("\r\n", " "); using (var strWriter = new StreamWriter(path, false, new UTF8Encoding(false))) using (var xmlWriter = XmlWriter.Create(strWriter)) { xmlWriter.WriteStartDocument(); xmlWriter.WriteStartElement(xelm.Name.LocalName); // 写入原始实体内容,不触发转义 xmlWriter.WriteRaw(processedText); xmlWriter.WriteEndElement(); xmlWriter.WriteEndDocument(); }
关键说明
NewLineHandling.None无法直接生成十进制实体,它只是禁止XmlWriter自动转换换行符,适合需要保留原始换行的场景,但不符合本次需求。- 自定义XmlWriter的核心是重写
WriteString方法,在输出文本前替换换行符为十进制实体,同时保留其他字符的正常处理逻辑。
内容的提问来源于stack exchange,提问作者Naveen
相关产品推荐
相关产品推荐

