在 .NET 中使用 XmlReader 取消转义 XML 实体?
Posted
技术标签:
【中文标题】在 .NET 中使用 XmlReader 取消转义 XML 实体?【英文标题】:Unescaping XML entities using XmlReader in .NET? 【发布时间】:2011-07-15 07:53:14 【问题描述】:我正在尝试在 .NET (C#) 中对字符串中的 XML 实体进行转义,但我似乎无法使其正常工作。
例如,如果我有字符串AT&T
,它应该被翻译成AT&T
。
一种方法是使用 HttpUtility.htmlDecode(),但这是针对 HTML。
所以我对此有两个问题:
使用 HttpUtility.HtmlDecode() 解码 XML 实体是否安全?
如何使用 XmlReader(或类似的东西)来做到这一点?我尝试了以下方法,但总是返回一个空字符串:
static string ReplaceEscapes(string text)
StringReader reader = new StringReader(text);
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
using (XmlReader xmlReader = XmlReader.Create(reader, settings))
return xmlReader.ReadString();
【问题讨论】:
【参考方案1】:HTML 转义和 XML 密切相关。正如您所说,HttpUtility
同时具有 HtmlEncode
和 HtmlDecode
方法。这些也将在 XML 上运行,因为只有少数实体需要转义:<
、>
、\
、'
和 &
在 HTML 和 XML 中。
使用HttpUtility
类的缺点是您需要引用System.Web
dll,这也带来了许多您可能不想要的其他内容。
特别是对于 XML,SecurityElement
类有一个将进行编码的 Escape
方法,但没有相应的 Unescape
方法。因此,您有几个选择:
-
使用
HttpUtility.HtmlDecode()
并忍受对System.Web
的引用
滚动您自己的解码方法来处理特殊字符(因为只有少数 - 查看 Reflector 中 SecurityElement
的静态构造函数以查看完整列表)
使用(hacky)解决方案,例如:
.
public static string Unescape(string text)
XmlDocument doc = new XmlDocument();
string xml = string.Format("<dummy>0</dummy>", text);
doc.LoadXml(xml);
return doc.DocumentElement.InnerText;
就个人而言,如果我已经引用了System.Web
,我会使用HttpUtility.HtmlDecode()
,如果没有,我会使用我自己的。我不喜欢你的XmlReader
方法,因为它是Disposable
,这通常表明它正在使用需要处置的资源,因此可能是一项昂贵的操作。
【讨论】:
【参考方案2】:您的#2 解决方案可以工作,但您需要在ReadString
之前致电xmlReader.Read();
(或xmlReader.MoveToContent();
)。
我猜#1 也是可以接受的,即使有像 &reg;
这样的边缘情况,它是一个有效的 HTML 实体,但不是一个 XML 实体——你的 unescaper 应该如何处理它?将异常作为适当的 XML 解析器抛出,还是像 HTML 解析器那样只返回“®”?
【讨论】:
添加xmlReader.MoveToContent()
成功了,这正是我正在寻找的解决方案。由于 HTML 和 XML 之间的差异,我真的不想使用 HttpUtility,所以您的回复非常有帮助。【参考方案3】:
这行得通:
using (XmlReader xmlReader = XmlReader.Create(reader, settings))
if (xmlReader.Read())
return xmlReader.ReadString();
【讨论】:
【参考方案4】:如果您的输入文本以某些空白字符(如回车符)结尾,我发现最佳答案有一个小错误。
字符串“Testing ”失去它的尾随空白。
如果您将问题中的解决方案与 adrianbanks 的包装标签结合起来,您会得到以下结果。
public static string UnescapeUnicode(string line)
using (StringReader reader = new StringReader("<a>" + line + "</a>"))
using (XmlReader xmlReader = XmlReader.Create(reader))
xmlReader.MoveToContent();
return xmlReader.ReadElementContentAsString();
【讨论】:
【参考方案5】:这也有效,并且代码最少:
public static string DecodeString(string encodedString)
if (string.IsNullOrEmpty(formattedText))
return string.Empty;
XmlTextReader xtr = new XmlTextReader(encodedString, XmlNodeType.Element, null);
if (xtr.Read())
return xtr.ReadString();
throw new Exception("Error decoding xml string : " + encodedString);
Update1:嗯,如果 encodeString 为 "" 似乎不起作用,那么 xtr.Read() 返回 false。
Update2:添加了解决方法
Update3:这似乎效果更好
public static string DecodeString(string encodedString)
XmlTextReader xtr = new XmlTextReader(encodedString, XmlNodeType.Element, null);
xtr.MoveToContent();
return xtr.Value;
【讨论】:
以上是关于在 .NET 中使用 XmlReader 取消转义 XML 实体?的主要内容,如果未能解决你的问题,请参考以下文章
在 XmlReader .NET 4.0 中加载失败目录文件
如何在 .Net 2.0/C# 中将 StreamReader 转换为 XMLReader 对象
从 XmlDocument 到 XmlReader .Net