C# HtmlEncode - ISO-8859-1 имена объектов против номеров

В соответствии со следующей таблицей для стандарта ISO-8859-1, похоже, что имя объекта и номер объекта связаны с каждым зарезервированным символом HTML.

Так, например, для персонажа é:

Имя сущности: é

Номер объекта: é

Аналогично для персонажа >:

Имя сущности: >

Номер объекта: >

Для данной строки HttpUtility.HtmlEncode возвращает строку в кодировке HTML, но я не могу понять, как это работает. Вот что я имею в виду:

Console.WriteLine(HtmlEncode("é>"));
//Outputs é>

Кажется, он использует номер объекта для é символ, но имя объекта для > персонаж.

Так действительно ли метод HtmlEncode работает со стандартом ISO-8859-1? Если это так, есть ли причина, по которой он иногда использует имя объекта, а иногда - номер объекта? Что еще более важно, могу ли я заставить его надежно назвать имя сущности?

РЕДАКТИРОВАТЬ: Спасибо за ответы, ребята. Я не могу декодировать строку, прежде чем выполнить поиск, хотя. Не вдаваясь в подробности, текст сохраняется в списке SharePoint, а "поиск" выполняется самой SharePoint (с использованием запроса CAML). В общем, я не могу.

Я пытаюсь придумать способ преобразования номеров сущностей в имена. Есть ли в.NET функция, которая это делает? Или любая другая идея?

5 ответов

Решение

Вот как метод был реализован. Для некоторых известных символов он использует соответствующую сущность, а для всего остального он использует соответствующее шестнадцатеричное значение, и вы мало что можете сделать, чтобы изменить это поведение. Выдержка из реализации System.Net.WebUtility.HtmlEncode (как видно с отражателем):

...
if (ch <= '>')
{
    switch (ch)
    {
        case '&':
        {
            output.Write("&amp;");
            continue;
        }
        case '\'':
        {
            output.Write("&#39;");
            continue;
        }
        case '"':
        {
            output.Write("&quot;");
            continue;
        }
        case '<':
        {
            output.Write("&lt;");
            continue;
        }
        case '>':
        {
            output.Write("&gt;");
            continue;
        }
    }
    output.Write(ch);
    continue;
}
if ((ch >= '\x00a0') && (ch < 'Ā'))
{
    output.Write("&#");
    output.Write(((int) ch).ToString(NumberFormatInfo.InvariantInfo));
    output.Write(';');
}
...

При этом вам не следует беспокоиться, так как этот метод всегда будет генерировать корректный, безопасный и правильно закодированный HTML.

Я сделал эту функцию, я думаю, что это поможет

        string BasHtmlEncode(string x)
        {
           StringBuilder sb = new StringBuilder();
           foreach (char c in x.ToCharArray())
               sb.Append(String.Format("&#{0};", Convert.ToInt16(c)));
           return(sb.ToString());
        }

HtmlEncode следует за спецификацией. Стандарт ISO определяет как имя, так и номер для каждого объекта, а имя и номер эквивалентны. Следовательно, соответствующая реализация HtmlEncode свободно кодировать все точки как числа, или все как имена, или некоторую смесь двух.

Я предлагаю вам подойти к вашей проблеме с другой стороны: позвоните HtmlDecode на целевом тексте, затем ищите декодированный текст, используя необработанную строку.

ISO-8859-1 не имеет никакого отношения к кодированию символов HTML. Из Википедии:

Числовые ссылки всегда ссылаются на кодовые точки Unicode, независимо от кодировки страницы.

Только для неопределенных кодовых точек Unicode часто используется ISO-8859-1:

Использование числовых ссылок, которые ссылаются на постоянно неопределенные символы и управляющие символы, запрещено, за исключением символов перевода строки, табуляции и возврата каретки. То есть символы в шестнадцатеричных диапазонах 00–08, 0B–0C, 0E–1F, 7F и 80–9F нельзя использовать в документе HTML, даже по ссылке, поэтому, например, "™" не допускается, Однако для обратной совместимости с ранними авторами HTML и браузерами, которые игнорировали это ограничение, необработанные символы и ссылки на числовые символы в диапазоне 80–9F интерпретируются некоторыми браузерами как представляющие символы, сопоставленные с байтами 80–9F в кодировке Windows-1252.

Теперь, чтобы ответить на ваш вопрос: чтобы поиск работал лучше, вы должны действительно искать незашифрованный HTML (сначала удаляя теги HTML), используя незашифрованную строку поиска. Сопоставление закодированных строк приведет к неожиданным результатам, таким как совпадения на основе тегов или комментариев HTML, а также совпадения, отсутствующие из-за различий в HTML, которые невидимы в тексте.

Я разработал следующий код, чтобы аз,AZ и 0-1 не кодировались, а оставались:

public static string Encode(string source)
{
    if (string.IsNullOrEmpty(source)) return string.Empty;

    var sb = new StringBuilder(source.Length);
    foreach (char c in source)
    {
        if (c >= 'a' && c <= 'z')
        {
            sb.Append(c);
        }
        else if (c >= 'A' && c <= 'Z')
        {
            sb.Append(c);
        }
        else if (c >= '0' && c <= '9')
        {
            sb.Append(c);
        }
        else
        {
            sb.AppendFormat("&#{0};",Convert.ToInt32(c));
        }
    }

    return sb.ToString();
}
Другие вопросы по тегам