Analyseur syntaxique XML XML
&reftitle.intro; Le langage XML (eXtensible Markup Language (Langage à Balises Extensible)) est un format structuré de données pour les échanges sur le web. C'est un standard défini par le consortium World Wide Web (W3C). Plus d'informations à propos du XML et des technologies afférentes sont accessibles (en anglais) &url.xml;. Cette extension &php; implémente la bibliothèque expat de James Clark sous &php;. Cela vous permettra d'analyser mais pas de valider les documents XML. Il supporte trois types de jeux de caractères différents, disponibles aussi sous &php; : US-ASCII, ISO-8859-1 et UTF-8. UTF-16 n'est pas supporté. Cette extension vous permet de créer des analyseurs XML puis de définir des gestionnaires pour chaque événement XML. Les analyseurs XML disposent de quelques paramétres que vous pouvez régler.
&reftitle.required; Cette extension &php; utilise expat compat layer par défaut. Elle peut aussi utiliser expat, qui est disponible sur &url.expat;. Le fichier Makefile livré avec expat ne construit pas par défaut de bibliothèque : il faut utiliser la ligne suivante : Un paquet RPM source de expat est disponible sur &url.expat.rpm;.
&reference.xml.configure;
&reftitle.runtime; &no.config;
&reftitle.resources;
<literal>xml</literal> La ressource xml est retournée par xml_parser_create et xml_parser_create_ns, et représente un analyseur XML à utiliser avec les autres fonctions de cette extension.
&reference.xml.constants;
gestionnaires d'événements Les gestionnaires d'événements XML sont: Les gestionnaires d'événements XML supportés Fonction &php; de configuration du gestionnaire Description de l'événement xml_set_element_handler Un événement est généré à chaque fois que l'analyseur XML rencontre une balise de début ou de fin. Deux gestionnaires sont disponibles : un pour le début, et un pour la fin. xml_set_character_data_handler "Character data" correspond grosso modo à tout ce qui n'est pas une balise XML, y compris les espaces entre les balises. Notez bien que l'analyseur XML n'ajoute ou n'efface aucun espace, et que c'est à l'application (c'est-à-dire vous) de décider de la signification de ces espaces. xml_set_processing_instruction_handler Les programmeurs &php; sont habitués aux instructions exécutables (processing instructions ou PIs). <?php ?> est une instruction exécutable où php est appelé programme cible. Ces instructions sont gérées de manière spécifique, (sauf le programme cible "XML" qui est réservé). xml_set_default_handler Tout ce qui n'a pas trouvé de gestionnaire est transmis au gestionnaire par défaut. Vous retrouverez par exemple, les déclarations de type de document dans ce gestionnaire. xml_set_unparsed_entity_decl_handler Ce gestionnaire est appelé pour gérer les déclaration des entités non analysées (NDATA). xml_set_notation_decl_handler Ce gestionnaire est appelé pour déclarer les notations. xml_set_external_entity_ref_handler Ce gestionnaire est appelé lorsque l'analyseur XML trouve une référence à une entité généale externe. Cela peut être une référence à un fichier ou à une URL. Reportez-vous à entité externe pour un exemple.
Problèmes de casse Les fonctions de gestion des balises peuvent rencontrer des balises en minuscule, majuscule ou encore dans un mélange des deux. En XML, la procédure standard est d' "identifier les séquences de caractères qui ne sont pas reconnues comme majuscule, et de les remplacer par leur équivalent majuscule". En d'autres termes, XML met toutes lettres en majuscules. Par défaut, tous les noms des éléments qui sont transmis aux fonctions de gestion sont mises en majuscule. Ce comportement est contrôlé par l'analyseur XML, et peut être lu et modifié avec les fonctions respectives xml_parser_get_option et xml_parser_set_option.
Codes d'erreurs Les constantes suivantes sont définies comme des codes d'erreurs XML : (retournées par xml_parse) XML_ERROR_NONE XML_ERROR_NO_MEMORY XML_ERROR_SYNTAX XML_ERROR_NO_ELEMENTS XML_ERROR_INVALID_TOKEN XML_ERROR_UNCLOSED_TOKEN XML_ERROR_PARTIAL_CHAR XML_ERROR_TAG_MISMATCH XML_ERROR_DUPLICATE_ATTRIBUTE XML_ERROR_JUNK_AFTER_DOC_ELEMENT XML_ERROR_PARAM_ENTITY_REF XML_ERROR_UNDEFINED_ENTITY XML_ERROR_RECURSIVE_ENTITY_REF XML_ERROR_ASYNC_ENTITY XML_ERROR_BAD_CHAR_REF XML_ERROR_BINARY_ENTITY_REF XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF XML_ERROR_MISPLACED_XML_PI XML_ERROR_UNKNOWN_ENCODING XML_ERROR_INCORRECT_ENCODING XML_ERROR_UNCLOSED_CDATA_SECTION XML_ERROR_EXTERNAL_ENTITY_HANDLING
Codage des caractères L'extension XML de &php; supporte les caractères Unicode grâce à différents codages. Il y a deux types de codages de caractères : le codage à la source et le codage à la cible. &php; utilise le UTF-8 comme représentation interne. L'encodage à la source est effectué lors de l'analyse du fichier par XML. Lors de la création d'un analyseur XML), un type de codage à la source peut être spécifié (et il ne pourra plus être modifié jusqu'à la destruction de l'analyseur). Les codages supportés sont : ISO-8859-1, US-ASCII et UTF-8. Les deux derniers sont des codages à un seul octet, c'est-à-dire que les caractères sont représentés sur un seul octet. UTF-8 peut représenter des caractères composés par un nombre variable de bits (jusqu'à 21), allant de 1 à quatre octets. Le codage par défaut utilisé par &php; ISO-8859-1. Le codage à la cible est effectué lorsque &php; transfert les données aux gestionnaires XML. Lorsqu'un analyseur est créé, le codage à la cible est spécifié de la même façon que le codage à la source, mais il peut être modifié à tout moment. Le codage à la cible affectera les balises, tout comme les données brutes, et les noms des instructions exécutables. Si l'analyseur XML rencontre un caractère qu'il ne connaît pas (hors limite, par exemple), il retournera une erreur. Si &php; rencontre un caractère dans le document XML analysé, qu'il ne peut pas représenter dans le codage à la cible choisi, le caractère sera remplacé par un point d'interrogation (cette attitude est susceptible de changer ultérieurement).
&reftitle.examples; Voici quelques exemples de code &php; analysant un document XML.
Exemple de structure XML Ce premier exemple affiche la structure de l'élément de début dans un document avec indentation. Afficher une structure XML ]]>
Transtypage XML -> HTML Transtypage XML -> HTML Cet exemple remplace les balises XML d'un document par des balises HTML. Les éléments inconnus seront ignorés. Bien entendu, cet exemple sera appliqué à un type précis de fichiers XML. "B", "EMPHASIS" => "I", "LITERAL" => "TT" ); function startElement($parser, $name, $attrs) { global $map_array; if (isset($map_array[$name])) { echo "<$map_array[$name]>"; } } function endElement($parser, $name) { global $map_array; if (isset($map_array[$name])) { echo ""; } } function characterData($parser, $data) { echo $data; } $xml_parser = xml_parser_create(); // Utilisons la gestion de casse, de manière à être sûrs de trouver la balise dans $map_array xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, true); xml_set_element_handler($xml_parser, "startElement", "endElement"); xml_set_character_data_handler($xml_parser, "characterData"); if (!($fp = fopen($file, "r"))) { die("Impossible de trouver le fichier XML"); } while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("erreur XML : %s à la ligne %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser); ?> ]]>
Entité externe Cet exemple exploite les références externes de XML : il est possible d'utiliser un gestionnaire d'entité externe pour inclure et analyser les documents, tous comme les instructions exécutables peuvent servir à inclure et analyser d'autres documents, et aussi fournir une indication de confiance (voir plus bas). Le document XML qui est utilisé dans cet exemple est fourni plus loin dans l'exemple (xmltest.xml et xmltest2.xml). Entité externe $name"; if (count($attribs)) { foreach ($attribs as $k => $v) { echo " $k=\"$v\""; } } echo ">"; } function endElement($parser, $name) { echo "</$name>"; } function characterData($parser, $data) { echo "$data"; } function PIHandler($parser, $target, $data) { switch (strtolower($target)) { case "php": global $parser_file; // If the parsed document is "trusted", we say it is safe // to execute PHP code inside it. If not, display the code // instead. if (trustedFile($parser_file[$parser])) { eval($data); } else { printf("Untrusted PHP code: %s", htmlspecialchars($data)); } break; } } function defaultHandler($parser, $data) { if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") { printf('%s', htmlspecialchars($data)); } else { printf('%s', htmlspecialchars($data)); } } function externalEntityRefHandler($parser, $openEntityNames, $base, $systemId, $publicId) { if ($systemId) { if (!list($parser, $fp) = new_xml_parser($systemId)) { printf("Could not open entity %s at %s\n", $openEntityNames, $systemId); return false; } while ($data = fread($fp, 4096)) { if (!xml_parse($parser, $data, feof($fp))) { printf("erreur XML : %s à la ligne %d lors de l'analyse de l'entité %s\n", xml_error_string(xml_get_error_code($parser)), xml_get_current_line_number($parser), $openEntityNames); xml_parser_free($parser); return false; } } xml_parser_free($parser); return true; } return false; } function new_xml_parser($file) { global $parser_file; $xml_parser = xml_parser_create(); xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 1); xml_set_element_handler($xml_parser, "startElement", "endElement"); xml_set_character_data_handler($xml_parser, "characterData"); xml_set_processing_instruction_handler($xml_parser, "PIHandler"); xml_set_default_handler($xml_parser, "defaultHandler"); xml_set_external_entity_ref_handler($xml_parser, "externalEntityRefHandler"); if (!($fp = @fopen($file, "r"))) { return false; } if (!is_array($parser_file)) { settype($parser_file, "array"); } $parser_file[$xml_parser] = $file; return array($xml_parser, $fp); } if (!(list($xml_parser, $fp) = new_xml_parser($file))) { die("Impossible d'ouvrir le fichier XML"); } echo "
";
while ($data = fread($fp, 4096)) {
    if (!xml_parse($xml_parser, $data, feof($fp))) {
        die(sprintf("Erreur XML : %s à la ligne %d\n",
                    xml_error_string(xml_get_error_code($xml_parser)),
                    xml_get_current_line_number($xml_parser)));
    }
}
echo "
"; echo "parse complete\n"; xml_parser_free($xml_parser); ?> ]]>
xmltest.xml ]> Title &plainEntity; a1b1c1 a2c2 a3b3c3 &systemEntity;
About this Document
]]>
Ce fichier est inclus depuis xmltest.xml: xmltest2.xml ]> &testEnt; ]]>
&reference.xml.functions;