在.NET中使用XmlReader取消XML实体?

时间:2011-03-14 20:47:55

标签: .net xml entities translate

我正在尝试在.NET(C#)中的字符串中删除XML实体,但我似乎无法使其正常工作。

例如,如果我有字符串AT&T,则应将其翻译为AT&T

一种方法是使用HttpUtility.HtmlDecode(),但这是针对HTML的。

所以我有两个问题:

  1. 使用HttpUtility.HtmlDecode()解码XML实体是否安全?

  2. 如何使用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();
        }
    }
    

5 个答案:

答案 0 :(得分:13)

HTML转义和XML密切相关。正如您所说,HttpUtility同时包含HtmlEncodeHtmlDecode方法。这些也将对XML进行操作,因为只有少数实体需要转义:两个HTML中都有<>\'&和XML。

使用HttpUtility类的缺点是你需要引用System.Web dll,这也带来了许多你可能不想要的东西。

特别是对于XML,SecurityElement类有一个Escape方法可以进行编码,但没有相应的Unescape方法。因此,您有几个选择:

  1. 使用HttpUtility.HtmlDecode()并提及对System.Web
  2. 的引用
  3. 滚动你自己的解码方法来处理特殊字符(因为只有少数 - 在Reflector中查看SecurityElement的静态构造函数以查看完整列表)

    < / LI>
  4. 使用(hacky)解决方案,如:

  5.     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;
        }
    

    就个人而言,如果我已经引用了HttpUtility.HtmlDecode(),我会使用System.Web,如果没有,我会使用自己的XmlReader。我不喜欢你的Disposable方法,因为它是{{1}},它通常表明它正在使用需要处理的资源,因此可能是一项代价高昂的操作。

答案 1 :(得分:8)

您的#2解决方案可行,但您需要在xmlReader.Read();之前致电xmlReader.MoveToContent();(或ReadString)。

我认为#1也是可以接受的,即使像&reg;这样的边缘情况是有效的HTML实体,但不是XML实体 - 你的unescaper应该怎么做呢?将异常作为正确的XML解析器抛出,或者只是像HTML解析器那样返回“®”?

答案 2 :(得分:1)

这有效:

using (XmlReader xmlReader = XmlReader.Create(reader, settings))
{
    if (xmlReader.Read())
    {
       return xmlReader.ReadString();
    }
}

答案 3 :(得分:1)

如果您的输入文字以某些空白字符结尾(如回车),我发现最常见的答案有一个小错误。

字符串“Testing&amp;#10;”失去它的尾随空白。

如果你将问题中的解决方案与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();
            }
        }
    }

答案 4 :(得分:0)

这也有效,并且代码最少:

    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是&#34;&#34;,那么xtr.Read()返回false,它似乎不起作用。

Update2:添加了解决方法

Update3:这似乎工作得更好

    public static string DecodeString(string encodedString)
    {
        XmlTextReader xtr = new XmlTextReader(encodedString, XmlNodeType.Element, null);
        xtr.MoveToContent();
        return xtr.Value;
    }