FAQ PHP
FAQ PHPConsultez toutes les FAQ
Nombre d'auteurs : 68, nombre de questions : 580, dernière mise à jour : 18 septembre 2021
- Qu'est-ce que DOM ?
- Comment installer DOM pour PHP5 ?
- Comment obtenir l'élément racine du document ?
- Comment ajouter un élément à un objet DOM ?
- Comment affecter un attribut à un élément DOM ?
- Comment enregistrer un document DOM ?
- Comment formater un document XML pour affichage ?
- Comment supprimer les noeuds correspondant à une expression XPath en PHP5 ?
- Comment lire un document XML distant en précisant des entêtes HTTP particulières ?
- Comment écrire un document XML sur un serveur FTP ?
DOM est une extension pour PHP 5 permettant, tout comme DOM XML en PHP4, de lire et de générer des documents au format XML.
Toute une série de classes est mise à disposition afin de permettre ue gestion très fine des documents.
Lien : Manuel DOM
Lien : Cours et tutoriels XML en PHP
Cette extension n'est pas en PECL mais dans la distribution core, ce qui la rend disponible simplement par l'activation dans php.ini suivie d'un redémarrage d'Apache.
Lien : Comment installer une extension pour PHP ?
Lien : https://www.php.net/manual/fr/book.dom.php
Tout objet DomDocument possède une variable d'instance documentElement, en lecture seule. Il est donc strictement inutile de passer par exemple par la méthode getElementsByTagName ou autres :
$dom
=
DomDocument::
load('
monFichier.xml
'
);
$racine
=
$dom
->
documentElement;
printf("
L'élément racine se nomme : %s
"
,
$racine
->
nodeName);
Au moyen des méthodes createElement() et appendChild() :
$document
=
new DOMDocument();
$XMLRoot
=
$document
->
createElement('
Utilisateurs
'
);
$document
->
appendChild($XMLRoot
);
On peut ensuite ajouter d'autres éléments à l'objet $XMLRoot :
$users
=
array
(
array('
name
'
=>
'
Yogui
'
,
'
password
'
=>
'
1234
'
),
array('
name
'
=>
'
BrYs
'
,
'
password
'
=>
'
4321
'
)
);
$document
=
new DOMDocument();
$XMLRoot
=
$document
->
createElement('
Utilisateurs
'
);
$document
->
appendChild($XMLRoot
);
foreach($users
as $user
)
{
$XMLUser
=
$document
->
createElement('
user
'
);
$XMLRoot
->
appendChild($XMLUser
);
$XMLName
=
$document
->
createElement('
name
'
,
$user
[
'
name
'
]
);
$XMLUser
->
appendChild($XMLName
);
$XMLPassword
=
$document
->
createElement('
password
'
,
$user
[
'
password
'
]
);
$XMLUser
->
appendChild($XMLPassword
);
}
Au moyen de la méthode setAttribute() :
$document
=
new DOMDocument();
$XMLName
=
$document
->
createElement('
password
'
,
$user
[
'
password
'
]
);
$XMLName
->
setAttribute('
crypted
'
,
0
);
$XMLUser
->
appendChild($XMLName
);
Notez que cette méthode peut être appelée à n'importe quel moment du script, tant que l'objet est accessible. Ici par exemple, vous pouvez intervertir les appels à appendChild() et setAttribute().
Il faut terminer le script par un appel à l'une des méthodes suivantes :
$document
=
new DOMDocument();
$XMLRoot
=
$document
->
createElement('
Utilisateurs
'
);
$document
->
appendChild($XMLRoot
);
echo htmlentities($document
->
saveXML(),
ENT_QUOTES,
'
ISO-8859-1
'
);
$document
=
new DOMDocument();
$XMLRoot
=
$document
->
createElement('
Utilisateurs
'
);
$document
->
appendChild($XMLRoot
);
$document
->
save('
users.xml
'
);
- preserveWhiteSpace doit être mise à la valeur fausse avant le chargement du document XML afin que tous les noeuds textuels composés de blanc, fruits du formatage, soient ignorés ;
- formatOuput doit être mis à la valeur vraie avant l'écriture du document (méthodes save*) afin qu'il soit indenté.
// 1. Créer un objet DomDocument "vierge"
$dom
=
new DomDocument;
// 2. Indiquer que les noeuds texte constitués de blancs soient ignorés
$dom
->
preserveWhiteSpace =
FALSE;
// 3. Indiquer qu'il devra être formaté lors de son écriture (peut être remis à plus tard)
$dom
->
formatOutput =
TRUE;
// 4. Charger votre document
$dom
->
load('
monFichier.xml
'
);
// Pour un fichier (même distant)
$dom
->
loadXML($maChaineXML
);
// Pour une chaîne de caractères
// Manipuler, optionnellement, l'arbre ...
// 5. Sauvegarder le document
$dom
->
save('
monFichier.xml
'
);
// Pour une sortie dans un fichier
$output
=
$dom
->
saveXML();
// Pour obtenir le résultat sous la forme d'une chaîne de caractères
<?php
define('FICHIER_XML'
,
'un_fichier_xml.xml'
);
define('DOCUMENT_FORMATE'
,
TRUE
);
$document
=
new
DOMDocument;
$document
->
preserveWhiteSpace =
!
DOCUMENT_FORMATE;
$document
->
formatOutput =
DOCUMENT_FORMATE;
$document
->
load(FICHIER_XML);
$xpath
=
new
DOMXPath($document
);
$noeuds
=
$xpath
->
query('/*/*/*'
);
// Tous les noeuds ayant deux ancêtres
foreach
($noeuds
as
$noeud
) {
if
($noeud
->
nodeType ==
XML_DOCUMENT_NODE) {
$document
->
removeChild($document
->
documentElement);
}
else
{
$noeud
->
parentNode->
removeChild($noeud
);
}
}
// Ecraser le fichier existant avec les modifications apportées
//$document->save(FICHIER_XML);
// Affichage pour test :
header('Content-type: text/plain'
);
echo $document
->
saveXML();
?>
La constante booléenne DOCUMENT_FORMATE, définie communément aux deux scripts, permet de tenir compte des fichiers XML indentés pour qu'il soit plus facilement lisible et éditable par l'Homme. Pour que cela soit possible, il faut, à l'ouverture du fichier XML en lecture, indiquer que les espaces utilisés pour cette indentation doivent être ignorés (il faut affecter une valeur fausse à l'attribut preserveWhiteSpace de l'objet correspondant au document). On doit ensuite lui faire savoir que le document doit être formaté lors de sa sortie, ce que nous faisons via l'attribut formatOutput du document que l'on fixe à la valeur vraie.
On peut avoir besoin de modifier les entêtes que PHP fait parvenir par défaut lors d'une communication avec un serveur HTTP. Il vous est notamment possible de modifier le type de requête pour POST (GET étant la méthode par défaut) et d'y adjoindre différentes données, de fixer un délai d'expiration pour la requête, de limiter le nombre de redirections dont vous pourriez faire l'objet, de vous faire passer pour un navigateur standard, etc. Pour ce faire, il faut créer un nouveau contexte (fonction stream_context_create) pour modifier le comportement par défaut, puis le rendre opérationnel grâce à la fonction libxml_set_streams_context qui le fera valoir à la librairie de plus bas niveau libxml sur laquelle les extensions DOM et SimpleXML sont toutes deux basées.
$post
=
array(
'
selection
'
=>
array(1
,
10
,
3
),
'
titre
'
=>
'
Test
'
,
'
submit
'
=>
'
valider
'
);
$contexte
=
stream_context_create(
array(
'
http
'
=>
array(
'
method
'
=>
'
POST
'
,
'
header
'
=>
"
User-Agent: PHP5 & DOM/SimpleXML
\r\n
Content-type: application/x-www-form-urlencoded
"
,
'
content
'
=>
http_build_query($post
),
'
max_redirects
'
=>
10
,
/* Suivre, au maximum, 10 redirections (requiert une version >= à 5.1.0) */
'
timeout
'
=>
10
/* Ne sera honoré que sur les versions >= à 5.2.1 */
)
)
);
libxml_set_streams_context($contexte
);
// DOM
$dom
=
DomDocument::
load('
https://login:motDePasse@www.monsite.fr/prive/flux.php
'
);
- allow_url_fopen est à la valeur On ;
- Les flux http(s) sont gérés par PHP.
Consultez la sortie de phpinfo() pour obtenir ces informations.
Par défaut, PHP, par l'intermédiaire de son gestionnaire de flux FTP, refusera d'écraser un fichier distant existant. Cette situation vous sera vraisemblablement indiquée par l'erreur suivante :
Remote file already exists and overwrite context option not specified.
La solution consite à modifier les options par défaut en créant un contexte où l'on modifie la valeur du paramètre overwrite puis à le fournir à la fonction libxml_set_streams_context, servant à configurer le flux pour la prochaine opération de la librairie libxml sous-jacente, avant de faire appel aux fonctions d'écriture :
$contexte
=
stream_context_create(
array(
'
ftp
'
=>
array('
overwrite
'
=>
TRUE)
)
);
libxml_set_streams_context($contexte
);
// DOM
$dom
->
save('
ftp://login:motDePasse@ftp.monsite.fr/offline/temp.xml
'
);
- allow_url_fopen doit être à On ;
- Les flux ftp(s) doivent être gérés par PHP.
Consultez la sortie de phpinfo() pour obtenir ces informations.