Подтвердить что ты не робот

WebUtility.HtmlDecode vs HttpUtilty.HtmlDecode

Я использовал WebUtilty.HtmlDecode для декодирования HTML. Оказывается, что он не декодируется должным образом, например, – должен декодировать символ "-", но WebUtilty.HtmlDecode не декодирует его. HttpUtilty.HtmlDecode, однако, делает.

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


> –
> –

decode screenshot

Документация для обоих из них одинакова: Преобразует строку, которая была кодирована HTML для передачи HTTP в декодированную строку.

Почему они разные, какие я должен использовать, и что изменится, если я переключусь на WebUtility.HtmlDecode, чтобы правильно декодировать "-"?

4b9b3361

Ответ 1

Реализация этих двух методов действительно отличается на 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. Кроме того, реализация WP8 для WebUtility идентична настольной. Реализация рабочего стола 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, просто выберите метод, поведение которого лучше всего соответствует вашим потребностям. WebUtility, вероятно, является будущим выбором, на случай, если Microsoft решит отказаться от среды выполнения Silverlight в предстоящей версии Windows Phone. Но я бы просто решил практиковать выбор HttpUtility, чтобы не беспокоиться о том, чтобы вручную поддержать пример, который вы задали в своем вопросе.

Ответ 2

Методы выполняют точно такие же. Более того, если вы попытаетесь декомпилировать их, реализаций выглядят так, как будто они были просто скопированы из другого.

Разница заключается только в предполагаемом использовании. HttpUtility содержится в сборке System.Web и, как ожидается, будет использоваться в приложениях ASP.net, которые построены на этой сборке. WebUtility содержится в сборке System, на которую ссылаются почти все приложения и предоставляется для общего использования или использования клиентом.

Ответ 3

Просто чтобы уведомить других, которые найдут это в поиске. Используйте любую функцию, указанную в вопросе, но никогда не используйте Windows.Data.Html.HtmlUtilities.ConvertToText(string input). Это в 70 раз медленнее, чем WebUtilty.HtmlDecode и приводит к сбоям! Crash будет называться mshtml!IEPeekMessage в DevCenter. Похоже, эта функция вызывает InternetExplorer для преобразования строки. Просто избегайте этого.