60

文字列内のすべてのテキストを html エンティティに変換したいが、HTML タグは保持します。たとえば、次のようになります。

<p><font style="color:#FF0000">Camión español</font></p>

これに翻訳する必要があります:

<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>

何か案は?

4

7 に答える 7

69

htmlentities関数get_html_translation_table;を使用して、文字 => によって使用されるエンティティの対応リストを取得できます。このコードを検討してください:

$list = get_html_translation_table(HTML_ENTITIES);
var_dump($list);

(マニュアルでその関数の 2 番目のパラメーターを確認することをお勧めします。デフォルト値とは異なる値に設定する必要があるかもしれません)

次のようなものが得られます:

array
  ' ' => string '&nbsp;' (length=6)
  '¡' => string '&iexcl;' (length=7)
  '¢' => string '&cent;' (length=6)
  '£' => string '&pound;' (length=7)
  '¤' => string '&curren;' (length=8)
  ....
  ....
  ....
  'ÿ' => string '&yuml;' (length=6)
  '"' => string '&quot;' (length=6)
  '<' => string '&lt;' (length=4)
  '>' => string '&gt;' (length=4)
  '&' => string '&amp;' (length=5)

ここで、不要な対応を削除します。

unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

リストには、エンコードしたくないいくつかの文字を除いて、htmlentites で使用されるすべての対応文字 => エンティティが含まれています。

そして今、キーと値のリストを抽出するだけです:

$search = array_keys($list);
$values = array_values($list);

最後に、 str_replace を使用して置換を行うことができます:

$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_out);

そして、あなたは得る:

string '<p><font style="color:#FF0000">Cami&Atilde;&sup3;n espa&Atilde;&plusmn;ol</font></p>' (length=84)

あなたが望んでいたもののように見えます;-)


編集:まあ、エンコーディングの問題を除いて(くそーUTF-8だと思います-私はその解決策を見つけようとしており、再び編集します)

utf8_encode数分後の2番目の編集:呼び出す前に、$searchリストで使用する必要があるようですstr_replace:-(

これは、次のようなものを使用することを意味します:

$search = array_map('utf8_encode', $search);

array_keysへの呼び出しと への呼び出しの間str_replace

そして今回は、あなたが本当に望んでいたものを手に入れるはずです:

string '<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>' (length=70)


そして、ここにコードの完全な部分があります:

$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

$search = array_keys($list);
$values = array_values($list);
$search = array_map('utf8_encode', $search);

$str_in = '<p><font style="color:#FF0000">Camión español</font></p>';
$str_out = str_replace($search, $values, $str_in);
var_dump($str_in, $str_out);

そして完全な出力:

string '<p><font style="color:#FF0000">Camión español</font></p>' (length=58)
string '<p><font style="color:#FF0000">Cami&oacute;n espa&ntilde;ol</font></p>' (length=70)

今回は、大丈夫です^^
1 行に収まりません。最適化されたソリューションではない可能性があります。しかし、それは正常に動作するはずであり、対応する文字 => エンティティを必要または不要に追加/削除できるという利点があります。

楽しむ !

于 2009-09-01T22:29:40.517 に答える
18

それほど効率的ではないかもしれませんが、うまくいきます

$sample = '<p><font style="color:#FF0000">Camión español</font></p>';

echo htmlspecialchars_decode(
    htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
  , ENT_NOQUOTES
);
于 2009-09-01T22:28:07.293 に答える
7

これは、受け入れられた回答の最適化されたバージョンです。

$list = get_html_translation_table(HTML_ENTITIES);
unset($list['"']);
unset($list['<']);
unset($list['>']);
unset($list['&']);

$string = strtr($string, $list);
于 2010-06-23T16:30:59.430 に答える
5

パーサー以外の解決策は、すべての場合に適切ではありません。あなたは良いケースです:

<p><font style="color:#FF0000">Camión español</font></p>

しかし、あなたもサポートしたいですか:

<p><font>true if 5 < a && name == "joe"</font></p>

次のように出力したい場所:

<p><font>true if 5 &lt; a &amp;&amp; name == &quot;joe&quot;</font></p>

質問: HTML を作成する前にエンコードを行うことはできますか? つまり、次のようなことができます。

"<p><font>" + htmlentities(inner) + "</font></p>"

それができれば、多くの悲しみを避けることができます。それができない場合は、<、>、および " のエンコードをスキップする (上記のように) か、単純にすべてをエンコードしてから元に戻す (例: replace('&lt;', '<'))方法が必要です。

于 2009-09-02T04:54:51.407 に答える
3

これは私が今書いた関数で、この問題を非常にエレガントな方法で解決します。

まず、文字列からHTMLタグが抽出され、残りのすべてのサブ文字列に対してhtmlentities()が実行されます。その後、元のHTMLタグが古い位置に挿入されるため、HTMLタグが変更されることはありません。:-)

楽しむ:

function htmlentitiesOutsideHTMLTags ($htmlText)
{
    $matches = Array();
    $sep = '###HTMLTAG###';

    preg_match_all("@<[^>]*>@", $htmlText, $matches);   
    $tmp = preg_replace("@(<[^>]*>)@", $sep, $htmlText);
    $tmp = explode($sep, $tmp);

    for ($i=0; $i<count($tmp); $i++)
        $tmp[$i] = htmlentities($tmp[$i]);

    $tmp = join($sep, $tmp);

    for ($i=0; $i<count($matches[0]); $i++)
        $tmp = preg_replace("@$sep@", $matches[0][$i], $tmp, 1);

    return $tmp;
}
于 2010-02-26T18:13:21.253 に答える
2

bfleschの回答に基づいて、less than signgreater than signandsingle quoteまたはを含む文字列を管理するためにいくつかの変更を行いdouble quotesました。

function htmlentitiesOutsideHTMLTags ($htmlText, $ent)
{
    $matches = Array();
    $sep = '###HTMLTAG###';

    preg_match_all(":</{0,1}[a-z]+[^>]*>:i", $htmlText, $matches);

    $tmp = preg_replace(":</{0,1}[a-z]+[^>]*>:i", $sep, $htmlText);
    $tmp = explode($sep, $tmp);

    for ($i=0; $i<count($tmp); $i++)
        $tmp[$i] = htmlentities($tmp[$i], $ent, 'UTF-8', false);

    $tmp = join($sep, $tmp);

    for ($i=0; $i<count($matches[0]); $i++)
        $tmp = preg_replace(":$sep:", $matches[0][$i], $tmp, 1);

    return $tmp;
}



使用例:

$string = '<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€&lt;/strong><img src="/some/path" /></p></div>';
$string_entities = htmlentitiesOutsideHTMLTags($string, ENT_QUOTES | ENT_HTML401);
var_dump( $string_entities );

出力は次のとおりです。

string '<b>Is 1 &lt; 4?</b>&egrave;<br><i>&quot;then&quot;</i> <div style="some:style;"><p>gain some <strong>&euro;</strong><img src="/some/path" /></p></div>' (length=150)



htmlentities マニュアルent flagに従って 任意のものを渡すことができます

于 2012-04-23T09:06:37.830 に答える