Vraag Inverse htmlentities / html_entity_decode


In principe wil ik een string als deze veranderen:

<code> &lt;div&gt; blabla &lt;/div&gt; </code>

in dit:

&lt;code&gt; <div> blabla </div> &lt;/code&gt;

Hoe kan ik het doen?


De use case (voor sommige mensen waren ze nieuwsgierig):

Een pagina zoals deze met een lijst met toegestane HTML-tags en voorbeelden. Bijvoorbeeld, <code> is een toegestane tag en dit zou het voorbeeld zijn:

<code>&lt;?php echo "Hello World!"; ?&gt;</code>

Ik wilde een reverse-functie omdat er veel van dergelijke tags met samples zijn die ik allemaal opsla in een array die ik in één lus itereer, in plaats van elk afzonderlijk te behandelen ...


11
2017-07-12 17:20


oorsprong


antwoorden:


Mijn versie met behulp van reguliere expressies:

$string = '<code> &lt;div&gt; blabla &lt;/div&gt; </code>';
$new_string = preg_replace(
    '/(.*?)(<.*?>|$)/se', 
    'html_entity_decode("$1").htmlentities("$2")', 
    $string
);

Het probeert om elke te evenaren label en textnode en pas dan toe htmlentities en html_entity_decode respectievelijk.


4
2017-07-17 11:33



Er is geen bestaande functie, maar kijk hiernaar. Tot dusverre heb ik het alleen op uw voorbeeld getest, maar deze functie zou moeten werken alle htmlentities

function html_entity_invert($string) {
    $matches = $store = array();
    preg_match_all('/(&(#?\w){2,6};)/', $string, $matches, PREG_SET_ORDER);

    foreach ($matches as $i => $match) {
        $key = '__STORED_ENTITY_' . $i . '__';
        $store[$key] = html_entity_decode($match[0]);
        $string = str_replace($match[0], $key, $string);
    }

    return str_replace(array_keys($store), $store, htmlentities($string));
}

Bijwerken:

  • Dankzij @Mike om de tijd te nemen om mijn functie met andere reeksen te testen. Ik heb mijn regex bijgewerkt vanaf /(\&(.+)\;)/ naar /(\&([^\&\;]+)\;)/ die moet zorgen voor het probleem dat hij aan de orde stelde.

  • Ik heb ook toegevoegd {2,6} om de lengte van elke wedstrijd te beperken om de kans op valse positieven te verkleinen.

  • Regex gewijzigd van /(\&([^\&\;]+){2,6}\;)/ naar /(&([^&;]+){2,6};)/ om onnodig excapen te verwijderen.

  • Whooa, hersengolf! De regex is gewijzigd van /(&([^&;]+){2,6};)/ naar /(&(#?\w){2,6};)/ om de kans op valse positieven te verkleinen zelfs verder!


4
2017-07-16 14:45



Alleen vervangen is niet goed genoeg voor jou. Of het nu gaat om reguliere expressies of eenvoudig vervangen van tekenreeksen, want als u de & lt & gt-tekens vervangt door de <en> -tekens of omgekeerd, krijgt u uiteindelijk één codering / decodering (alle & lt en & gt of alle <en> tekens).

Dus als u dit wilt doen, moet u een set ontleden (ik kies ervoor om deze te vervangen door een plaatshouder), doe een vervanging en doe ze daarna weer terug en doe nog een vervanging.

$str = "<code> &lt;div&gt; blabla &lt;/div&gt; </code>";
$search = array("&lt;","&gt;",);

//place holder for &lt; and &gt;
$replace = array("[","]");

//first replace to sub out &lt; and &gt; for [ and ] respectively
$str = str_replace($search, $replace, $str);

//second replace to get rid of original < and >
$search = array("<",">");
$replace = array("&lt;","&gt;",);
$str = str_replace($search, $replace, $str);

//third replace to turn [ and ] into < and >
$search = array("[","]");
$replace = array("<",">");

$str = str_replace($search, $replace, $str);

echo $str;

1
2017-07-12 18:46



Ik denk dat ik een kleine oplossing heb, waarom html-tags niet in een array breken en vervolgens vergelijken en wijzigen als dat nodig is?

function invertHTML($str) {
    $res = array();
    for ($i=0, $j=0; $i < strlen($str); $i++) { 
        if ($str{$i} == "<") { 
           if (isset($res[$j]) && strlen($res[$j]) > 0){
                $j++; 
                $res[$j] = '';
           } else {
               $res[$j] = '';
           }
           $pos = strpos($str, ">", $i); 
           $res[$j] .= substr($str, $i, $pos - $i+1); 
           $i += ($pos - $i); 
           $j++;
           $res[$j] = '';
           continue; 
        } 
        $res[$j] .= $str{$i}; 
    } 

    $newString = '';
    foreach($res as $html){
        $change = html_entity_decode($html);
        if($change != $html){
            $newString .= $change;
        } else {
            $newString .= htmlentities($html);
        }
    }
    return $newString; 
}

Gewijzigd .... zonder fouten.


1
2017-07-17 07:14



Dus, hoewel andere mensen hier regelmatige uitdrukkingen hebben aanbevolen, wat misschien wel de absoluut juiste manier is om te gaan ... Ik wilde dit posten, omdat het voldoende is voor de vraag die je hebt gesteld.

Ervan uitgaande dat u altijd de code van html'esque gebruikt:

 $str = '<code> &lt;div&gt; blabla &lt;/div&gt; </code>';
 xml_parse_into_struct(xml_parser_create(), $str, $nodes);
 $xmlArr = array();
 foreach($nodes as $node) { 
     echo htmlentities('<' . $node['tag'] . '>') . html_entity_decode($node['value']) . htmlentities('</' . $node['tag'] . '>');
 }

Geeft me de volgende output:

&lt;CODE&gt; <div> blabla </div> &lt;/CODE&gt;

Redelijk zeker dat dit niet zou ondersteunen om weer achteruit te gaan .. zoals andere geposte oplossingen zouden zijn, in de zin van:

 $orig = '<code> &lt;div&gt; blabla &lt;/div&gt; </code>';
 $modified = '&lt;CODE&gt; <div> blabla </div> &lt;/CODE&gt;';
 $modifiedAgain = '<code> &lt;div&gt; blabla &lt;/div&gt; </code>';

1
2017-07-17 12:03



Ik raad aan om een ​​reguliere expressie te gebruiken, bijvoorbeeld preg_replace ():


0
2017-07-12 17:33



Bewerken: het lijkt erop dat ik uw vraag niet volledig heb beantwoord. Er is geen ingebouwde PHP-functie om te doen wat je wilt, maar je kunt gewone reguliere expressies of zelfs eenvoudige expressies vinden en vervangen: str_replace, preg_replace


0
2017-07-12 17:26