Мне действительно нужно кодировать '&' как '& amp;'?

207

Я использую &символ ' ' с HTML5 и UTF-8 на своем сайте <title>. Google показывает амперсанд отлично на его выдаче, как и все браузеры в их названиях.

http://validator.w3.org дает мне это:

& не начал ссылку на символ. (и, вероятно, следовало бы избежать как &amp;.)

Мне действительно нужно сделать &amp;?

Я не беспокоюсь о том, что мои страницы проверяются ради подтверждения, но мне любопытно услышать мнение людей по этому поводу, а также важно ли это и почему.

Haroldo
источник
63
Спецификации не говорят так. Плакат относится к HTML5, который не требует выхода из амперсанда во всех сценариях.
Мэтью Уилсон
2
Это должна быть вики-страница сообщества, так как вы ищете мнения, а отсутствие суеты по поводу проверки подразумевает, что нет объективных оснований для ответа.
Ричард Дж.П. Ле Гуен
6
@Richard: правда? Хотя я не согласен с тем, что «валидация не имеет значения», я считаю это очень объективным вопросом: «это нарушает что-либо кроме спецификации?»
Иоахим Зауэр
2
@YiJiang Современные веб-браузеры идут на все, чтобы понять пользователя . И Google тоже . Это часть Spec. Будущие веб-браузеры могут быть менее щадящими. Поэтому всегда полезно проверить, как это делает Википедия, и скопировать их.
unixman83
2
Спецификация HTML говорит, что нужно принимать дерьмовый ввод. Означает ли это, что ваш сайт "позволено" быть дерьмом сейчас? Закрывайте теги, которые нужно закрыть, и избегайте вещей! Давай люди.
doug65536

Ответы:

143

Да. Как и в сообщении об ошибке, в HTML атрибуты #PCDATA означают, что они анализируются. Это означает, что вы можете использовать символьные объекты в атрибутах. Использование &само по себе неправильно , и если не для мягких браузеров и тот факт , что это HTML не XHTML, разорвет разборе. Просто избегайте этого, &amp;и все будет хорошо.

HTML5 позволяет оставить его без экранирования, но только в том случае, если последующие данные не похожи на действительную ссылку на символ. Тем не менее, лучше просто избежать всех экземпляров этого символа, чем беспокоиться о том, какие из них должны быть, а какие нет.

Помните об этом; если вы не экранируете & в & amp;, это достаточно плохо для создаваемых вами данных (где код вполне может быть недействительным), вы также можете не экранировать теги-разделители, что является огромной проблемой для данных, отправляемых пользователями, что вполне может привести к внедрению HTML и скриптов, краже файлов cookie и другим действиям.

Пожалуйста, просто избегайте вашего кода. Это избавит вас от многих неприятностей в будущем.

Делан Азабани
источник
9
Ни один браузер никогда не будет «неверно истолковывать» a &. Каждый существующий браузер отображает его как «&». Принимая во внимание, что он явно попросил практическую причину сделать это, и что он заявил, что его не волнует проверка ...
Томас Бонини
47
Да. Но морально, мы должны полагаться на снисходительность и "хорошую" обработку ошибок браузеров? Или мы должны просто написать правильный код?
Делан Азабани
8
@Delan: хотя я пытаюсь сделать каждую написанную страницу достоверной, я понимаю, прочитав его вопрос, что он не заботится о «морально». Ему просто все равно, работает это или нет. Это две разные философии, и у каждой есть свои плюсы и минусы, и нет «правильной». Например, этот сайт не проверяется, и все же это отличный сайт.
Томас Бонини
3
@ Андреас, но браузеры имеют достаточно ошибок в том, как они интерпретируют правильный код, в зависимости от того, получают ли они правильные результаты, когда вы отправляете им бессмысленную разметку - это случайность. Он может работать сегодня с этим примером, а затем потерпеть неудачу со следующим примером (скажем, если следующий пример имеет точку с запятой где-то после &)
Джон Ханна
11
Кажется, все говорят о HTML5, но в первоначальном вопросе говорится, что HTML5 используется. HTML5 явно разрешает скрываться и в этой ситуации, если только то, что следует, & обычно не расширяется до сущности (например, & copy = 2 проблематично, но & x = 2 хорошо).
Мэтью Уилсон
55

Помимо проверки, факт остается фактом: кодирование определенных символов важно для документа HTML, чтобы он мог правильно и безопасно отображаться как веб-страница.

Для меня кодирование, &как &amp;при любых обстоятельствах, является более легким правилом, снижающим вероятность ошибок и сбоев.

Сравните следующее: что проще? что легче поднять ?

Методология 1

  1. Напишите некоторый контент, который включает символы амперсанда.
  2. Кодируй их всех.

Методология 2

(с крошкой соли, пожалуйста;))

  1. Напишите некоторый контент, который включает символы амперсанда.
  2. В каждом конкретном случае посмотрите на каждый амперсанд. Определите, если:
    • Он изолирован и как таковой однозначно амперсанд. например. volt & amp
       > В этом случае не беспокойтесь о его кодировании.
    • Он не изолирован, но вы чувствуете, что он, тем не менее, недвусмысленен, поскольку результирующая сущность не существует и никогда не будет существовать, поскольку список сущностей никогда не сможет развиваться. Например amp&volt
       > В этом случае не беспокойтесь о его кодировании.
    • Он не изолирован и неоднозначен. например. volt&amp
       > Закодировать это.

??

Ричард Дж.П. Ле Гуэн
источник
3
Второй случай amp&volt является неоднозначным: Является ли &voltтеперь ссылка на сущность или нет?
Гамбо
6
@Gumbo Амперсанд в amp&voltэто не неоднозначный амперсанд (в соответствии с определением в HTML - спецификации). См. Mathiasbynens.be/notes/ambiguous-ampersands и mothereff.in/ampersands#amp%26volt .
Матиас Биненс
@MathiasBynens К настоящему времени (2019) определение неоднозначного амперсанда, похоже, немного изменилось по сравнению с определением, которое вы цитировали в 2011 году в mathiasbynens.be/notes/ambiguous-ampersands .
Джейкоб С. говорит восстановить
21

Правила HTML5 отличаются от HTML4. Это не требуется в HTML5 - если амперсанд не выглядит так, как будто он запускает имя параметра. «& copy = 2» по-прежнему проблема, например, так как & copy; является символом авторского права.

Однако мне кажется, что труднее решить, кодировать или не кодировать, в зависимости от следующего текста. Так что, возможно, самый простой путь - это все время кодировать.

Мэтью Уилсон
источник
2
Это похоже на цитирование значений атрибутов - вам не нужно, но вы не ошибетесь, если будете делать это все время.
Пол Д. Уэйт
3
&copy=2не такая большая проблема, как вы думаете. В значениях атрибутов (например, hrefатрибут), &copyне будет рассматриваться как символьная ссылка для ©. Вне значения атрибута это было бы.
Матиас Биненс
Учитывая, что перед английским текстом перед амперсандом обычно стоит пробел, за которым следует пробел, не трудно вспомнить или подумать о правиле, которому я следую: если амперсанд не касается другого видимого символа, что почти всегда, то в этом нет необходимости кодирование. В противном случае, просто для простоты кодирования.
Карл Смит
Не могли бы вы добавить ссылку на правила HTML5?
Ferrybig
17

Я думаю, что это превратилось в вопрос «зачем следовать спецификации, если браузеру все равно». Вот мой обобщенный ответ:

Стандарты не являются «настоящей» вещью. Это «будущее». Если мы, как разработчики, следуем веб-стандартам, то поставщики браузеров с большей вероятностью будут правильно применять эти стандарты, и мы приблизимся к полностью совместимому вебу, где хакерские функции CSS, обнаружение функций и обнаружение браузера не нужны. Где нам не нужно выяснять, почему наши макеты ломаются в конкретном браузере или как обойти это.

В частности, если HTML5 не требует использования & amp; в вашей конкретной ситуации, когда вы используете тип документа HTML5 (а также ожидаете, что ваши пользователи будут использовать браузеры, совместимые с HTML5), тогда нет причин делать это.

Райан Кинал
источник
1
При этом, в общем, вы должны помнить, что большинство «стандартных» способов все еще находятся в черновом режиме и могут измениться в будущем.
refaelio
6

Ну, если это происходит из-за пользовательского ввода, то, конечно, по очевидным причинам. Подумайте, если бы этот веб-сайт этого не делал: название этого вопроса появилось бы так, как мне действительно нужно кодировать '&' как '&'?

Если это просто что-то вроде echo '<title>Dolce & Gabbana</title>';этого, строго говоря, вам не нужно. Было бы лучше, но если вы этого не сделаете, пользователь не заметит разницу.

Томас Бонини
источник
5

Не могли бы вы показать нам, что вы на titleсамом деле? Когда я отправляю

<!DOCTYPE html>
<html>
<title>Dolce & Gabbana</title>
<body>
<p>am i allowed loose & mpersands?</p>
</body>
</html>

на http://validator.w3.org/ - явно просить его использовать экспериментальный режим HTML 5 - он не имеет никаких претензий по поводу &...

AakashM
источник
1
Да, HTML5 имеет другой синтаксический анализатор, чем предыдущие анализаторы HTML и XHTML, и в определенных ситуациях допускает использование амперсандов без экранирования.
Кевинджи
Что касается этих примеров, в HTML5 нет ничего нового. Оба <title>Dolce & Gabbana</title>и <p>Dolce & Gabbana</p>действительны HTML 2.0.
Матиас Биненс
4

В HTML a &отмечает начало ссылки, либо ссылки на символ , либо ссылки на сущность . С этого момента синтаксический анализатор ожидает либо #обозначение ссылки на символ, либо имя сущности, обозначающее ссылку на сущность, за которой следует буква a ;. Это нормальное поведение.

Но если имя ссылки или просто ссылка открытие &сопровождается пробелом или другими разделителями нравится ", ', <, >, &, окончание ;и даже ссылка для представления равнины &можно опустить:

<p title="&amp;">foo &amp; bar</p>
<p title="&amp">foo &amp bar</p>
<p title="&">foo & bar</p>

Только в этих случаях конец ;или даже сама ссылка могут быть опущены (по крайней мере, в HTML 4). Я думаю, что HTML 5 требует окончания ;.

Но спецификация рекомендует всегда использовать ссылку, такую ​​как ссылка на символ &#38;или ссылку на сущность, &amp;чтобы избежать путаницы:

Авторам следует использовать « &amp;» (десятичное число ASCII 38) вместо « &», чтобы избежать путаницы с началом ссылки на символ (открытый разделитель ссылки на сущность). Авторам также следует использовать « &amp;» в значениях атрибутов, поскольку ссылки на символы допускаются в значениях атрибутов CDATA.

гумбо
источник
1
Это спецификация HTML 4, на которую вы ссылаетесь; из моего прочтения (черновой) спецификации HTML 5 запрещены только неоднозначные амперсанды. Например, амперсанд, за которым следует пробел, не является двусмысленным, и поэтому (опять же по моим прочтениям) должен быть разрешен - см. Мой ответ для разметки, который принимает валидатор HTML 5.
AakashM
1
@AakashM: Я не уверен, это звучало так.
Гамбо
3

Если пользователь передает его вам, или он попадет в URL, вам нужно его избежать.

Если это появляется в статическом тексте на странице? Все браузеры поймут это правильно в любом случае, вы не беспокоитесь об этом, так как он будет работать.

Дин Дж
источник
3

Обновление (март 2020 г.): валидатор W3C больше не жалуется на экранирование URL-адресов.

Я проверял, почему URL изображения нужно экранировать, поэтому попробовал сделать это на https://validator.w3.org . Объяснение довольно хорошее. Это подчеркивает, что даже URL должны быть экранированы. [PS: я полагаю, что он будет удален, когда его потребляют, так как URL нужен &. Кто-нибудь может уточнить?]

<img alt="" src="foo?bar=qut&qux=fop" />

Ссылка на сущность была найдена в документе, но нет ссылки на это имя. Часто это вызвано неправильным написание названия в качестве ссылки, незакодированных амперсандов или убрав замыкающую точку с запятой (;). Наиболее распространенной причиной этой ошибки являются незашифрованные амперсанды в URL, как описано WDG в разделе «Амперсанды в URL». Ссылки на сущности начинаются с амперсанда (&) и заканчиваются точкой с запятой (;). Если вы хотите использовать буквальный амперсанд в своем документе, вы должны закодировать его как «&» (даже внутри URL!). Будьте осторожны, заканчивая ссылки на сущности точкой с запятой, иначе ссылка на вашу сущность может быть интерпретирована в связи со следующим текстом. Также имейте в виду, что ссылки на именованные сущности чувствительны к регистру; & Aelig; и æ разные символы.

Nishant
источник
1
Прочитайте ответ с наибольшим количеством голосов. Атрибуты #PCDATA и, следовательно, анализируются. Объекты обрабатываются там. В вашем примере &начинается ссылка на сущность. После прочтения &quxсинтаксический анализатор не находит окончательной точки с запятой ( ;), но наталкивается на знак равенства ( =), который не может быть частью имени объекта. Это должно быть ошибкой синтаксического анализа, если синтаксический анализатор пытался быть очень строгим (согласно HTML 4). В HTML 5 разбор сущностей в целом более упрощен.
Палек
1
Я подозреваю, что ;по этой причине лучше всего использовать в качестве разделителя в строках запроса (когда вы управляете ссылкой).
Деми
2

Да, вы должны попытаться предоставить действительный код, если это возможно.

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

Некоторые примеры, когда браузеры могут реагировать по-разному, это если вы помещаете элементы в таблицу, но вне ячеек таблицы, или если вы вкладываете ссылки друг в друга.

Для вашего конкретного примера это вряд ли вызовет какие-либо проблемы, но исправление ошибок в браузере может, например, привести к тому, что браузер перейдет из режима соответствия стандартам в режим совместимости, что может привести к полной поломке макета.

Таким образом, вы должны исправить подобные ошибки в коде, если не для чего-то еще, чтобы сохранить список ошибок в валидаторе коротким, чтобы вы могли обнаружить более серьезные проблемы.

Guffa
источник
2

Пару лет назад мы получили сообщение о том, что одно из наших веб-приложений некорректно отображалось в Firefox. Оказалось, что страница содержала тег, который выглядел как

<div style="..." ... style="...">

Столкнувшись с повторяющимся стилевым атрибутом, IE объединяет оба стиля, в то время как Firefox использует только один из них, следовательно, различное поведение. Я изменил тег на

<div style="...; ..." ...>

и, конечно же, это решило проблему! Мораль этой истории заключается в том, что браузеры более последовательно обрабатывают действительный HTML, чем недействительный HTML. Итак, исправьте свою чертову разметку уже! (Или используйте HTML Tidy, чтобы исправить это.)

dan04
источник
1

если &используется в HTML то вы должны избежать его

Если &используется в строках JavaScript, например,alert('This & that'); или document.href, вам не нужно его использовать.

Если вы используете document.write, то вы должны использовать его, например, document.write(<p>this &amp; that</p>)

Alex
источник
document.writeследует избегать. Смотрите окно с предупреждением в w3.org/html/wg/drafts/html/master/dom.html#document.write%28%29
Oriol
Хороший вопрос о document.write(). Но главное, что Алекс делает для записи в документ со сценариев, IMO. +1
Патрик М
1

Это зависит от вероятности того, что точка с запятой окажется возле вашей &, что приведет к отображению чего-то совершенно другого.

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

Для вашего собственного статического HTML, конечно, вы могли бы его пропустить, но включить трикотаж настолько просто, что нет веской причины его избегать.

Дуглас
источник
0

Если вы действительно говорите о статическом тексте

<title>Foo & Bar</title>

хранится в каком-то файле на жестком диске и обслуживается непосредственно сервером, тогда да: его, вероятно, не нужно экранировать.

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

Если вы не избежите простого &, то, скорее всего, вы также не избежите &amp;или &nbsp;или <b>или <script src="http://attacker.com/evil.js">или любого другого недействительного текста. Это будет означать, что вы в лучшем случае отображаете свой контент неправильно и, скорее всего, подвержены атакам XSS .

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

Йоахим Зауэр
источник
2
Я не понизил голос, но, если бы мне пришлось угадывать, я бы сказал, что за вас проголосовали, потому что ваш ответ (хотя и умный) немного не соответствует вопросу. Он не спрашивает о том, чтобы избежать пользовательского ввода. Он контролирует персонажей и в основном спрашивает: «Если он делает то, что я хочу, действительно ли важно следовать спецификации языка к букве?» То есть он знает, что есть &, потому что он вставил его.
Мэтт
@Matt: я вижу, и это было бы разумно. Я просто предполагал, что никто больше не пишет полностью статические HTML-страницы и что почти весь контент, по крайней мере, несколько динамический (обычно основанный на некотором содержимом базы данных). Возможно, это предположение следовало сделать явным.
Иоахим Зауэр
-1

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

Добавьте это к переопределению рендера на главной странице или элементе управления:

Пожалуйста, не сердитесь на меня за то, что я поставил это не в том месте:

// remove the & from href="blaw?a=b&b=c" and replace with &amp; 
//in urls - this corrects any unencoded & not just those in URL's
// this match will also ignore any matches it finds within <script> blocks AND
// it will also ignore the matches where the link includes a javascript command like
// <a href="javascript:alert{'& & &'}">blaw</a>
html = Regex.Replace(html, "&(?!(?<=(?<outerquote>[\"'])javascript:(?>(?!\\k<outerquote>|[>]).)*)\\k<outerquote>?)(?!(?:[a-zA-Z][a-zA-Z0-9]*|#\\d+);)(?!(?>(?:(?!<script|\\/script>).)*)\\/script>)", "&amp;", RegexOptions.Singleline | RegexOptions.IgnoreCase);
Ричард Дюфур
источник
-1

Ссылка имеет довольно хороший пример того , когда и почему вы , возможно , придется уйти &в&amp;

https://jsfiddle.net/vh2h7usk/1/

Интересно, что мне пришлось убежать от персонажа, чтобы правильно представить его в своем ответе здесь. Если бы я использовал опцию встроенного примера кода (из панели ответов), я мог бы просто набрать, &amp;и это выглядит так, как должно. Но если бы мне пришлось использовать <code></code>элемент вручную , мне нужно было бы убежать, чтобы правильно его представить :)

Mathin
источник