xml_set_character_data_handler()
La fonction xml_set_character_data_handler() définit un callback utilisateur comme gestionnaire de données de caractères dans un analyseur XML PHP.
La fonction xml_set_character_data_handler() enregistre un callback défini par l'utilisateur que l'analyseur XML appelle chaque fois qu'il rencontre des données de caractères — le contenu textuel situé entre les balises XML. Elle appartient à l'extension xml héritée, qui encapsule l'analyseur Expat orienté événements, et fait donc partie de l'API d'analyse en flux ("style SAX") de PHP plutôt que des approches arborescentes DOMDocument ou SimpleXML.
On utilise cette fonction lorsqu'on souhaite capturer ou transformer le texte à l'intérieur des éléments au fur et à mesure que le document est parcouru — par exemple, pour collecter le titre de chaque <item> dans un flux RSS, ou pour effectuer une transformation sur du texte extrait sans jamais construire l'intégralité du document en mémoire. Elle est presque toujours utilisée conjointement avec xml_set_element_handler(), qui indique à quel élément appartient le texte.
Attention : L'extension
xmlest héritée. Pour tout nouveau code, préférezSimpleXMLouDOMDocument. Utilisez ce gestionnaire lorsque vous maintenez des analyseurs Expat existants ou avez réellement besoin d'un traitement en flux pour des documents très volumineux.
Syntaxe
xml_set_character_data_handler(XMLParser $parser, callable $handler): bool$parser— l'analyseur créé parxml_parser_create().$handler— le callback à invoquer pour les données de caractères. Passez un nom de fonction sous forme de chaîne, une closure, ou un tableau pour un callback de méthode. Passer une chaîne vide""supprime un gestionnaire précédemment enregistré.
La fonction retourne true en cas de succès.
La signature du gestionnaire
Votre gestionnaire reçoit deux arguments — l'analyseur et le fragment de texte :
function handler(XMLParser $parser, string $data): voidD'anciennes documentations indiquent parfois un troisième paramètre $length, mais l'extension xml basée sur Expat n'en passe pas. Sur PHP 8+, déclarer un troisième paramètre obligatoire génère une ArgumentCountError, donc gardez votre gestionnaire à deux paramètres (ou rendez les paramètres supplémentaires optionnels).
Exemples d'utilisation
Exemple 1 : Un gestionnaire de données de caractères minimal
Créez un analyseur, attachez un gestionnaire, puis alimentez-le avec une chaîne XML. Le gestionnaire affiche simplement le texte reçu après suppression des espaces :
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() construit l'analyseur, xml_set_character_data_handler() connecte le callback, xml_parse() traite les données en flux (le true final indique qu'il s'agit du dernier fragment), et xml_parser_free() libère l'analyseur.
Le piège du découpage en fragments
L'analyseur peut appeler votre gestionnaire plusieurs fois pour un seul élément, et il se déclenche aussi pour les espaces entre les éléments. Il ne vous fournit pas une chaîne propre par élément. Voici ce qui se passe avec deux éléments et quelques indentations :
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]L'espace de deux caractères entre le </item> et le <item> suivant déclenche son propre appel. Un texte long peut également arriver découpé en plusieurs appels. Pour cette raison, vous devez mettre en tampon les données et n'agir qu'une fois que vous savez que l'élément est terminé.
Exemple 2 : Mise en tampon du texte avec un gestionnaire d'éléments
Le modèle fiable consiste à : réinitialiser un tampon au démarrage d'un élément, y ajouter chaque fragment de données de caractères, et lire le tampon à la fin de l'élément. C'est pourquoi xml_set_element_handler() est presque toujours associé à cette fonction.
$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 XMLLes noms d'éléments arrivent en majuscules par défaut car l'analyseur normalise la casse. Pour conserver la casse d'origine, désactivez la normalisation avec xml_parser_set_option() :
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);Pièges courants
- Supposer un seul appel par élément. Comme illustré ci-dessus, les données de caractères peuvent être livrées en plusieurs fragments ; accumulez-les toujours dans un tampon.
- Appels avec uniquement des espaces. Les indentations et les sauts de ligne entre les balises déclenchent le gestionnaire avec des espaces. Filtrez-les avec
trim()avant d'agir. - Un troisième paramètre de gestionnaire. Le gestionnaire Expat ne passe que
$parseret$data; un paramètre$lengthobligatoire provoque uneArgumentCountError. - Enregistrement du gestionnaire après l'analyse. Attachez tous les gestionnaires avant d'appeler
xml_parse(), sinon les événements seront déjà passés.
Conclusion
xml_set_character_data_handler() enregistre un callback pour le texte entre les balises XML dans l'extension xml héritée de PHP, basée sur Expat. Son gestionnaire prend deux arguments — l'analyseur et le fragment de données — et peut se déclencher plusieurs fois par élément, y compris pour les espaces. L'approche fiable consiste donc à mettre le texte en tampon et à le traiter à la fin de l'élément via xml_set_element_handler(). Pour les nouveaux projets, préférez les API modernes SimpleXML ou DOMDocument ; utilisez cette fonction pour maintenir des analyseurs existants ou traiter en flux des documents très volumineux.