Waarom wordt “&reg” weergegeven als “®” zonder de begrenzende puntkomma

Ik ben een probleem tegengekomen dat aan het licht is gekomen via onze Google AdWords-gestuurde marketingcampagne. Een van de standaard gebruikte parameters is “regio”. Wanneer een gebruiker op een gesponsorde link zoekt en erop klikt, genereert Google een lange URL om de klik bij te houden en stuurt een heleboel dingen mee in de verwijzer. We leggen dit vast voor onze administratie, en we hebben gemerkt dat de parameter “Regio” niet goed doorkomt. Wat zou moeten zijn

http://ravercats.com/meow?foo=bar&region=catnip

komt in plaats daarvan door als:

http://ravercats.com/meow?foo=bar®ion=catnip

Ik heb geverifieerd dat dit in alle browsers voorkomt. Ik heb begrepen dat HTML-entiteitssyntaxisals volgt is gedefinieerd:

&VALUE;

waarbij de eerste grens de ampersand is en de afsluitende grens de puntkomma is. Lijkt duidelijk genoeg. Het probleem is dat dit niet wordt gerespecteerd voor de entiteit ® en dat het allerlei soorten schade aanricht in ons hele systeem.

Weet iemand waarom dit gebeurt? Is het een bug in de DTD? (Ik ben op zoek naar de huidige HTML DTD om te zien of ik het kan begrijpen) Ik probeer erachter te komen wat in alle browsers gebruikelijk is om dit mogelijk te maken, dus ik ben op zoek naar de DTD.

Hier is een bewijs dat u kunt gebruiken. Neem deze code, maak er een HTML-bestand van en render het in een browser:

<html>
<a href="http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_test=fail&trademark=correct">http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_test=fail&trademark=correct</a>
</html>

EDIT: voor iedereen die suggereert dat ik de hele URL moet escapen, de bovenstaande voorbeeld-URL’s zijn precies dat, voorbeelden. De echte URL komt rechtstreeks van Google en ik heb geen controle over hoe deze is opgebouwd. Deze suggesties, hoewel geldig, geven geen antwoord op de vraag: “Waarom gebeurt dit”.


Antwoord 1, autoriteit 100%

Hoewel geldigetekenverwijzingen altijd een puntkomma hebben, worden sommige ongeldige benoemde tekenverwijzingen zonder puntkomma, om redenen van achterwaartse compatibiliteit, herkend door de HTML-parsers van moderne browsers.

Of je weet wat die hele lijst is, of je volgt de HTML5-regels voor wanneer &geldig is zonder escapetekens (bijv. gevolgd door een spatie) of anders altijd escape &als &amp;bij twijfel.

Ter referentie, de volledige lijst met verwijzingen naar benoemde tekensdie worden herkend zonder puntkomma is:

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, acute, aelig,
agrave, amp, aring, atilde, auml, brvbar, ccedil, cedil, cent, kopiëren,
curren, deg, verdelen, eacute, ecirc, egrave, eth, euml, frac12, frac14,
frac34, gt, iacute, icirc, iexcl, igrave, iquest, iuml, laquo, lt,
macr, micro, middot, nbsp, not, ntilde, oacute, ocirc, ograve, ordf,
ordm, oslash, otilde, ouml, para, plusmn, pond, quot, raquo, reg,
sekte, verlegen, sup1, sup2, sup3, szlig, doorn, tijden, uacute, ucirc,
ugrave, uml, uuml, yacute, yen, yuml

Er moet echter worden opgemerkt dat alleen wanneer in een attribuutwaarde, benoemde tekenreferenties in de bovenstaande lijst niet als zodanig worden verwerkt door HTML5-parsers te conformeren als het volgende teken een =of een alfanumeriek teken is ASCII-teken.

Voor de volledige lijst van benoemde karakterreferenties met of zonder puntkomma’s, zie hier.


Antwoord 2, autoriteit 30%

Dit is een erg rommelige zaak en hangt af van de context (tekstinhoud versus kenmerkwaarde).

Formeel gezien, volgens HTML-specificaties tot en met HTML 4.01, kan een entiteitsverwijzing verschijnen zonder puntkomma achteraan, als het volgende teken geen naamteken is. Dus bijv. &region=zou syntactisch correct zijn, maar niet gedefinieerd, omdat entiteit regionniet is gedefinieerd. XHTML maakt de volgpuntkomma vereist.

Browsers hebben traditioneel echter andere regels gehanteerd. Vanwege de algemene syntaxis van query-URL’s ontleden ze b.v. href="http://ravercats.com/meow?foo=bar&region=catnip"zodat &regionniet wordt behandeld als een entiteitsreferentie, maar als tekst gegevens. En auteurs gebruikten meestal dergelijke constructies, ook al zijn ze formeel onjuist.

In tegenstelling tot wat de vraag lijkt te zeggen, werkt href="http://ravercats.com/meow?foo=bar&region=catnip"eigenlijk goed. Er ontstaan ​​problemen wanneer de tekenreeks zich niet in een attribuutwaarde bevindt, maar in tekstinhoud, wat nogal ongebruikelijk is: we schrijven normaal gesproken geen URL’s in tekst. In tekst wordt &region=zo verwerkt dat &regwordt herkend als een entiteitsreferentie (voor “®”) en de rest alleen tekengegevens zijn. Dergelijk vreemd gedrag wordt officieel gemaakt in HTML5 CR, waar clausule 8.2.4.69 Tokenizing-tekenreferentiesbeschrijft de “dubbele standaard”:

Als de tekenreferentie wordt gebruikt als onderdeel van een kenmerk,
en het laatste overeenkomende teken is geen “;” (U+003B) teken, en
het volgende teken is ofwel een “=” (U+003D) teken of in het bereik
ASCII-cijfers, ASCII-hoofdletters of kleine ASCII-letters,
vervolgens, om historische redenen, alle karakters die overeenkwamen
na het U+0026 AMPERSAND-teken (&) mag niet worden geconsumeerd, en
er wordt niets geretourneerd.

Dus in een attribuutwaardezou zelfs &reg=niet worden behandeld als een tekenreferentie, en nog minder &region=. (Maar reg_test=is een ander geval, vanwege het onderstrepingsteken.)

In tekstinhoudgelden andere regels. De constructie &region=veroorzaakt dan een parseerfout (volgens HTML5 CR-regels), maar met goed gedefinieerde foutafhandeling: &regwordt herkend als een tekenreferentie.


Antwoord 3, autoriteit 21%

Misschien probeer je &te vervangen door &amp;? Ampersands zijn tekens die ook in HTML moeten worden ontsnapt, omdat ze zijn gereserveerd om te worden gebruikt als onderdelen van entiteiten.


Antwoord 4, autoriteit 9%

1:De volgende opmaak is in de eerste plaats ongeldig (gebruik de W3C Markup Validation Serviceom te verifiëren):

<a href="http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_test=fail&trademark=correct"></a>

In het bovenstaande voorbeeld moet het teken &worden gecodeerd als &amp;, zoals:

<a href="http://foo.com/bar?foo=bar&amp;region=US&amp;register=lowpass&amp;reg_test=fail&amp;trademark=correct"></a>

2:Browsers zijn tolerant; ze proberen iets te begrijpen uit gebroken HTML. In jouw geval worden alle mogelijk geldige HTML-entiteiten geconverteerd naar HTML-entiteiten.


Antwoord 5, autoriteit 7%

Hier is een eenvoudige oplossing en deze werkt mogelijk niet in alle gevallen.

Dus hieruit:

http://ravercats.com/meow?status=Online&region=Atlantis

Hiervoor:

http://ravercats.com/meow?region=Atlantis&status=Online

Omdat de &regzoals we die kennen het speciale teken ®

activeert

Voorbehoud:als u geen controle heeft over de volgorde van de parameters van uw URL-queryreeks, moet u de naam van uw variabele wijzigen in iets anders.


Antwoord 6, autoriteit 2%

Ontsnap aan je output!

Gewoon genoeg moet je het url-formaat coderen in html-formaat voor een nauwkeurige weergave (idealiter zou je dit doen met een functie voor het ontsnappen van variabelen in de template-engine, maar behalve dat, met htmlspecialchars($url)of htmlentities($url)in php).

Bekijk je testcase en vervolgens de correct gecodeerde html op deze jsfiddle:
http://jsfiddle.net/tchalvakspam/Fp3W6/

Inactieve code hier:

<div>
Unescaped:
<br>
<a href="">http://foo.com/bar?foo=bar&region=US&register=lowpass&reg_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>

Antwoord 7, autoriteit 2%

Het lijkt mij dat wat je van Google hebt ontvangen geen echte URL is, maar een variabele die verwijst naar een url (query-string). Dus daarom wordt het geparseerd als registratieteken wanneer het wordt weergegeven.

Ik zou zeggen dat je het moet url-encoderen en decoderen wanneer je het verwerkt. Net als elke andere variabele die speciale entiteiten bevat.


Antwoord 8

Om dit te voorkomen, moet u urls coderen, die tekens zoals het ampersand vervangt met een % en een hexadecimaal getal erachter in de url.

Other episodes