簡體   English   中英

PHP中的htmlentities但保留了html標簽

[英]htmlentities in PHP but preserving html tags

我想將字符串中的所有文本轉換為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>

有任何想法嗎?

您可以使用函數get_html_translation_table htmlentities使用的對應列表character => entity。 考慮這段代碼:

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

(您可能需要在手冊中檢查該功能的第二個參數 - 也許您需要將其設置為與默認值不同的值)

它會得到這樣的東西:

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,我想 - 我正試圖找到一個解決方案,並將再次編輯)

第二次編輯幾分鍾之后:在調用str_replace之前,似乎你必須在$search列表上使用utf8_encode :-(

這意味着使用這樣的東西:

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

這一次,應該沒問題^^
它並不真正適合一行,可能不是最優化的解決方案; 但它應該工作正常,並且有一個優點,允許您添加/刪除任何對應的字符=>您需要或不需要的實體。

玩得開心 !

可能不是非常有效,但它的工作原理

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

echo htmlspecialchars_decode(
    htmlentities($sample, ENT_NOQUOTES, 'UTF-8', false)
  , ENT_NOQUOTES
);

這是已接受答案的優化版本。

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

$string = strtr($string, $list);

對於所有情況,解析器之外沒有解決方案是正確的。 你的是一個很好的案例:

<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;', '<')

這是我剛剛編寫的一個函數,它以非常優雅的方式解決了這個問題:

首先,將從字符串中提取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;
}

根據bflesch的答案,我做了一些更改來管理包含less than signgreater than signsingle quotedouble 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>€</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

無需轉換表或自定義功能的單行解決方案:

我知道這是一個老問題,但我最近不得不將靜態網站導入wordpress網站,並且必須克服這個問題:

這是我的解決方案,不需要擺弄翻譯表:

htmlspecialchars_decode( htmlentities( html_entity_decode( $string ) ) );

當應用於OP的字符串時:

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

輸出:

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

當應用於Luca的字符串時:

<b>Is 1 < 4?</b>è<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>€</strong><img src="/some/path" /></p></div>

輸出:

<b>Is 1 < 4?</b>&egrave;<br><i>"then"</i> <div style="some:style;"><p>gain some <strong>&euro;</strong><img src="/some/path" /></p></div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM