如何阻止XDocument解析XML中的字符实体?
问题
读取并处理XML数据时,XML文档包含ISO字符实体(如↶),需要保留这些实体编码,但使用XDocument.Load()加载时,实体会被自动解析为对应符号。如何阻止这种解析行为?
示例XML
<?xml version="1.0" encoding="UTF-8"?> <doc> <table> <title>iso-amsa.ent</title> <tgroup cols="3"> <colspec colname="col1" colwidth="0.50*"/> <colspec colname="col2" align="center" colwidth="0.40*"/> <colspec colname="col3" colwidth="2.20*"/> <thead> <row><entry><para>ISO Entity Name</para></entry><entry><para>Unicode Entity</para></entry><entry><para>Description</para></entry></row> </thead> <tbody> <row><entry><para>cularr</para></entry><entry><para>↶</para></entry><entry><para>ANTICLOCKWISE TOP SEMICIRCLE ARROW</para></entry></row> <row><entry><para>curarr</para></entry><entry><para>↷</para></entry><entry><para>CLOCKWISE TOP SEMICIRCLE ARROW</para></entry></row> <row><entry><para>dArr</para></entry><entry><para>⇓</para></entry><entry><para>DOWNWARDS DOUBLE ARROW</para></entry></row> <row><entry><para>darr2</para></entry><entry><para>⇊</para></entry><entry><para>DOWNWARDS PAIRED ARROWS</para></entry></row> <row><entry><para>dharl</para></entry><entry><para>⇃</para></entry><entry><para>DOWNWARDS HARPOON WITH BARB LEFTWARDS</para></entry></row> </tbody> </tgroup> </table> </doc>
当前加载代码
string fileName = @"C:\MyTestFile.xml"; XDocument _doc = XDocument.Load(fileName);
解决方案
XDocument默认会自动解析XML中的字符实体,要保留实体编码,需通过预转义或自定义读取逻辑实现,以下是几种可行方法:
方法1:预转义数字字符实体(推荐)
读取XML原始文本,用正则表达式精准匹配数字形式的字符实体并转义,避免破坏XML标准实体(如<、>):
using System.Text.RegularExpressions; using System.IO; string fileName = @"C:\MyTestFile.xml"; // 读取XML原始内容 string rawXml = File.ReadAllText(fileName); // 仅转义数字字符实体,保留标准实体引用 string escapedXml = Regex.Replace(rawXml, @"&#(x?[0-9A-Fa-f]+);", @"&#$1;"); // 解析转义后的XML XDocument _doc = XDocument.Parse(escapedXml);
方法2:全局替换(适用于无标准实体的场景)
如果XML中仅包含数字字符实体、无标准实体引用,可直接全局替换:
using System.IO; string fileName = @"C:\MyTestFile.xml"; string rawXml = File.ReadAllText(fileName); string escapedXml = rawXml.Replace("&#", "&#"); XDocument _doc = XDocument.Parse(escapedXml);
方法3:自定义XmlReader遍历构建XDocument(复杂场景)
若需要深度定制实体处理逻辑,可使用XmlReader遍历节点,手动捕获实体原始字符串并构建XDocument:
using System.Xml; using System.Xml.Linq; string fileName = @"C:\MyTestFile.xml"; XDocument doc = new XDocument(); XElement currentElement = null; using (XmlReader reader = XmlReader.Create(fileName)) { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: var element = new XElement(reader.Name); // 处理属性 if (reader.HasAttributes) { while (reader.MoveToNextAttribute()) { element.Add(new XAttribute(reader.Name, reader.Value)); } reader.MoveToElement(); } currentElement = currentElement == null ? doc.Add(element).FirstNode as XElement : currentElement.Add(element).LastNode as XElement; // 自闭合标签回退父节点 if (reader.IsEmptyElement) currentElement = currentElement.Parent; break; case XmlNodeType.Text: currentElement.Add(reader.Value); break; case XmlNodeType.EntityReference: // 保留实体原始字符串 currentElement.Add($"&{reader.Name};"); break; case XmlNodeType.EndElement: currentElement = currentElement.Parent; break; } } }
此方法实现复杂度较高,适合需要精细控制的场景。
内容的提问来源于stack exchange,提问作者Daedalus
相关产品推荐
相关产品推荐

