如何读取包含回车符 的XML文件并保留该字符不转换?
保留XML中
实体不被转换的解决方案
你遇到的问题是XML解析器默认会把 字符实体解析为实际的回车符(\r),后续如果重新序列化XML,这些回车符可能被转换为换行符或直接输出,导致xmldsig签名验证失败。以下是几种可行的解决方法:
方法一:序列化时将回车符还原为 实体
当你用XmlDocument或XmlReader读取XML后,节点内容里的 已经变成了\r,此时在写回XML时,手动将\r替换为 实体即可:
// 加载XML XmlDocument doc = new XmlDocument(); doc.Load("target.xml"); // 获取目标节点 XmlNode descNode = doc.SelectSingleNode("//description"); string rawContent = descNode.InnerText; // 将回车符替换回 实体,再设置回节点 descNode.InnerXml = rawContent.Replace("\r", " "); // 保存XML doc.Save("output.xml");
方法二:预替换占位符避免实体解析
先读取原始XML文本,把 替换为自定义占位符,处理完XML后再还原:
// 读取原始XML字符串 string xmlRaw = File.ReadAllText("target.xml"); // 替换 为占位符 xmlRaw = xmlRaw.Replace(" ", "@@CR_MARKER@@"); // 加载处理XML XmlDocument doc = new XmlDocument(); doc.LoadXml(xmlRaw); // 执行你的节点读取/修改操作... // 还原占位符并保存 string finalXml = doc.OuterXml.Replace("@@CR_MARKER@@", " "); File.WriteAllText("output.xml", finalXml);
方法三:直接用SignedXml验证签名(推荐)
如果你的核心需求是验证xmldsig签名,不要手动处理XML内容,直接用.NET内置的SignedXml类,它会自动处理XML规范化(包括空白和字符实体),确保和签名生成时的规则一致:
XmlDocument doc = new XmlDocument(); doc.PreserveWhitespace = true; // 必须保留空白,否则签名验证会失败 doc.Load("target.xml"); // 加载签名节点 SignedXml signedXml = new SignedXml(doc); XmlNodeList signatureNodes = doc.GetElementsByTagName("Signature"); signedXml.LoadXml((XmlElement)signatureNodes[0]); // 验证签名 bool isSignatureValid = signedXml.CheckSignature();
关键提示
- XML规范要求解析器必须解析预定义字符实体(如
),所以直接读取无法避免实体被转换,只能通过后续还原或预替换来保留原始实体格式。 - 处理带签名的XML时,永远不要随意修改XML的空白、字符实体或节点顺序,这些都会导致签名验证失败。
内容的提问来源于stack exchange,提问作者Y0rd4nis
相关产品推荐
相关产品推荐

