11

.NET(C#)で文字列内のXMLエンティティをエスケープ解除しようとしていますが、正しく機能しないようです。

たとえば、文字列がある場合は、AT&Tに変換する必要がありますAT&T

1つの方法は、HttpUtility.HtmlDecode()を使用することですが、これはHTML用です。

だから私はこれについて2つの質問があります:

  1. XMLエンティティのデコードにHttpUtility.HtmlDecode()を使用しても安全ですか?

  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両方HtmlEncodeHtmlDecode方法があります。エスケープが必要なエンティティは、、、、およびHTMLとXMLの両方<であるため>、これらもXMLで動作します。\'&

このクラスを使用することの欠点は、dllHttpUtilityへの参照が必要になることですSystem.Web。これにより、おそらく不要な他の多くのものも取り込まれます。

特にXMLの場合、SecurityElementクラスにはEscapeエンコードを行うメソッドがありますが、対応するメソッドはありませんUnescape。したがって、いくつかのオプションがあります。

  1. を使用しHttpUtility.HtmlDecode()て、への参照を我慢するSystem.Web
  2. 特殊文字を処理する独自のデコードメソッドをロールします(ほんの一握りしかないためSecurityElement、Reflectorの静的コンストラクターで完全なリストを確認してください)

  3. 次のような(ハッキーな)ソリューションを使用します。

    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

#2のソリューションは機能しますが、の前にxmlReader.Read();(または)を呼び出す必要があります。xmlReader.MoveToContent();ReadString

有効なHTMLエンティティであるがXMLエンティティではないようなエッジケースがあるとしても、#1も受け入れられると思い&reg;ます。これをアンスケーパーはどうすればよいでしょうか。適切なXMLパーサーとして例外をスローしますか、それともHTMLパーサーのように「®」を返しますか?

于 2011-03-14T21:31:11.697 に答える
1

入力テキストがキャリッジリターンのように特定の空白文字で終わっている場合、一番上の答えには小さなバグがあることがわかりました。

文字列「Testing&#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();
            }
        }
    }
于 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);
    }

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;
    }
于 2016-03-10T14:23:57.513 に答える