50

私はGoogleのアドワーズ広告主導のマーケティングキャンペーンを通じて明らかになった問題に遭遇しました。使用される標準パラメータの1つは「リージョン」です。ユーザーがスポンサーリンクを検索してクリックすると、Googleはクリックを追跡するための長いURLを生成し、リファラーに大量の情報を送信します。これを記録のためにキャプチャしましたが、「Region」パラメータが正しく処理されていないことに気付きました。どうあるべきか

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

代わりに次のように通過します:

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

これがすべてのブラウザで発生することを確認しました。HTMLエンティティの構文は次のように定義されていると私は理解しています。

&VALUE;

ここで、先頭の境界はアンパサンドで、終了の境界はセミコロンです。簡単そうです。問題は、これが®エンティティに対して尊重されておらず、システム全体にあらゆる種類の大混乱を引き起こしていることです。

なぜこれが起こっているのか誰かが知っていますか?DTDのバグですか?(私は現在のHTML DTDを探して、それを理解できるかどうかを確認しています)これを実現するためにブラウザー間で共通することを理解しようとしているので、DTDを探しています。

これがあなたが使える証拠です。このコードを取得し、それからHTMLファイルを作成して、ブラウザーでレンダリングします。

<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>

編集:URL全体をエスケープする必要があることを示唆しているすべての人にとって、上記のURLの例はまさにその例です。実際のURLはGoogleから直接取得されており、その構成方法を制御することはできません。これらの提案は有効ですが、「なぜこれが起こっているのか」という質問には答えません。

4

8 に答える 8

43

有効な文字参照の最後には常にセミコロンがありますが、セミコロンのない無効な名前付き文字参照の中には、下位互換性の理由から、最新のブラウザーのHTMLパーサーによって認識されるものがあります。

そのリスト全体が何であるかを知っているか、&エスケープせずに有効な場合(たとえば、スペースが続く場合)のHTML5規則に従うか、疑わしい場合は常にエスケープ&します。&amp;

参考までに、セミコロンなしで認識される名前付き文字参照の完全なリストは次のとおりです。

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、copy、 curren、deg、divide、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、pound、quot、raquo、reg、sect、shy、sup1、sup2、sup3、szlig、thorn、times、uacute、ucirc、 ugrave、uml、uuml、yacute、yen、yuml

ただし、属性値の場合にのみ、次の文字が=英数字または英数字のASCII文字である場合、上記のリストの名前付き文字参照はHTML5パーサーに準拠することによってそのように処理されないことに注意してください。

終了セミコロンの有無にかかわらず、名前付き文字参照の完全なリストについては、ここを参照してください。

于 2013-03-20T18:58:31.457 に答える
13

これは非常に厄介なビジネスであり、コンテキスト(テキストコンテンツと属性値)によって異なります。

正式には、HTML 4.01までのHTML仕様では、次の文字が名前文字でない場合、エンティティ参照は末尾のセミコロンなしで表示される場合があります。したがって、たとえば&region=、エンティティが定義されていないため、構文的には正しいが未定義になりますregion。XHTMLでは、末尾のセミコロンが必要になります。

ただし、ブラウザは伝統的に他のルールでプレイされてきました。クエリURLの一般的な構文により、たとえば、エンティティ参照としてではなく、単なるテキストデータとして扱われるhref="http://ravercats.com/meow?foo=bar&region=catnip"ように解析されます。&regionそして、それらが形式的に正しくないにもかかわらず、著者は主にそのような構成を使用しました。

質問が言っているように見えることとは反対に、href="http://ravercats.com/meow?foo=bar&region=catnip"実際にはうまく機能します。文字列が属性値ではなくテキストコンテンツ内にある場合、問題が発生します。これはかなりまれです。通常、URLをテキストで記述しません。テキストでは、エンティティ参照(「®」の場合)として認識され、残りは単なる文字データに&region=なるように処理されます。&regこのような奇妙な動作は、HTML5 CRで公式に行われています。ここで、8.2.4.69節のトークン化文字参照は、「二重基準」について説明しています。

文字参照が属性の一部として消費されており、最後に一致した文字が「;」ではない場合 (U + 003B)文字であり、次の文字は "="(U + 003D)文字か、ASCII数字、大文字のASCII文字、または小文字のASCII文字の範囲であり、歴史的な理由から、 U + 0026 AMPERSAND文字(&)が消費されていない必要があり、何も返されない場合に一致します。

したがって、属性値&reg=では、文字参照を含むものとしても扱われず、さらに少なくなります&region=。(ただしreg_test=、アンダースコア文字のため、別のケースです。)

テキストコンテンツでは、他のルールが適用されます。構成&region=により、(HTML5 CRルールによる)解析エラーが発生しますが、明確に定義されたエラー処理&regにより、文字参照として認識されます。

于 2013-03-20T22:14:56.813 に答える
9

&たぶんあなたのように置き換えてみてください&amp;?アンパサンドは、エンティティの一部として使用するために予約されているため、HTMLでもエスケープする必要がある文字です。

于 2013-03-20T18:57:03.540 に答える
4

1:次のマークアップはそもそも無効です( W3C Markup Validation Serviceを使用して確認してください):

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

上記の例では、&文字は次のようにエンコードする必要があります&amp;

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

2:ブラウザは寛容です。彼らは壊れたHTMLを理解しようとします。あなたの場合、おそらく有効なすべてのHTMLエンティティがHTMLエンティティに変換されます。

于 2013-03-20T19:32:48.983 に答える
4

これは簡単な解決策であり、すべての場合に機能するとは限りません。

だからこれから:

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

これに:

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

私たちが知っている&regように、特殊文字をトリガーするからです®

警告: URLクエリ文字列パラメータの順序を制御できない場合は、変数名を別の名前に変更する必要があります。

于 2018-04-17T13:41:12.773 に答える
1

出力をエスケープしてください!

簡単に言うと、正確に表現するにはurl形式をhtml形式にエンコードする必要があります(理想的には、テンプレートエンジンの変数エスケープ関数を使用してエンコードしますが、phpを使用するhtmlspecialchars($url)htmlentities($url)、phpでエンコードする必要はありません)。

テストケースを確認してから、次のjsfiddleで正しくエンコードされたHTMLを確認してください:http: //jsfiddle.net/tchalvakspam/Fp3W6/

ここに非アクティブなコード:

<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&amp;region=US&amp;register=lowpass&amp;reg_test=fail&amp;trademark=correct
</div>
于 2013-03-20T19:15:43.597 に答える
1

あなたがグーグルから受け取ったものは実際のURLではなく、URL(クエリ文字列)を参照する変数であるように私には思えます。そのため、レンダリング時に登録マークとして解析されます。

つまり、処理するたびにurlエンコードしてデコードする必要があります。特別なエンティティを含む他の変数と同じように。

于 2015-11-09T04:55:45.993 に答える
-4

これを防ぐには、 URLをエンコードする必要があります。これにより、アンパサンドなどの文字が、URL内の%とその後ろの16進数に置き換えられます。

于 2013-03-20T18:57:20.480 に答える