Кодировать ли амперсанды в <a href...>?
Я пишу код, который автоматически генерирует HTML, и я хочу, чтобы он правильно кодировал вещи.
Скажем, я генерирую ссылку на следующий URL:
http://www.google.com/search?rls=en&q=stack+overflow
Я предполагаю, что все значения атрибутов должны быть в кодировке HTML. (Пожалуйста, исправьте меня, если я ошибаюсь.) Это означает, что если я помещаю вышеуказанный URL в тег привязки, я должен закодировать амперсанд как &
, как это:
<a href="http://www.google.com/search?rls=en&q=stack+overflow">
Это верно?
4 ответа
Да, это. HTML-сущности анализируются внутри атрибутов HTML и &
создаст двусмысленность. Вот почему вы всегда должны писать &
вместо просто &
внутри всех атрибутов HTML.
Тем не менее, только &
и кавычки должны быть закодированы. Если у вас есть специальные символы, такие как é
в вашем атрибуте вам не нужно кодировать их, чтобы удовлетворить анализатор HTML.
Раньше было так, что URL-адреса нуждались в специальной обработке с не-ASCII символами, например é
, Вы должны были закодировать тех, кто использует процент-экранирование, и в этом случае это дало бы %C3%A9
потому что они были определены RFC 1738. Однако RFC 1738 был заменен RFC 3986 (URI, унифицированные идентификаторы ресурсов) и RFC 3987 (IRI, интернационализированные идентификаторы ресурсов), на которых WhatWG основывал свою работу, чтобы определить, как должны вести себя браузеры, когда они видят URL с не-ASCII символы в нем начиная с HTML5. Поэтому теперь безопасно включать не-ASCII символы в URL, в процентах или нет.
Согласно действующим официальным рекомендациям HTML, амперсанд должен быть экранирован, например, как &
в таких ситуациях Тем не менее, браузеры не требуют этого, и HTML5 CR предлагает сделать это правилом, чтобы специальные значения применялись в значениях атрибутов. Текущие валидаторы HTML5 в этом отношении устарели (см. Сообщение об ошибке с комментариями).
По-прежнему будет возможно избежать амперсандов в значениях атрибутов, но кроме проверки с помощью текущих инструментов, нет практической необходимости избегать их в href
ценности (и есть небольшой риск ошибиться, если вы начнете избегать их).
Я публикую новый ответ, потому что обнаружил, что в ответе zneak не хватает примеров, он не показывает обработку HTML и URI как различные аспекты и стандарты, а некоторые мелочи отсутствуют.
У вас есть два стандарта, касающиеся URL в ссылках (<a href
).
Первым стандартом является RFC 1866 (HTML 2.0), где в "3.2.1. Символы данных" вы можете прочитать символы, которые необходимо экранировать при использовании в качестве значения для атрибута HTML. (Сами атрибуты вообще не позволяют использовать специальные символы, например, <a hr&ef="http://...
не допускается и не является <a hr&ef="http://...
.)
Позже это вошло в стандарт HTML 4, символы, которые вы должны экранировать:
< to <
> to >
& to &
" to "e;
' to '
Другим стандартом является RFC 3986 "Общий стандарт URI", где обрабатываются URL-адреса (это происходит, когда браузер собирается перейти по ссылке, потому что пользователь нажал на элемент HTML).
reserved = gen-delims / sub-delims
gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
Важно избегать этих символов, чтобы клиент знал, представляют ли они данные или разделитель.
Пример unescaped:
https://example.com/?user=test&password&te&st&goto=https://google.com
Пример, полностью допустимый URL
https://example.com/?user=test&password&te%26st&goto=https%3A%2F%2Fgoogle.com
Пример полностью допустимого URL в значении атрибута HTML:
https://example.com/?user=test&password&te%26st&goto=https%3A%2F%2Fgoogle.com
Также важны сценарии:
Javascript как значение:
<img src="..." onclick="window.location.href = "https://example.com/?user=test&password&te%26st&goto=https%3A%2F%2Fgoogle.com";">...</a>
(Да,;;
верно.)JSON как значение:
<a href="..." data-analytics="{"event": "click"}">...</a>
Экранированные вещи внутри экранированных вещей, двойное кодирование, URL внутри URL внутри параметра и т. Д.,...
http://x.com/?passwordUrl=http%3A%2F%2Fy.com%2F%3Fuser%3Dtest&password=""123
Да, вы должны конвертировать &
в &
,
Этот инструмент проверки html от W3C полезен для вопросов, подобных этому. Он расскажет вам об ошибках и предупреждениях для конкретной страницы.