xml_set_character_data_handler()
La funzione xml_set_character_data_handler() imposta una funzione definita dall'utente come handler per i dati carattere in un parser XML PHP.
La funzione xml_set_character_data_handler() registra un callback definito dall'utente che il parser XML richiama ogni volta che incontra dati carattere — il contenuto testuale che si trova tra i tag XML. Appartiene all'estensione legacy xml, che racchiude il parser Expat basato sugli eventi, ed è quindi parte dell'API di parsing "a flusso" (stile SAX) di PHP piuttosto che degli approcci ad albero come DOMDocument o SimpleXML.
Si ricorre a questa funzione ogni volta che si vuole catturare o trasformare il testo all'interno degli elementi mentre il documento scorre — ad esempio, raccogliendo il titolo di ogni <item> in un feed RSS, oppure eseguendo una trasformazione sul testo estratto senza mai costruire l'intero documento in memoria. Viene quasi sempre usata insieme a xml_set_element_handler(), che indica a quale elemento appartiene il testo.
Attenzione: l'estensione
xmlè legacy. Per il codice nuovo si preferisceSimpleXMLoDOMDocument. Usa questo handler quando stai mantenendo parser esistenti basati su Expat o hai genuinamente bisogno dello streaming guidato dagli eventi per documenti molto grandi.
Sintassi
xml_set_character_data_handler(XMLParser $parser, callable $handler): bool$parser— il parser creato daxml_parser_create().$handler— il callback da invocare per i dati carattere. Si può passare il nome di una funzione come string, una closure oppure un array per un callback di metodo. Passando una string vuota""si rimuove un handler precedentemente registrato.
La funzione restituisce true in caso di successo.
La firma dell'handler
Il tuo handler riceve due argomenti — il parser e il frammento di testo:
function handler(XMLParser $parser, string $data): voidDocumentazioni più vecchie mostrano talvolta un terzo parametro $length, ma l'estensione xml basata su Expat non lo passa. Su PHP 8+, dichiarare un terzo parametro obbligatorio genera un ArgumentCountError, quindi mantieni il tuo handler a due parametri (oppure rendi opzionali quelli aggiuntivi).
Esempi di utilizzo
Esempio 1: un handler minimo per i dati carattere
Crea un parser, collega un handler, quindi alimentalo con una string XML. L'handler si limita a stampare il testo ricevuto dopo il trim:
function handle_character_data($parser, $data) {
echo trim($data);
}
$xml_parser = xml_parser_create();
xml_set_character_data_handler($xml_parser, "handle_character_data");
$xml_data = '<root><item>Hello World</item></root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);
// Output: Hello Worldxml_parser_create() costruisce il parser, xml_set_character_data_handler() collega il callback, xml_parse() fa scorrere i dati (il true finale lo segna come ultimo blocco) e xml_parser_free() libera il parser.
Il problema dei frammenti
Il parser può chiamare il tuo handler più volte per un singolo elemento, e si attiva anche per gli spazi bianchi tra gli elementi. Non ti consegna una string ordinata per ogni elemento. Guarda cosa succede con due elementi e qualche indentazione:
function show($parser, $data) {
echo '[' . $data . "]\n";
}
$p = xml_parser_create();
xml_set_character_data_handler($p, "show");
$xml = '<root><item>Hello World</item> <item>Goodbye</item></root>';
xml_parse($p, $xml, true);
xml_parser_free($p);
// Output:
// [Hello World]
// [ ]
// [Goodbye]Lo spazio di due caratteri tra </item> e il successivo <item> attiva una propria chiamata. Testi lunghi possono anche arrivare suddivisi in più chiamate. Per questo motivo dovresti accumulare i dati in un buffer e agire solo quando sai che l'elemento è terminato.
Esempio 2: buffering del testo con un handler di elemento
Il pattern affidabile è: azzera un buffer quando un elemento inizia, aggiungi ogni frammento di dati carattere, e leggi il buffer quando l'elemento finisce. Ecco perché xml_set_element_handler() viene quasi sempre abbinato a questa funzione.
$buffer = '';
function start_element($parser, $name, $attrs) {
global $buffer;
$buffer = ''; // start collecting fresh text
}
function character_data($parser, $data) {
global $buffer;
$buffer .= $data; // chunks may arrive in pieces — append
}
function end_element($parser, $name) {
global $buffer;
$text = trim($buffer);
if ($text !== '') {
echo "$name: $text\n";
}
}
$parser = xml_parser_create();
xml_set_element_handler($parser, "start_element", "end_element");
xml_set_character_data_handler($parser, "character_data");
$xml = '<books><title>PHP Basics</title><title>Advanced XML</title></books>';
xml_parse($parser, $xml, true);
xml_parser_free($parser);
// Output:
// TITLE: PHP Basics
// TITLE: Advanced XMLI nomi degli elementi arrivano in maiuscolo di default perché il parser normalizza le lettere. Per mantenere la capitalizzazione originale, disabilita il case folding con xml_parser_set_option():
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);Errori comuni
- Supporre una sola chiamata per elemento. Come mostrato sopra, i dati carattere possono essere consegnati in più frammenti; accumula sempre in un buffer.
- Chiamate con soli spazi bianchi. Indentazione e a capo tra i tag attivano l'handler con spazi bianchi. Filtrali con
trim()prima di agire. - Un terzo parametro nell'handler. L'handler Expat passa solo
$parsere$data; un parametro$lengthobbligatorio causa unArgumentCountError. - Registrare l'handler dopo il parsing. Collega tutti gli handler prima di chiamare
xml_parse(), altrimenti gli eventi saranno già passati.
Conclusione
xml_set_character_data_handler() registra un callback per il testo tra i tag XML nell'estensione xml legacy basata su Expat di PHP. Il suo handler accetta due argomenti — il parser e il frammento di dati — e può attivarsi molte volte per un singolo elemento, incluso per gli spazi bianchi; l'approccio affidabile è quindi accumulare il testo in un buffer e processarlo quando l'elemento termina tramite xml_set_element_handler(). Per i nuovi progetti si preferiscono le API moderne SimpleXML o DOMDocument; usa questa funzione quando mantieni parser esistenti o elabori in streaming documenti molto grandi.