Почему "& reg" отображается как "®" без ограничивающей точки с запятой
У меня возникла проблема, которая была выявлена в нашей маркетинговой кампании, основанной на Google adwords. Одним из стандартных используемых параметров является "регион". Когда пользователь выполняет поиск и нажимает на спонсируемую ссылку, Google генерирует длинный URL-адрес для отслеживания щелчка и отправляет кучу материала в реферере. Мы фиксируем это для наших записей, и мы заметили, что параметр "Регион" происходит неправильно. Что должно быть
http://ravercats.com/meow?foo=bar®ion=catnip
вместо этого появляется как:
http://ravercats.com/meow?foo=bar®ion=catnip
Я проверил, что это происходит во всех браузерах. Я понимаю, что синтаксис HTML-объекта определяется следующим образом:
&VALUE;
где главная граница - амперсанд, а закрывающая граница - точка с запятой. Кажется достаточно простым. Проблема заключается в том, что это не соблюдается для субъекта ®, и оно разрушает все виды хаоса в нашей системе.
Кто-нибудь знает, почему это происходит? Это ошибка в DTD? (Я ищу текущий HTML DTD, чтобы узнать, могу ли я это понять). Я пытаюсь выяснить, что будет распространено в браузерах, чтобы это произошло, поэтому я ищу DTD.
Вот доказательство, которое вы можете использовать. Возьмите этот код, внесите из него HTML файл и отрисуйте его в браузере:
<html>
<a href="#" onclick="location.href='http://foo.com/bar?foo=bar®ion=US®ister=lowpass®_test=fail&trademark=correct'; return false;">http://foo.com/bar?foo=bar®ion=US®ister=lowpass®_test=fail&trademark=correct</a>
</html>
РЕДАКТИРОВАТЬ: всем, кто предполагает, что мне нужно избежать всего URL-адреса, приведенные выше примерные URL-адреса являются именно такими примерами. Настоящий URL-адрес поступает напрямую от Google, и я не могу контролировать, как он построен. Эти предложения, хотя и действительны, не отвечают на вопрос: "Почему это происходит".
Ответы
Ответ 1
Хотя правильные ссылки на символы всегда имеют точку с запятой в конце, некоторые недопустимые именованные символьные ссылки без точки с запятой для соображений обратной совместимости распознаются HTML-парсерами современных браузеров.
Либо вы знаете, что такое весь список, либо вы следуете правилам HTML5, если &
действителен без экранирования (e, g, за которым следует пробел) или иначе всегда выходите &
как &
когда есть сомнения.
Для справки, полный список названных имен символов, которые распознаются без точки с запятой:
AElig, AMP, Aacute, Acirc, Agrave, Aring, Atilde, Auml, COPY, Ccedil, ETH, Eacute, Ecirc, Egrave, Euml, GT, Iacute, Icirc, Igrave, Iuml, LT, Ntilde, Oacute, Ocirc, Ograve, Oslash, Otilde, Ouml, QUOT, REG, THORN, Uacute, Ucirc, Ugrave, Uuml, Yacute, aacute, acirc, sharp, aelig, agrave, amp, aring, atilde, auml, brvbar, ccedil, cedil, cent, копия, curren, deg, divide, eacute, ecirc, egrave, eth, euml, frac12, frac14, frac34, gt, iacute, icirc, iexcl, igrave, iquest, iuml, laquo, lt, macr, micro, middot, nbsp, не, ntilde, oacute, ocirc, ograve, ordf, ordm, oslash, otilde, ouml, para, plusmn, pound, quotquo, raquo, reg, sect, shy, sup1, sup2, sup3, szlig, thorn, times, uacute, ucirc, ugrave, uml, uuml, yacute, yen, yuml
Однако следует отметить, что только в том случае, когда в значении атрибута, ссылки на именованные символы в приведенном выше списке не обрабатываются как таковые, согласовывая синтаксические анализаторы HTML5, если следующий символ является =
или буквенно-цифровым символом ASCII.
Для полного списка имен символов с или без конечных точек с запятой, см. здесь
Ответ 2
Это очень грязный бизнес и зависит от контекста (текстовый контент и значение атрибута).
Формально, по спецификациям HTML вплоть до HTML 4.01, ссылка на сущность может появляться без конечной точки с запятой, если следующий символ не является символом имени. Так, например, ®ion=
будет синтаксически корректным, но undefined, поскольку объект region
не определен. XHTML делает конечную точку с запятой.
Браузеры традиционно играют другие правила. Из-за общего синтаксиса URL-адресов запросов они анализируют, например. href="http://ravercats.com/meow?foo=bar®ion=catnip"
, так что ®ion
не рассматривается как ссылка на сущность, а как только текстовые данные. И авторы в основном использовали такие конструкции, хотя они формально неверны.
Вопреки тому, что, кажется, говорит вопрос, href="http://ravercats.com/meow?foo=bar®ion=catnip"
действительно работает хорошо. Проблемы возникают, когда строка не находится в значении атрибута, а внутри текстового содержимого, что довольно необычно: мы обычно не пишем URL-адреса в тексте. В тексте ®ion=
обрабатывается так, что ®
распознается как ссылка на сущность (для "®" ), а остальные - только символьные данные. Такое нечетное поведение становится официальным в HTML5 CR, где предложение 8.2.4.69 Обозначение символьных символов описывает "двойной стандарт":
Если ссылка символа потребляется как часть атрибута, и последний совпадающий символ не является ";" (U + 003B) и следующий символ является либо символом "=" (U + 003D), либо в диапазоне ASCII цифры, прописные буквы ASCII или строчные буквы ASCII, то по историческим причинам все символы, которые были сопоставлены после того, как символ U + 0026 AMPERSAND (&) должен быть не загружен, и ничего не возвращается.
Таким образом, в значении атрибута даже ®=
не будет рассматриваться как содержащий ссылку на символ, и еще меньше ®ion=
. (Но reg_test=
- это другой случай из-за символа подчеркивания.)
В текстовом контенте применяются другие правила. Конструкция ®ion=
вызывает тогда ошибку синтаксического анализа (по правилам HTML5 CR), но с четко определенной обработкой ошибок: ®
распознается как ссылка на символ.
Ответ 3
Возможно, попробуйте заменить &
как &
? Амперсанды - это символы, которые также должны быть экранированы в HTML, потому что они зарезервированы для использования в качестве частей сущностей.
Ответ 4
1: Следующая разметка недействительна в первую очередь (используйте службу проверки валидности W3C)
<a href="http://foo.com/bar?foo=bar®ion=US®ister=lowpass®_test=fail&trademark=correct"></a>
В приведенном выше примере символ &
должен быть закодирован как &
, например:
<a href="http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_test=fail&trademark=correct"></a>
2: Браузеры терпимы; они пытаются разобраться в сломанном HTML. В вашем случае все возможные допустимые объекты HTML преобразуются в объекты HTML.
Ответ 5
Устраните выход!
Достаточно просто вам нужно закодировать формат url в html-формате для точного представления (в идеале вы бы сделали это с помощью функции escaping переменной шаблона шаблона, но запретили это с помощью htmlspecialchars($url)
или htmlentities($url)
в php).
Посмотрите на свой тестовый пример, а затем правильно закодированный html на этом jsfiddle:
http://jsfiddle.net/tchalvakspam/Fp3W6/
Неактивный код здесь:
<div>
Unescaped:
<br>
<a href="">http://foo.com/bar?foo=bar®ion=US®ister=lowpass®_test=fail&trademark=correct</a>
</div>
<div>
Correctly escaped:
<br>
http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_test=fail&trademark=correct
</div>
Ответ 6
Мне кажется, что то, что вы получили от google, не является фактическим URL, а переменной, которая ссылается на url (строка запроса). Итак, вот почему он анализируется как отметка регистрации при визуализации.
Я бы сказал, вы должны его кодировать и декодировать при обработке. Как и любая другая переменная, содержащая специальные сущности.
Ответ 7
Чтобы этого не произошло, вы должны закодировать URL-адреса, который заменяет символы, такие как амперсанд, на% и шестнадцатеричное число за ним в URL-адресе.