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) » http://www.w3.org/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. Ce langage 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.
Cette extension PHP utilise expat compat layer par défaut. Elle peut aussi utiliser expat , qui est disponible sur » http://www.jclark.com/xml/expat.html . Le fichier Makefile livré avec expat ne construit pas par défaut de bibliothèque : il faut utiliser la ligne suivante :
libexpat.a: $(OBJS) ar -rc $@ $(OBJS) ranlib $@Un paquet RPM source de expat est disponible sur » http://sourceforge.net/projects/expat/ .
Ces fonctions sont activées par défaut, et utilisent la bibliothèque expat fournie avec la distribution. Vous pouvez désactiver le support de XML en utilisant l'option de compilation --disable-xml . Si vous compilez PHP comme module pour Apache 1.3.9 ou supérieur, PHP va automatiquement utiliser la bibliothèque expat fournie par Apache. Si vous ne souhaitez pas utiliser la bibliothèque expat intégrée, il faut que vous compiliez PHP avec l'option --with-expat-dir=DIR , où DIR est le dossier d'installation de votre bibliothèque expat.
La version Windows de PHP dispose du support automatique de cette extension. Vous n'avez pas à ajouter de bibliothèque supplémentaire pour disposer de ces fonctions.
Cette extension ne définit aucune directive de configuration.
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.
Ces constantes sont définies par cette extension, et ne sont disponibles que si cette extension a été compilée avec PHP, ou bien chargée au moment de l'exécution.
Les gestionnaires d'événements XML sont :
Tableau 336. Les gestionnaires d'événements XML supportés
Fonction PHP de configuration du gestionnaire | Description de l'événement |
---|---|
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 les 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() .
Les constantes suivantes sont définies comme des codes d'erreurs XML : (retournées par xml_parse() )
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).
Voici quelques exemples de code PHP analysant un document XML.
Ce premier exemple affiche la structure de l'élément de début dans un document avec indentation.
Exemple 2816. Afficher une structure XML
<?php
$file
=
"donnees.xml"
;
$depth
= array();
function
debutElement
(
$parser
,
$name
,
$attrs
)
{
global
$depth
;
for (
$i
=
0
;
$i
<
$depth
[
$parser
];
$i
++) {
echo
" "
;
}
echo
"$name\n"
;
$depth
[
$parser
]++;
}
function
finElement
(
$parser
,
$name
)
{
global
$depth
;
$depth
[
$parser
]--;
}
$xml_parser
=
xml_parser_create
();
xml_set_element_handler
(
$xml_parser
,
"debutElement"
,
"finElement"
);
if (!(
$fp
=
fopen
(
$file
,
"r"
))) {
die(
"Impossible d'ouvrir 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
);
?>
Exemple 2817. 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.
<?php
$file
=
"data.xml"
;
$map_array
= array(
"BOLD"
=>
"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
"</$map_array[$name]>"
;
}
}
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
);
?>
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 ).
Exemple 2818. Entité externe
<?php
$file
=
"xmltest.xml"
;
function
trustedFile
(
$file
)
{
// faites seulement confiance aux fichiers locaux dont vous êtes le propriétaire
if (!
eregi
(
"^([a-z]+)://"
,
$file
)
&&
fileowner
(
$file
) ==
getmyuid
()) {
return
true
;
}
return
false
;
}
function
startElement
(
$parser
,
$name
,
$attribs
)
{
echo
"<<font color=\"#0000cc\">$name</font>"
;
if (
count
(
$attribs
)) {
foreach (
$attribs
as
$k
=>
$v
) {
echo
" <font color=\"#009900\">$k</font>=\"<font
color=\"#990000\">$v</font>\""
;
}
}
echo
">"
;
}
function
endElement
(
$parser
,
$name
)
{
echo
"</<font color=\"#0000cc\">$name</font>>"
;
}
function
characterData
(
$parser
,
$data
)
{
echo
"<strong>$data</strong>"
;
}
function
PIHandler
(
$parser
,
$target
,
$data
)
{
switch (
strtolower
(
$target
)) {
case
"php"
:
global
$parser_file
;
// si le document analysé est de confiance, nous déclarons qu'il est sûr
// d'exécuter le code PHP qu'il contient. Si ce n'est pas le cas, le code est affiché
// à la place.
if (
trustedFile
(
$parser_file
[
$parser
])) {
eval(
$data
);
} else {
printf
(
"Untrusted PHP code: <em>%s</em>"
,
htmlspecialchars
(
$data
));
}
break;
}
}
function
defaultHandler
(
$parser
,
$data
)
{
if (
substr
(
$data
,
0
,
1
) ==
"&"
&&
substr
(
$data
, -
1
,
1
) ==
";"
) {
printf
(
'<font color="#aa00aa">%s</font>'
,
htmlspecialchars
(
$data
));
} else {
printf
(
'<font size="-1">%s</font>'
,
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
"<pre>"
;
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
"</pre>"
;
echo
"parse complete\n"
;
xml_parser_free
(
$xml_parser
);
?>
Exemple 2819. xmltest.xml
Ce fichier est inclus depuis xmltest.xml :
Exemple 2820. xmltest2.xml