【问题标题】:Unescaping XML entities using XmlReader in .NET?在 .NET 中使用 XmlReader 取消转义 XML 实体?
【发布时间】:2011-07-15 07:53:14
【问题描述】:

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

【问题讨论】:

    标签: .net xml entities translate


    【解决方案1】:

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

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

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      我猜#1 也是可以接受的,即使有像 &amp;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;
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-14
            • 2011-01-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多