Page 1 sur 1

La DOM + php 5 : parcer un fichier XML

Posté : 25 mai 2007, 21:12
par zuX
Bonjour,

Voici mon flux XML :

Code : Tout sélectionner

<?xml version="1.0" encoding="ISO-8859-1"?> <weather ver="2.0"> <dayf> <lsup>5/25/07 3:39 PM Local Time</lsup> <day d="0" t="Friday" dt="May 25"> <hi>N/A</hi> <low>15</low> </day> <day d="1" t="Saturday" dt="May 26"> <hi>21</hi> <low>11</low> </day> </dayf> </weather>
Je n'arrive pas à parcer ce flux XML avec DOM, avec simpleXML j'y arrive :/
Le principe est simple :
Lister toutes les balises <day> (qui correspond à 1 jour) et lister à l'intérieur d'elle meme <hi> par exemple.

Donc je liste les jours, et dans cette boucle j'affiche la valeur du noeud <hi>.

Je n'arrive pas à écrire cela :(

A vrai dire, je ne comprends pas bien getElementsByTagName() et l'histoire du '->item(0)'
Mon code me propose aucune erreur, c'est ma méthodologie qui doit etre mauvaise.


Merci d'avance de votre aide =)


PS : ce qui me gène le plus au niveau de la compréhension, c'est comment afficher la valeur d'un noeud préci et comment sortir de ce noeud.

Re: La DOM + php 5 : parcer un fichier XML

Posté : 25 mai 2007, 21:36
par Hubert Roksor
avec simpleXML j'y arrive
Ben alors continue avec SimpleXML ! :lol: Plus sérieusement, pour 95% des besoins, SimpleXML est le plus adapté, le plus rapide et le plus... simple.

Et je te propose encore mieux, ça s'appelle XPath et c'est un language développé pour retrouver des données dans un arbre XML. Dans XPath, pour trouver tous les nœuds "day" n'importe où dans le document on utilise //day et pour trouver tous les nœuds "hi" comme descendants direct de ces nœud on utilise //day/hi.

En imaginant que les données XML que tu as posté plus haut soient dans le fichier "temp.xml" alors tu peux faire quelque chose comme
$xml = simplexml_load_file('temp.xml');

foreach ($xml->xpath('//day/hi') as $hi)
{
	echo "Temp hi: ", $hi, "\n";
}

foreach ($xml->xpath('//day') as $day)
{
	echo $day['t'], ', ', $day['dt'], ': ', $day->hi, "\n";
}
Dans la première boucle j'utilie XPath pour récupérer la valeur des nœuds "hi" dont on parlait. Mais par cette expression je n'accède qu'à la valeur de "hi". Si tu dois utiliser les données d'autres nœuds en même temps il vaut mieux y accéder différement. En l'occurence, dans le second exemple je récupère par XPath tous les nœuds "day". XPath nous renvoit des éléments SimpleXML donc je peux utiliser sur $day tout ce que je peux utiliser sur $xml, je pourrais utiliser d'autres XPath ou utiliser des fonctions ou propriétés de SimpleXML dessus. Sous SimpleXML on peut accéder aux attributs comme s'ils étaient les valeurs d'un tableau (ou par la fonction attributes() mais autant aller au plus simple), et on peut accéder aux descendants comme s'ils étaient des variables de classe, ce que tu peux voir dans la seconde boucle de l'exemple.

Posté : 25 mai 2007, 22:27
par zuX
Un grand merci pour ton aide :)
Je ne connaissais pas xpath, c'est vrai que c'est très pratique !

A vrai dire, je trouve la DOM tres compliquée pour LIRE simplement un fichier XML :( Je veux dire que rien de plus simple que de travailler sur un tableau avec simpleXML ;)

Par contre, étant donné que je serais amener rajouter des infos dans mon fichier XML, là, la DOM est indispensable.

Je voulais tout faire avec la DOM, car lire mon flux avec simpleXML puis rajouter des infos via la DOM je trouvais ça brouillon ;) M'enfin, si tu dis que c'ets plus rapide alors bingo !

J'utilise aussi foreach avec simpleXML et ca marche sans aucun problème, mais jvais m'orienté vers xpath c'est vraiment sympa.

Une autre question ! Quelle est la solution la plus simple si je veux, écrire/modifier des informations d'un fichier XML ? la DOM ? autre chose ? et me dis pas fopen() :p Je cherche quelque chose de propre tout de même =)

Encore merci à toi.
Cordialement,
Pierre.

Posté : 25 mai 2007, 23:08
par Hubert Roksor
je serais amener rajouter des infos dans mon fichier XML, là, la DOM est indispensable.
Pourquoi indispensable ? Tu peux modifier un arbre XML avec SimpleXML aussi facilement que tu peux le lire, est-ce que tu utilises quelque chose chez DOM que SimpleXML n'a pas ?

Si je reprends l'exemple plus haut, je peux ajouter un "day" supplémentaire de cette façon
$day = $xml->dayf->addChild('day');

$day['d'] = 2;
$day['t'] = 'Monday';
$day['dt'] = 'May 27';
$day->hi = 21;
$day->low = 21;
...puis mettre à jour le fichier par asXML()
$xml->asXML('temp.xml');
On peut difficilement faire plus... Simple ? Image

Posté : 25 mai 2007, 23:35
par zuX
Pour l'ajout je suis tout à fait daccord mais si je veux modifier la valeur de <hi> ?
Je ne vois aucune informations dans la doc :?

Re: La DOM + php 5 : parcer un fichier XML

Posté : 26 mai 2007, 00:47
par Hubert Roksor
Sous SimpleXML on peut accéder aux attributs comme s'ils étaient les valeurs d'un tableau (ou par la fonction attributes() mais autant aller au plus simple), et on peut accéder aux descendants comme s'ils étaient des variables de classe
Quand je dis "accéder", c'est en lecture ET écriture. Trouve le "day" et modifie la valeur de "hi". Donne-moi un exemple concret d'un nœud que tu voudrais modifier : par quel critères tu le sélectionnes, et les valeurs que tu veux modifier, et je te montrerais une ou deux façons de le faire.

Posté : 26 mai 2007, 01:29
par Hubert Roksor
J'en ai profité pour réviser mes propres connaissances donc je te donne l'exemple que j'ai utilisé pour gagner du temps. Disons que je veux modifier la valeur de "hi" pour le nœud dont l'attribut "dt" est "May 26". Je pourrais faire une boucle foreach et m'arrêter dès que je tombe sur le bon nœud, c'est souvent ce que font les débutants mais c'est une mauvaise idée parce que la boucle devient de plus en plus longue au fur et à mesure que ton volume de données grossit. À la place, on réutilise le bon vieux XPath.

On a vu comment trouver tous les nœuds "day" grâce à l'expression //day, maintenant il nous faut demander à XPath de ne filtrer que ceux qui correspondent à notre critère. Au passage on apprend que ces filtres s'appellent "prédicats" et qu'on peut les appliquer à tout groupe de nœuds. On ajoute un prédicat entre crochets à la suite du nom du nœud. Notre prédicat est "seulement ceux dont l'attribut 'dt' vaut 'May 26'". On note le nom d'un attribut à l'aide du caractère @. Au final, notre expression XPath est //day[@dt="May 26"] (tu peux utiliser des " ou ' indifféremment). Donc pour récupérer tous les nœuds dont la date est May 26, on utilisera
$xml->xpath('//day[@dt="May 26"]');
L'erreur courante c'est de s'attendre à ce qu'XPath retourne un nœud parce qu'on sait qu'il n'y a qu'un seul nœud qui correspond à cette date. Néanmoins, il n'y a pas de tel concept en XML donc XPath est configuré pour retourner un nombre quelconque de nœuds et utilise donc un tableau. Dans notre exemple, le tableau n'aura qu'un seul élément (voire zéro, si tu t'es trompé de date). Après avoir sélectionné l'élément du tableau on peut y appliquer tous les concepts de SimpleXML. Au final, pour changer le "hi" de la date en question on utilisera
$days = $xml->xpath('//day[@dt="May 26"]');

if (!isset($days[0]))
{
	echo 'Pas de mesure à cette date';
}
else
{
	$days[0]->hi = 32;
}

Posté : 26 mai 2007, 10:24
par zuX
Un GRAND merci à toi ;)
Je suis tout simplement bluffer :shock:

Je note l'astuce du xpath et du filtre "@" ;)
J'utilise un fichier XML aussi pour tous les paramètres de configuration de mon site (nombre de news par page, l'adresse email de l'admin, l'activation de la maintenance...) pour éviter de passer par une BDD ;)

Dans mon cas, je connais bien l'arborescence de mon fichier XML (nullement besoin d'utiliser de Xpath puisque je n'ai pas de double noeuds !).

Cependant, je note l'astuce puisqu'elle est très pratique.

J'ajoute simplement une remarque, très bien on peut ajouter un attribut, on noeud, le modifier ! et la suppression ?

De plus si je veux ajouter un autre day, entre 2 noeuds ! C’est possible ? Je sais que la DOM c'est le faire...

Cordialement,
Pierre.

Posté : 26 mai 2007, 12:47
par zuX
J'ajoute une chose,

pour enregistré par un 'é' dans mon fichier XML je suis obligé de faire un htmlspecialchars() + utf8_encode() sur ma variable qui contient mon texte.

Est-ce la bonne solution ?

Merci d'avance.

Posté : 27 mai 2007, 00:49
par Hubert Roksor
et la suppression ?
Ce n'est pas impossible, mais pas très pratique non plus. Tu peux faire quelque chose comme
unset($xml->dayf->day[1]);
...pour supprimer le second nœud "day", mais la suppression par critère n'est vraiment pas pratique parce qu'elle requiert de déterminer à quelle position se trouve le nœud à supprimer. Je ne connais pas de manière plus pratique que
$days = $xml->xpath('dayf/day[@d = "1"]');

// $idx est la position du nœud
$idx = array_search($days[0], $xml->xpath('dayf/day'));
unset($xml->dayf->day[$idx]);
si je veux ajouter un autre day, entre 2 noeuds ! C’est possible ?
Bonne question. Pas à ma connaissance, mais je peux me tromper. En tout cas j'en doute.

Posté : 29 mai 2007, 21:36
par zuX
Merci à toi je vais m'orienter vers la DOM pour ça ;)