在PHPヶ辆,但保存的HTML标签(htmlentities in PHP but preservi

2019-07-04 07:59发布

我想所有的文本转换成字符串转换成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>

有任何想法吗?

Answer 1:

你可以得到correspondances人物名单=>通过使用实体htmlentities ,与功能get_html_translation_table ; 考虑下面的代码:

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

现在,删除不想要的correspondances:

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

您的清单,目前,已通过htmlentites使用,除非你不想编码几个字符的所有字符correspondances =>实体。

而现在,你只需要提取键和值的列表:

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

这一次,它应该确定^^
它并不真正适合在一条线,就是可能不是最优化的解决方案; 但它应该做工精细,并具有允许您添加/删除任何对应关系性格的优势=>实体,你需要与否。

玩得开心 !



Answer 2:

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

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

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


Answer 3:

这是优化的接受的答案的版本。

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

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


Answer 4:

没有解析器的解决方案短期将是对所有的情况下是正确的。 你是一个很好的例子:

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



Answer 5:

这是我刚刚写了一个函数,它以一种非常优雅的方式解决了这个问题:

首先,HTML标签将从串中提取,然后ヶ辆()是在每一个剩余的子串执行,从而导致没有交替的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;
}


Answer 6:

基于对答案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)



你可以通过任何ent flag根据ヶ辆手册



Answer 7:

与NO转换表或自定义函数单行解决方案所需:

我知道这是一个老问题,但我最近不得不进口静态站点到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>

当应用于卢卡的字符串:

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


文章来源: htmlentities in PHP but preserving html tags