11

我正在尝试在 .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();
        }
    }
    
4

5 回答 5

16

HTML 转义和 XML 密切相关。正如你所说,有HttpUtility两种方法。这些也将在 XML 上运行,因为只有少数实体需要转义:、、和HTML 和 XML 。HtmlEncodeHtmlDecode<>\'&

使用HttpUtility该类的缺点是您需要对System.Webdll 的引用,这也带来了许多您可能不想要的其他内容。

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

  1. 使用HttpUtility.HtmlDecode()and put up 参考System.Web
  2. 滚动处理特殊字符的自己的解码方法(因为只有少数 - 查看SecurityElementReflector 中的静态构造函数以查看完整列表)

  3. 使用(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;
    }

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

于 2011-03-14T21:31:44.623 回答
8

xmlReader.Read();您的 #2 解决方案可以工作,但您需要xmlReader.MoveToContent();ReadString.

我想#1 也是可以接受的,即使有一些边缘情况,比如&reg;它是一个有效的 HTML 实体,但不是一个 XML 实体——你的 unescaper 应该如何处理它?作为适当的 XML 解析器抛出异常,还是像 HTML 解析器那样只返回“®”?

于 2011-03-14T21:31:11.697 回答
1

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

字符串“测试 ” 失去它的尾随空白。

如果您将问题中的解决方案与 adrianbanks 的 wrapper 标签结合起来,您会得到以下内容,这很有效。

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();
            }
        }
    }
于 2012-05-25T15:23:21.320 回答
1

这有效:

using (XmlReader xmlReader = XmlReader.Create(reader, settings))
{
    if (xmlReader.Read())
    {
       return xmlReader.ReadString();
    }
}
于 2011-03-14T21:41:07.290 回答
1

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

    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);
    }

更新1:嗯,如果encodeString是“”,似乎它不起作用,然后xtr.Read()返回false。

更新 2:添加了解决方法

Update3:这似乎效果更好

    public static string DecodeString(string encodedString)
    {
        XmlTextReader xtr = new XmlTextReader(encodedString, XmlNodeType.Element, null);
        xtr.MoveToContent();
        return xtr.Value;
    }
于 2016-03-10T14:23:57.513 回答