Domanda

Ecco l'obiettivo: sostituire tutte le e commerciali standalone con & amp; amp; ma NON sostituire quelli che fanno già parte di un'entità HTML come & amp; nbsp ;.

Penso di aver bisogno di un'espressione regolare per PHP (preferibilmente per le funzioni preg_) che corrisponderà solo alle e commerciali standalone. Semplicemente non so come farlo con preg_replace.

È stato utile?

Soluzione

Potresti sempre eseguire html_entity_decode prima di eseguire htmlentities ? Funziona a meno che tu non voglia fare solo e commerciali (e anche allora puoi giocare con i parametri charset).

Molto più facile e veloce di una regex.

Altri suggerimenti

Il htmlentities () di PHP ha l'argomento double_encode per questo.

Se vuoi fare cose del genere in espressioni regolari, le affermazioni negative diventano utili:

preg_replace('/&(?![a-z#]+;)/i','&',$txt);

Ross mi ha portato a una buona risposta. Ecco il codice che sembra funzionare abbastanza bene. Finora. :-) L'obiettivo, ancora una volta, è convertire HTML in XML, in particolare le descrizioni per i feed RSS. Nel breve test che ho fatto finora (con alcuni dati abbastanza eccentrici) sono stato in grado di prendere stringhe avvolte in CDATA e scartarle. Supera i test di validazione. Grazie, Ross.

//decode all entities
$string=html_entity_decode($string,ENT_COMPAT,'UTF-8');

//entity-encode only &<> and double quotes
$string=htmlspecialchars($string,ENT_COMPAT,'UTF-8');

Gli altri sono buoni suggerimenti e potrebbero essere il modo migliore per farlo. Ma ho pensato di provare a rispondere alla domanda come chiesto, se non altro per fornire un esempio regex.

La seguente è la speciale forma esplosa consentita in alcuni motori. Naturalmente la cosa strana è che un motore che consente regex commentate consente altre espressioni semplificate, ma non così generico. Metterò quelle espressioni semplificate tra parentesi nei commenti.

&                      # an ampersand
( \#                   # a '#' character
  [1-9]                # followed by a non-zero digit, 
  [0-9]{1,3}           # with between 2 and 4             (\d{1,3} or \p{IsDigit}{1,3})
| [A-Za-z]             # OR a letter                      (\p{IsAlpha})
  [0-9A-Za-z]+         # followed by letters or numbers   (\p{IsAlnum}+)
)
;                      # all capped with a ';'

Potresti anche lanciare un mucchio di entità previste anche lì, per aiutare lo scanner regex.

&                      # an ampersand
( amp | apos | gt | lt | nbsp | quot                 
                       # standard entities
| bull | hellip | [lr][ds]quo | [mn]dash | permil          
                       # some fancier ones
| \#                   # a '#' character
  [1-9]                # followed by a non-zero digit, 
  [0-9]{1,3}           # with between 2 and 4 
|  [A-Za-z]            # OR a letter
  [0-9A-Za-z]+         # followed by letters or numbers
)
;                      # all capped with a ';'

Ho avuto lo stesso problema, originariamente utilizzavo:

$string = htmlspecialchars($string, ENT_QUOTES, "UTF-8", FALSE);

Ma serviva che funzionasse con PHP4 e un mix di CharSet, finito con:


function htmlspecialchars_custom($string)
{
  $string = str_replace("\x05\x06", "", $string);
  $string = preg_replace("/&([a-z\d]{2,7}|#\d{2,5});/i", "\x05\x06$1", $string);
  $string = htmlspecialchars($string, ENT_QUOTES);
  $string = str_replace("\x05\x06", "&", $string);

  return $string;
}

Non è perfetto, ma abbastanza buono per le mie esigenze.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top