PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links 
search for in the  
previouswddx_serialize_varsutf8_decodenext
Last updated: Tue, 09 Jul 2002
view the printer friendly version or the printer friendly version with notes or change language to English | Brazilian Portuguese | Chinese | Czech | Dutch | Finnish | German | Hungarian | Italian | Japanese | Korean | Polish | Romanian | Russian | Spanish | Swedish | Turkish

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

Installation

Cette extension de PHP utilise expat, disponible � . Le fichier Makefile livr� avec expat ne construit pas par d�faut de librairie : il faut utiliser la ligne suivante :

libexpat.a: $(OBJS)
	ar -rc $@ $(OBJS)
	ranlib $@
Les sources RPM de expat sont disponibles � .

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 l� o� 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 gestionnaireDescription 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�cifiques, (sauf le programme cible, qui est r�serv� � XML).
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�s.
xml_set_notation_decl_handler() Ce gestionnaire est appel� pour g�rer les notations.
xml_set_external_entity_ref_handler() 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())

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 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�.
User Contributed Notes
Analyseur syntaxique XML
add a note about notes
[email protected]
12-Jan-1999 10:05

In the installation section, be sure that the indents in the code you add to the Makefile are tabs, not spaces. make will choke otherwise.

Additionally, you need to copy two header files into your /usr/local/include or equivalent:

$EXPAT_SRC/xmltok/xmltok.h
$EXPAT_SRC/xmlparse/xmlparse.h

[email protected]
07-Jul-1999 04:21

When using the XML parser, make sure you're not using the magic quotes option (e.g. use set_magic_quotes_runtime(0) if it's not the compiled default), otherwise you'll get 'not well-formed' errors when dealing with tags with attributes set in them.
[email protected]
16-Aug-1999 10:13

"The expat library should be installed somewhere your compiler can find it." is a little vague. Here is a quick install guide:
1) download expat.zip
2) mv expat.zip /dir/of/expat
3) unzip expat.zip
4) cd expat
5) Add these lines to Makefile:
libexpat.a: $(OBJS)
(tab) ar -rc $@ $(OBJS)
(tab) ran lib $@
6) make
7) cp libexpat.a /usr/local/lib
8) mkdir /usr/local/include/xml
9) cd xmlparse
10) cp *.h /usr/local/include/xml
11) cd ../xmltok
12) cp *.h /usr/local/include/xml
13) cd ../xmlwf
14) cp *.h /usr/local/include/xml
Then reconfigure and make php, then apache.

[email protected]
30-Oct-1999 04:40

I'm not sure if anyone else has had or will have this problem, but here is my solution. For some reason, the PHP compile did recognise the Apache 1.3.9 support for XML. I circumvented this by creating a link from /usr/local/include/xml to the Apache src/lib/expat-lite directory. I then however ran into problems with the Apache compile. It was looking for libexpat.a which hadn't been created. I tried to create this by downloading the source and modifying the Makefile, but it wasnt created for some reason. Finally, I resorted to creating the libexpat.a file by hand:

ar -rc xmltok/xmltok.o
ar -q xmltok/xmlrole.o
ar -q xmlwf/xmlwf.o
ar -q xmlwf/xmlfile.o
ar -q xmlwf/codepage.o
ar -q xmlparse/xmlparse.o
ar -q xmlparse/hashtable.o

I hope this helps someone, because it would have saved me a lot of time. Also note that I was getting an ANSI non-compliance error in the Apache build process. After added the -v swicth to line 2141 as pointed out in the FAQ, I found out it was the missing libexpat.a package.

[email protected]
15-Dec-1999 03:25

Remember, that when adding the lines for making:
libexpat.a: $(OBJS)
<tab> ar -rc $@ $(OBJS)
<tab> ranlib $@
,you'll have to do a "make libexpat.a" after running "make".

[email protected]
17-Feb-2000 05:31

The link is no active. For the expat.zip do a FTP file search.
[email protected]
28-Sep-2000 01:39

I've discovered some unusual behaviour in this API when ampersand entities are parsed in cdata; for some reason the parser breaks up the section around the entities, and calls the handler repeated times for each of the sections. If you don't allow for this oddity and you are trying to put the cdata into a variable, only the last part will be stored.

You can get around this with a line like:

$foo .= $cdata;

If the handler is called several times from the same tag, it will append them, rather than rewriting the variable each time. If the entire cdata section is returned, it doesn't matter.

May happen for other entities, but I haven't investigated.

Took me a while to figure out what was happening; hope this saves someone else the trouble.

[email protected]
06-Oct-2000 07:37

There's a really good article on XML parsing with PHP at
[email protected]
31-Mar-2001 12:35

Excellent IMHO XPath library for XML manipulation. Doesn't requires the XML libraries to be installed.
Take a look:

[email protected]
24-Jan-2002 02:43

I had to TRIM the data when I passed one large String containig a wellformed XML-File to xml_parse. The String was read by CURL, which aparently put a BLANK at the end of the String. This BLANK produced a "XML not wellformed"-Error in xml_parse!
jason@NOSPAM_projectexpanse_NOSPAM.com
26-Feb-2002 10:11

For newbies wanting a good tutorial on how to actually get started and where to go from this listing of functions, then visit:


It shows an excellent example of how to read the XML data into a class file so you can actually process it, not just display it all pretty-like, like many tutorials on PHP/XML seem to be doing.

[email protected]
22-Mar-2002 07:16

In reference to the note made by [email protected] about parsing entities:

I could be wrong, but since it is possible to define your own entities within an XML DTD, the cdata handler function parses these individually to allow for your own implementation of those entities within your cdata handler.

[email protected]
15-Apr-2002 08:23

I put up a good, simple, real world example of how to parse XML documents. While the sample grabs stock quotes off of the web, you can tweak it to do whatever you need.


[email protected]
14-Aug-2002 07:59

[Editor's note: see also xml_parse_into_struct().]

Very simple routine to convert an XML file into a PHP structure. $obj->xml contains the resulting PHP structure. I would be interested if someone could suggest a cleaner method than the evals I am using.

<?
$filename = 'sample.xml';
$obj->tree = '$obj->xml';
$obj->xml = '';

function startElement($parser, $name, $attrs) {
global $obj;

// If var already defined, make array
eval('$test=isset('.$obj->tree.'->'.$name.');');
if ($test) {
eval('$tmp='.$obj->tree.'->'.$name.';');
eval('$arr=is_array('.$obj->tree.'->'.$name.');');
if (!$arr) {
eval('unset('.$obj->tree.'->'.$name.');');
eval($obj->tree.'->'.$name.'[0]=$tmp;');
$cnt = 1;
}
else {
eval('$cnt=count('.$obj->tree.'->'.$name.');');
}

$obj->tree .= '->'.$name."[$cnt]";
}
else {
$obj->tree .= '->'.$name;
}
if (count($attrs)) {
eval($obj->tree.'->attr=$attrs;');
}
}

function endElement($parser, $name) {
global $obj;
// Strip off last ->
for($a=strlen($obj->tree);$a>0;$a--) {
if (substr($obj->tree, $a, 2) == '->') {
$obj->tree = substr($obj->tree, 0, $a);
break;
}
}
}

function characterData($parser, $data) {
global $obj;

eval($obj->tree.'->data=\''.$data.'\';');
}

$xml_parser = xml_parser_create();
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
if (!($fp = fopen($filename, "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);
print_r($obj->xml);
return 0;

?>

add a note about notes
previouswddx_serialize_varsutf8_decodenext
Last updated: Tue, 09 Jul 2002
show source | credits | stats | mirror sites
Copyright © 2001, 2002 The PHP Group
All rights reserved.
This mirror generously provided by:
Last updated: Sat Aug 31 06:19:44 2002 CEST