CVII. Analyseur syntaxique XML

Introduction

A propos de XML

Le langage XML ( eXtensible Markup Language (Langage à Balises Etendu) ) 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 / .

Installation

Cette extension de PHP utilise expat , disponible à http : / /www.jclark.com / xml / . Le fichier Makefile livré avec expat ne construit pas par défaut de librairie : il faut utiliser la ligne suivante :




Les sources RPM de expat sont disponibles à http://sourceforge.net/projects/expat/ .

Notez que si vous utilisez Apache-1.3.7 ou plus récent , vous disposez déjà de la librairie expat . Configurez simplement PHP avec --with-xml ( sans aucun autre information ) et la librairie expat d 'Apache sera automatiquement utilisée .

Sous UNIX , lancez la configuration de PHP avec l ' option --with-xml , la librairie expat étant installée votre compilateur peut la trouver . Si vous compilez PHP comme module de PHP 1.3.9 ou plus récent , PHP utilisera automatiquement le module expat livré avec Apache . Il vous faudra peut être fixer les valeurs des variables d ' environnement CPPFLAGS et LDFLAGS , si vous avez fait une installation exotique .

Compilez PHP . Tada ! C ' est fait !

A propos de cette extension :

Cette extension PHP supporte la librairie expat de James Clark sous PHP . Cela vous permettra d ' analyser mais pas de valider les documents XML . Il supporte trois types de codage 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 points d ' entrée pour chaque événement XML . Les analyseurs XML disposent de quelques paramétrages .

Les gestionnaires d ' évènements XML sont :

Tableau 1 . Les gestionnaires d ' évènements XML

Fonction PHP de configuration du gestionnaire Description de l ' événement
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 .
" 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 .
Les programmeurs PHP sont habitués aux instructions exécutables ( processing instructions ou PIs ) . ?php ? est une instruction exécutable php est appelé programme cible . Ces instructions sont gérées de manière spécifiques , ( sauf le programme cible , qui est réservé à XML ) .
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 .
Ce gestionnaire est appelé pour gérer les déclaration des entités non analysés .
Ce gestionnaire est appelé pour gérer les notations .
Ce gestionnaire est appelé lorsque l ' analyseur XML trouve une référence à un fichier externe . Cela peut être 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ère 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( ) , respectivement .

Codes d'erreurs

Les constantes suivantes sont définies comme des codes d' erreurs XML : (retournée par xml_parse( ) )



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 doit ê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 ) .

Quelques exemples

Voici une liste d ' exemple de code PHP qui analyse 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 .

Exemple 1 . Afficher une structure XML

 
?php

 
$file

 
=

 
"

 
data.xml"

 
;

 
$depth

 
=

 
array()

 
;

 
function

 
startElement($parser

 
,

 
$name

 
,

 
$attrs

 
)

 
{

 
global

 
$depth

 
;

 
for

 
($i

 
=

 
0

 
;

 
$i

 
$depth[$parser]

 
;

 
$i++

 
)

 
{

 
print

 
"

 
"

 
;

 
    }

 
print

 
"$name\n"

 
;

 
$depth[$parser]++

 
;

 
}

 
function

 
endElement($parser

 
,

 
$name

 
)

 
{

 
global

 
$depth

 
;

 
$depth[$parser]--

 
;

 
}

 
$xml_parser

 
=

 
xml_parser_create()

 
;

 
xml_set_element_handler($xml_parser

 
,

 
"startElement"

 
,

 
"endElement")

 
;

 
if

 
(

 
!($fp

 
=

 
fopen($file

 
,

 
"r"))

 
)

 
{

 
die("could

 
not

 
open

 
XML

 
input")

 
;

 
}

 
while

 
($data

 
=

 
fread($fp

 
,

 
4096)

 
)

 
{

 
if

 
(!xml_parse($xml_parser

 
,

 
$data

 
,

 
feof($fp))

 
)

 
{

 
die(sprintf("XML

 
error

 
:

 
%s

 
at

 
line

 
%d"

 
,

 

xml_error_string(xml_get_error_code($xml_parser))

 
,

 
xml_get_current_line_number($xml_parser)))

 
;

 
    }

 
}

 
xml_parser_free($xml_parser)

 
;

 
?





XML Transtypage XML - HTML

Exemple 2 . XML 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

 
($htmltag

 
=

 
$map_array[$name]

 
)

 
{

 
print

 
"

 
$htmltag

 
"

 
;

 
    }

 
}

 
function

 
endElement($parser

 
,

 
$name

 
)

 
{

 
global

 
$map_array

 
;

 
if

 
($htmltag

 
=

 
$map_array[$name]

 
)

 
{

 
print

 
"

 
/

 
$htmltag

 
"

 
;

 
    }

 
}

 
function

 
characterData($parser

 
,

 
$data

 
)

 
{

 
print

 
$data

 
;

 
}

 
$xml_parser

 
=

 
xml_parser_create()

 
;

 
/

 
/

 
use

 
case-folding

 
so

 
we

 
are

 
sure

 
to

 
find

 
the

 
tag

 
in

 
$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("could

 
not

 
open

 
XML

 
input")

 
;

 
}

 
while

 
($data

 
=

 
fread($fp

 
,

 
4096)

 
)

 
{

 
if

 
(!xml_parse($xml_parser

 
,

 
$data

 
,

 
feof($fp))

 
)

 
{

 
die(sprintf("XML

 
error

 
:

 
%s

 
at

 
line

 
%d"

 
,

 

xml_error_string(xml_get_error_code($xml_parser))

 
,

 
xml_get_current_line_number($xml_parser)))

 
;

 
    }

 
}

 
xml_parser_free($xml_parser)

 
;

 
?







XML 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 ) .

Exemple 3 . Entité externe

 
?php

 
$file

 
=

 
"

 
xmltest.xml"

 
;

 
function

 
trustedFile($file

 
)

 
{

 
/

 
/

 
only

 
trust

 
local

 
files

 
owned

 
by

 
ourselves

 
if

 
(!eregi("^([a-z]+)

 
:

 
/

 
/"

 
,

 
$file

 
)

 
fileowner($file

 
)

 
==

 
getmyuid()

 
)

 
{

 
return

 
TRUE

 
;

 
    }

 
return

 
FALSE

 
;

 
}

 
function

 
startElement($parser

 
,

 
$name

 
,

 
$attribs

 
)

 
{

 
print

 
"

 
lt

 
;

 
font

 
color=\"#0000cc\

 
"

 
$name

 
/

 
font

 
"

 
;

 
if

 
(sizeof($attribs)

 
)

 
{

 
while

 
(list($k

 
,

 
$v

 
)

 
=

 
each($attribs)

 
)

 
{

 
print

 
"

 
font

 
color=\"#009900\

 
"

 
$k

 
/

 
font

 
=\

 
"

 
font

 
color=\"#990000\

 
"

 
$v

 
/

 
font

 
\""

 
;

 
        }

 
    }

 
print

 
"

 
gt

 
;"

 
;

 
}

 
function

 
endElement($parser

 
,

 
$name

 
)

 
{

 
print

 
"

 
lt

 
;

 
/

 
font

 
color=\"#0000cc\

 
"

 
$name

 
/

 
font

 
gt

 
;"

 
;

 
}

 
function

 
characterData($parser

 
,

 
$data

 
)

 
{

 
print

 
"

 
B

 
$data

 
/

 
B

 
"

 
;

 
}

 
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(

 
"Code

 
PHP

 
peu

 
sûr

 
:




 
B

 
%s

 
/

 
B

 
"

 
,

 
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("XML

 
error

 
:

 
%s

 
at

 
line

 
%d

 
while

 
parsing

 
entity

 
%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("could

 
not

 
open

 
XML

 
input")

 
;

 
}

 
print

 
"

 
pre

 
"

 
;

 
while

 
($data

 
=

 
fread($fp

 
,

 
4096)

 
)

 
{

 
if

 
(!xml_parse($xml_parser

 
,

 
$data

 
,

 
feof($fp))

 
)

 
{

 
die(sprintf("XML

 
error

 
:

 
%s

 
at

 
line

 
%d\n"

 
,

 

xml_error_string(xml_get_error_code($xml_parser))

 
,

 
xml_get_current_line_number($xml_parser)))

 
;

 
    }

 
}

 
print

 
"

 
/

 
pre

 
"

 
;

 
print

 
"parse

 
complete\n"

 
;

 
xml_parser_free($xml_parser)

 
;

 
?





Exemple 4 . xmltest.xml

 
?xml

 
version='

 
1.0'

 
?

 
!DOCTYPE

 
chapter

 
SYSTEM

 
"

 
/

 
just

 
/

 
a/test.dtd

 
"

 
[

 
!ENTITY

 
plainEntity

 
"FOO

 
entity

 
"

 
!ENTITY

 
systemEntity

 
SYSTEM

 
"xmltest2.xml

 
"

 
]

 
chapter

 
TITLE

 
Title

 
plainEntity

 
;

 
/

 
TITLE

 
para

 
informaltable

 
tgroup

 
cols="3

 
"

 
tbody

 
row

 
entry

 
a1

 
/

 
entry

 
entry

 
morerows="1

 
"

 
b1

 
/

 
entry

 
entry

 
c1

 
/

 
entry

 
/

 
row

 
row

 
entry

 
a2

 
/

 
entry

 
entry

 
c2

 
/

 
entry

 
/

 
row

 
row

 
entry

 
a3

 
/

 
entry

 
entry

 
b3

 
/

 
entry

 
entry

 
c3

 
/

 
entry

 
/

 
row

 
/

 
tbody

 
/

 
tgroup

 
/

 
informaltable

 
/

 
para

 
systemEntity

 
;

 
sect1

 
id="about

 
"

 
title

 
About

 
this

 
Document

 
/

 
title

 
para

 
!-

 
-

 
this

 
is

 
a

 
comment

 
-

 
-

 
?php

 
print

 
'Hi

 
!




 
This

 
is

 
PHP

 
version

 
'

 
.phpversion()

 
;

 
?

 
/

 
para

 
/

 
sect1

 
/

 
chapter





Ce fichier est inclus depuis xmltest.xml :

Exemple 5 . xmltest2.xml

 
?xml

 
version="

 
1.0

 
"

 
?

 
!DOCTYPE

 
foo

 
[

 
!ENTITY

 
testEnt

 
"test

 
entity

 
"

 
?

 
foo

 
element

 
attrib="value"

 
?

 
testEnt

 
;

 
?php

 
print

 
"This

 
is

 
some

 
more

 
PHP

 
code

 
being

 
executed

 
."

 
;

 
?

 
/

 
foo





Table des matières
utf8_decode -- Convertit une chaîne UTF-8 en ISO-8859.
utf8_encode -- Convertit une chaîne ISO-8859-1 en UTF-8.
xml_error_string -- Lit le message d'erreur de l'analyseur XML.
xml_get_current_byte_index -- Retourne l'index de l'octet courant d'un analyseur XML.
xml_get_current_column_number -- Retourne le nombre courant de colonne d'un analyseur XML.
xml_get_current_line_number -- Retourne le numéro de ligne courant d'un analyseur XML.
xml_get_error_code -- Retourne le nombre courant de colonne d'un analyseur XML.
xml_parse_into_struct -- Analyse une structure XML
xml_parse -- Commence l'analyse d'un fichier XML.
xml_parser_create_ns -- Create an XML parser
xml_parser_create -- Création d'un analyseur XML.
xml_parser_free -- Détruit un analyseur XML.
xml_parser_get_option -- Lit les options d'un analyseur XML.
xml_parser_set_option -- Affecte les options d'un analyseur XML.
xml_set_character_data_handler -- Affecte les gestionnaires de caractère bruts.
xml_set_default_handler -- Affecte le gestionnaire par défaut.
xml_set_element_handler -- Affecte les gestionnaires de début et de fin.
xml_set_end_namespace_decl_handler -- Set up character data handler
xml_set_external_entity_ref_handler -- Modifie le gestionnaire de référence externes.
xml_set_notation_decl_handler -- Affecte les gestionnaires de notation.
xml_set_object -- Utilise un analyseur XML à l'intérieur d'un objet.
xml_set_processing_instruction_handler -- Affecte les gestionnaires d'instructions exécutables.
xml_set_start_namespace_decl_handler -- Set up character data handler
xml_set_unparsed_entity_decl_handler -- Affecte les gestionnaires d'entité non déclaré.