Equivalent du SELECT de MySQL en PHP/XML? Extraire une donnée spécifiq

Equivalent du SELECT de MySQL en PHP/XML? Extraire une donnée spécifiq - PHP - Programmation

Marsh Posté le 16-11-2010 à 09:26:51    

Salut,
 
Je découvre XML et son parsing et je bloque sur un point.
 
Voici un résumé de mon flux (données fictives) :

Code :
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <catalogue>
  3. <progname>Laspatas</progname>
  4. <store>
  5.   <name>Laspatas</name>
  6.   <products>
  7.    <product>
  8.     <trademark>LUSTUCRU</trademark>
  9.     <title>TAGLIATELLES 250 G</title>
  10.     <desc>Tagliatelles fraîches en pack de 250gr</desc>
  11.    </product>
  12.    <product>
  13.     <trademark>BARILLA</trademark>
  14.     <title>TAGLIATELLES 500 G</title>
  15.     <desc>Tagliatelles fraîches en pack de 500gr</desc>
  16.    </product>
  17.   </products>
  18. </store>
  19. <catalogue>


 
J'ai fait ce script pour afficher les titres des produits, ça marche nickel :

Code :
  1. $xml = 'xml/monflux.xml';
  2. $flux = simplexml_load_file($xml);
  3. foreach($flux->store->products->product as $product){
  4. echo $product->title.'<br />';
  5. }


Ca fonctionne nickel. Mais ça affiche tout.
Comment ne faire afficher QUE sous conditions ?
Par exemple, ici, comment limiter l'affichage à la marque Barilla ?
 
Un grand merci


Message édité par vanquishV12 le 16-11-2010 à 09:37:05
Reply

Marsh Posté le 16-11-2010 à 09:26:51   

Reply

Marsh Posté le 16-11-2010 à 09:46:15    

Code :
  1. if($product->trademark == 'BARILLA'){
  2. echo $product->title;
  3. }


[:autobot]


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 16-11-2010 à 09:50:54    

Merci mais avec ça tu passes en revue l'ensemble des données dans le foreach et tu limites non pas la lecture / recherche des données (puisque tu parcours tout) mais l'affichage.
Il n'y a pas moyen de cibler directement ?

Reply

Marsh Posté le 16-11-2010 à 09:53:38    

vanquishV12 a écrit :

Merci mais avec ça tu passes en revue l'ensemble des données dans le foreach et tu limites non pas la lecture / recherche des données (puisque tu parcours tout) mais l'affichage.
Il n'y a pas moyen de cibler directement ?


 
...et tu crois que ça se passe comment, en sql? Le SGBD est capable de filter sans lire les données, peut-être? :D


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 16-11-2010 à 09:57:54    

En SQL je peux par exemple mettre une LIMIT 1 qui s'arrête dès que la ligne est trouvée.
C'est un exemple.
Et j'ai un autre cas de figure, comment faire (en restant dans mon exemple) pour n'afficher les TITLE que des produits ayant pour STORE > NOM 'laspatas' ?
 
Désolé si les questions sont stupides...

Reply

Marsh Posté le 16-11-2010 à 10:00:32    

vanquishV12 a écrit :

En SQL je peux par exemple mettre une LIMIT 1 qui s'arrête dès que la ligne est trouvée.
C'est un exemple.


 
Là aussi, il suffit d'ajouter un compteur que tu incrémentes à chaque fois que ton enregistrement matche ce que tu cherches, et un break.
 

vanquishV12 a écrit :


Et j'ai un autre cas de figure, comment faire (en restant dans mon exemple) pour n'afficher les TITLE que des produits ayant pour STORE > NOM 'laspatas' ?


tu boucles sur le store, puis sur les produits...aucune difficulté.


---------------
Can't buy what I want because it's free -
Reply

Marsh Posté le 16-11-2010 à 10:01:44    

Avec des xpath :

Code :
  1. $xml = 'xml/monflux.xml';
  2. $flux = simplexml_load_file($xml);
  3. foreach($flux->xpath("//product[trademark='BARILLA']" ) as $product){
  4.  echo $product->title.'<br />';
  5. }


 
Ici tu as pas mal de choses sur xpath : http://www.w3schools.com/xpath/default.asp


Message édité par Tirkyth le 16-11-2010 à 10:02:48

---------------
Mon Feedback !
Reply

Marsh Posté le 16-11-2010 à 10:06:21    

Merci beaucoup pour vos réponses. Xpath me semble tout à fait ce que je cherche. C'est gourmand cette bête là ? (genre sur un flux d'1 Go :D )

Message cité 1 fois
Message édité par vanquishV12 le 16-11-2010 à 10:06:32
Reply

Marsh Posté le 16-11-2010 à 10:06:42    

vanquishV12 a écrit :

En SQL je peux par exemple mettre une LIMIT 1 qui s'arrête dès que la ligne est trouvée.
C'est un exemple.
Et j'ai un autre cas de figure, comment faire (en restant dans mon exemple) pour n'afficher les TITLE que des produits ayant pour STORE > NOM 'laspatas' ?
 
Désolé si les questions sont stupides...


De la même manière, avec un xpath :

Code :
  1. $xml = 'xml/monflux.xml';
  2. $flux = simplexml_load_file($xml);
  3. foreach($flux->xpath("/store[name='laspastas']/products/product" ) as $product){
  4.  echo $product->title.'<br />';
  5. }


---------------
Mon Feedback !
Reply

Marsh Posté le 16-11-2010 à 10:17:57    

vanquishV12 a écrit :

Merci beaucoup pour vos réponses. Xpath me semble tout à fait ce que je cherche. C'est gourmand cette bête là ? (genre sur un flux d'1 Go :D )


Gourmand ça je ne pourrais pas trop dire ...
En fait, je suppose que si tu arrives à charger ton fichier avec simplexml_load_file tu es tranquille, je suppose que les éléments renvoyés par xpath sont des références d'objets déjà créés lors du chargement de ton xml. Mais je n'ai aucune certitude là dessus.
 
Sinon, il me semble que simplexml est un parseur DOM, alors qu'il existe aussi des parseurs SAX qui sont il me semble plus indiqué pour traiter des fichiers de taille importante. Il me semble que le parseur DOM créé un arbre contenant tous les noeuds directement, alors que le parseur SAX non.
La doc est là : http://us2.php.net/manual/fr/book.xml.php
 

vanquishV12 a écrit :

Ca me donne Invalid argument supplied for foreach()


Pour le 2ème cas ? Avec une majucule à Laspastas ça devrait aller mieux ;)


---------------
Mon Feedback !
Reply

Marsh Posté le 16-11-2010 à 10:17:57   

Reply

Marsh Posté le 16-11-2010 à 10:25:41    

Oui le second cas, il ne me renvoie aucun résultat, comme si aucun résultat n'était trouvé.
 
Merci pour les liens.

Reply

Marsh Posté le 16-11-2010 à 10:35:03    

J'ai pas testé donc je te laisse lire les liens et corriger l'expression xpath comme il faut. Mais j'ai fait des fautes j'ai écrit "laspastas" au lieu de "Laspatas".
Je pense que c'est juste ça qui ne va pas. Il faut qu'il soit correctement écris et en respectant les majuscules.


---------------
Mon Feedback !
Reply

Marsh Posté le 16-11-2010 à 10:43:21    

je dirais plutôt comme ca le xpath :
//store[name='Laspatas']/products/product


Message édité par stealth35 le 16-11-2010 à 10:44:14
Reply

Marsh Posté le 16-11-2010 à 11:00:23    

C'est bon merci à vous en fait je m'étais planté dans mon affichage echo ;)
 
Merci beaucoup pour votre aide, c'est cool de pouvoir compter sur les experts sans se faire envoyer sur les roses. Les liens m'ont été très utiles également.
 
Bonne journée (et p-e à plus tard :D )

Reply

Marsh Posté le 16-11-2010 à 23:23:06    

question stupide mais pourquoi ne pas passer par une DB :??:
charger le fichier dans une DB puis sélectionner ce que l'on veux...


---------------
Tout à commencé par un rêve...
Reply

Marsh Posté le 17-11-2010 à 08:15:32    

Par ce que les données sont actualisées à l'externe toutes les 4 heures...

Reply

Marsh Posté le 17-11-2010 à 10:36:26    

ça n'empêche pas d'en faire autant pour ta base ;)
avec un script en cron ou autre suivant le mode de mise à jour ...


---------------
Tout à commencé par un rêve...
Reply

Marsh Posté le 17-11-2010 à 10:53:00    

ça dépend de la fréquence à laquelle il fait ses selects. S'il a 1 update toutes les 4h et qu'il fait 1 select  / jour, alors ça serait con d'insérer le tout dans une BDD.
S'il a 1000 requetes par minute, par contre, faudrait vraiment passer par un système plus malin genre SOAP+BDD je pense.


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 17-11-2010 à 11:04:57    

Je fais une requête toutes les 4 heures, une mise à jour des données toutes les 4 heures et la page / le select sont effetués une seule fois. Après génératino des résultats, tout est stocké en cache statique.
 
J'ai fais des tests hier, ça marche très très bien.
 
Merci pour votre aide en tout cas.

Reply

Marsh Posté le 17-11-2010 à 11:05:28    

stef_dobermann a écrit :

ça n'empêche pas d'en faire autant pour ta base ;)
avec un script en cron ou autre suivant le mode de mise à jour ...


Non non tu n'y penses pas. XML est largement plus souple pour ça !

Reply

Marsh Posté le 17-11-2010 à 11:08:16    

J'irais pas jusqu'à là quand même ...
Ta structure de système est ce qu'on utilise dans le cas où on ne peut/veut pas donner accès à la base de donnée à des partenaires extérieurs. On passe donc par qqch genre SOAP pour créer un étage intermédiaire. Mais de là à dire que c'est plus souple qu'une BDD, faut pas non plus exagérer ;)


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 17-11-2010 à 11:10:53    

Je ne parle pas du niveau des traitement mais de l'import / export.
Pour ma part, importer les nouvelles données me parait plus souple.
Après, pour l'utilisation des données, c'est autre chose...
 
De toutes façons je n'ai pas d'accès BDD, j'utilise bien un flux partenaire.

Reply

Marsh Posté le 17-11-2010 à 11:14:30    

Non mais d'accord, c'est justement c'est ce que je dis :o
Transporter des données par XML : Pas forcément une mauvaise idée (voir SOAP justement)
Utiliser un fichier XML comme base pour actions CRUD : En général très mauvaise idée. Il vaut mieux prendre le flux XML et insérer les données dans une BDD pour ensuite effectuer les post-traitements.
 
Dans ton cas, vu que tu fais très peu d'opérations avec tes données, la situation est un peu différente et en effet ça aurait aucun sens d'utiliser une BDD.


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 18-11-2010 à 16:57:36    

Bon ça fonctionne très bien mais j'ai encore un souci.

 

Imaginons ceci (non lié au flux ci dessus) :

Code :
  1. foreach($flux->xpath("store/products/product[trademark='BARILLA']/category/merchant[contains(name,'TAGLIATELLES')]" ) as $product){
  2. echo $product->image;
  3. }


Je voudrais que $product contienne en fait store/products/product
or là, pour des raisons de tri, il contient store/products/product/category/merchant

 

J'ai eu beau chercher, je n'ai pas réussi à le faire. Je sais qu'il y a des child::* ect mais je n'arrive pas à m'en servir.


Message édité par vanquishV12 le 18-11-2010 à 16:58:10
Reply

Marsh Posté le 18-11-2010 à 18:36:20    

comme pour un path normale  avec .. pour remonter au parent

 

store/products/product[trademark='BARILLA']/category/merchant[contains(name,'TAGLIATELLES')]/../../


Message édité par stealth35 le 18-11-2010 à 18:41:14
Reply

Marsh Posté le 18-11-2010 à 18:38:47    

:pt1cable: merci je teste ça, j'avais pas du tout pensé à cette méthode.
 
Merci [:charlest]

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed