web-dev-qa-db-ja.com

WebUtility.HtmlDecodeとHttpUtilty.HtmlDecode

HTMLのデコードにWebUtilty.HtmlDecodeを使用していました。たとえば、–は「–」文字にデコードされることになっていますが、WebUtilty.HtmlDecodeはそれをデコードしません。ただし、HttpUtilty.HtmlDecodeはサポートします。

Debug.WriteLine(WebUtility.HtmlDecode("–"));
Debug.WriteLine(HttpUtility.HtmlDecode("–"));


> –
> –

decode screenshot

これらの両方のドキュメントは同じです:HTTP送信用にHTMLエンコードされた文字列をデコードされた文字列に変換します。

なぜそれらが異なるのか、どちらを使用する必要があるのか​​、および「–」を正しくデコードするためにWebUtility.HtmlDecodeに切り替えると何が変わるのですか?

24
zi3guw

2つのメソッドの実装は、Windows Phoneでは実際に異なります。

WebUtility.HtmlDecode:

public static void HtmlDecode(string value, TextWriter output)
{
    if (value != null)
    {
        if (output == null)
        {
            throw new ArgumentNullException("output");
        }
        if (!StringRequiresHtmlDecoding(value))
        {
            output.Write(value);
        }
        else
        {
            int length = value.Length;
            for (int i = 0; i < length; i++)
            {
                bool flag;
                uint num4;
                char ch = value[i];
                if (ch != '&')
                {
                    goto Label_01B6;
                }
                int num3 = value.IndexOfAny(_htmlEntityEndingChars, i + 1);
                if ((num3 <= 0) || (value[num3] != ';'))
                {
                    goto Label_01B6;
                }
                string entity = value.Substring(i + 1, (num3 - i) - 1);
                if ((entity.Length <= 1) || (entity[0] != '#'))
                {
                    goto Label_0188;
                }
                if ((entity[1] == 'x') || (entity[1] == 'X'))
                {
                    flag = uint.TryParse(entity.Substring(2), NumberStyles.AllowHexSpecifier, NumberFormatInfo.InvariantInfo, out num4);
                }
                else
                {
                    flag = uint.TryParse(entity.Substring(1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out num4);
                }
                if (flag)
                {
                    switch (_htmlDecodeConformance)
                    {
                        case UnicodeDecodingConformance.Strict:
                            flag = (num4 < 0xd800) || ((0xdfff < num4) && (num4 <= 0x10ffff));
                            goto Label_0151;

                        case UnicodeDecodingConformance.Compat:
                            flag = (0 < num4) && (num4 <= 0xffff);
                            goto Label_0151;

                        case UnicodeDecodingConformance.Loose:
                            flag = num4 <= 0x10ffff;
                            goto Label_0151;
                    }
                    flag = false;
                }
            Label_0151:
                if (!flag)
                {
                    goto Label_01B6;
                }
                if (num4 <= 0xffff)
                {
                    output.Write((char) num4);
                }
                else
                {
                    char ch2;
                    char ch3;
                    ConvertSmpToUtf16(num4, out ch2, out ch3);
                    output.Write(ch2);
                    output.Write(ch3);
                }
                i = num3;
                goto Label_01BD;
            Label_0188:
                i = num3;
                char ch4 = HtmlEntities.Lookup(entity);
                if (ch4 != '\0')
                {
                    ch = ch4;
                }
                else
                {
                    output.Write('&');
                    output.Write(entity);
                    output.Write(';');
                    goto Label_01BD;
                }
            Label_01B6:
                output.Write(ch);
            Label_01BD:;
            }
        }
    }
}

HttpUtility.HtmlDecode:

public static string HtmlDecode(string html)
{
    if (html == null)
    {
        return null;
    }
    if (html.IndexOf('&') < 0)
    {
        return html;
    }
    StringBuilder sb = new StringBuilder();
    StringWriter writer = new StringWriter(sb, CultureInfo.InvariantCulture);
    int length = html.Length;
    for (int i = 0; i < length; i++)
    {
        char ch = html[i];
        if (ch == '&')
        {
            int num3 = html.IndexOfAny(s_entityEndingChars, i + 1);
            if ((num3 > 0) && (html[num3] == ';'))
            {
                string entity = html.Substring(i + 1, (num3 - i) - 1);
                if ((entity.Length > 1) && (entity[0] == '#'))
                {
                    try
                    {
                        if ((entity[1] == 'x') || (entity[1] == 'X'))
                        {
                            ch = (char) int.Parse(entity.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
                        }
                        else
                        {
                            ch = (char) int.Parse(entity.Substring(1), CultureInfo.InvariantCulture);
                        }
                        i = num3;
                    }
                    catch (FormatException)
                    {
                        i++;
                    }
                    catch (ArgumentException)
                    {
                        i++;
                    }
                }
                else
                {
                    i = num3;
                    char ch2 = HtmlEntities.Lookup(entity);
                    if (ch2 != '\0')
                    {
                        ch = ch2;
                    }
                    else
                    {
                        writer.Write('&');
                        writer.Write(entity);
                        writer.Write(';');
                        continue;
                    }
                }
            }
        }
        writer.Write(ch);
    }
    return sb.ToString();
}

興味深いことに、WebUtilityはWP7には存在しません。また、WebUtilityのWP8実装はデスクトップのものと同じです。 HttpUtility.HtmlDecodeのデスクトップ実装は、WebUtility.HtmlDecodeの単なるラッパーです。最後に重要なことですが、Silverlight 5はHttpUtility.HtmlDecodeの実装がWindows Phoneと同じであり、WebUtilityを実装していません。

Windows Phone 7ランタイムはSilverlightに基づいているため、WP7はSilverlightバージョンのHttpUtility.HtmlDecodeを継承しており、WebUtilityは存在しませんでした。その後、WP8が登場しました。そのランタイムはWinRTに基づいています。 WinRTはWebUtilityをもたらし、古いバージョンのHttpUtility.HtmlDecodeはレガシーWP7アプリとの互換性を確保するために維持されました。

どちらを使用するかを知るために... WP7をターゲットにしたい場合は、HttpUtility.HtmlDecodeを使用するしかありません。 WP8をターゲットにしている場合は、ニーズに最も適した動作のメソッドを選択するだけです。 Microsoftが次期バージョンのWindows PhoneでSilverlightランタイムを廃止することを決定した場合に備えて、WebUtilityはおそらく将来性のある選択です。ただし、質問に入力した例を手動でサポートすることを心配する必要がないように、HttpUtilityを選択するという実際的な選択をそのまま使用します。

12
Kevin Gosse

メソッドまったく同じ。さらに、それらを逆コンパイルしようとすると、実装が別の実装からコピーされたように見えます。

違いは使用目的のみです。 HttpUtilitySystem.Webアセンブリに含まれており、このアセンブリで構築されるASP.netアプリケーションで使用されることが期待されています。 WebUtilityは、ほぼすべてのアプリケーションによって参照されるSystemアセンブリに含まれており、より一般的な目的またはクライアントの使用のために提供されています。

6
Jan Dobkowski

検索でこれを見つけた人に通知するだけです。質問で言及されている関数を使用しますが、Windows.Data.Html.HtmlUtilities.ConvertToText(string input)は使用しないでください。 WebUtilty.HtmlDecodeより70倍遅く、クラッシュが発生します。クラッシュは、DevCenterではmshtml!IEPeekMessageという名前になります。この関数はInternetExplorerを呼び出して文字列を変換するように見えます。ただそれを避けなさい。

3
crea7or