Parser un xml voluminueux sur plusieurs pages ?

WRInaute occasionnel
bonjour,

Actuellement je parse un fichier xml en php, en faisant une mise en cache du code généré. Cependant maintenant le fichier xml devient un peu long. Je voudrais donc le parser sur plusieurs pages? Afficher par exemple 20 résultats par page.
Voila le code que j'utilise:


Code:
<?php

// le répertoire "cache" 

$dir_cache = 'cache/';

// nom du fichier mis en cache
$file_cache1 = 'flux1.html';

if (!is_dir($dir_cache)) {
	exit ('Répertoire cache "'.$dir_cache.'" inexistant !');
}


	// on impose la mise à jour avec une certaine periodicité
$date_modif1 = time();
	// le delai entre deux rafraichissements en secondes 
	$delai1 = 43200;


// le fichier est-il en cache et suffisamment jeune
$file_cache1 = $dir_cache.$file_cache1;
$en_cache1 = file_exists($file_cache1);
if ($en_cache1) {
	$en_cache1 = ($date_modif1 < filemtime($file_cache1) + $delai1);
}

if (!$en_cache1) {
	// Lecture d'un fichier XML
function lit_xml1($fichier,$item,$champs) {
   // on lit le fichier
   if($chaine = @implode("",@file($fichier))) {
      // on explode sur <item>
      $tmp = preg_split("/<\/?".$item.">/",$chaine);
	  
	
	  $nombre = sizeof($tmp);

      // pour chaque <item>
      for($i=1;$i<$nombre -1;$i+=2)
         // on lit les champs demandés <champ>
         foreach($champs as $champ) {
            $tmp2 = preg_split("/<\/?".$champ.">/",$tmp[$i]);
            // on ajoute au tableau
            $tmp3[$i-1][] = @$tmp2[1];
         }
      // et on retourne le tableau
      return $tmp3;
   }
}

// Exemple :
$xml1 = lit_xml1("http://monsite.com/xml.php","item",array("title","description","link","category","url"));

		foreach($xml1 as $row1) { 
			
		
		$data1 .= '<br><table width=400 height=190 align=center cellpadding=0 cellspacing=0 bgcolor="#F8D630"  border=2>';
		$data1 .= '<tr>';
		$data1 .= '<td colspan=2 height=25 align=center bordercolor=#FFFFCC><a href='.$row1[2].'><font color="#000000">'.$row1[0].'</font> </a></td>';
		$data1 .= '</tr>';
		$data1 .= '<tr>';
		$data1 .= '<td bordercolor=#FFFFCC height="136" width="133" valign="middle" align="center"><a href='.$row1[2].'><img src='.$row1[4].' border=0></a></td>';
		$data1 .= '<td  bordercolor=#FFFFCC ><span class="tailledescrip" ><div style="margin-left:10px;">'.$row1[1].'</div></span></td>';
		$data1 .= '</tr>';
		$data1 .= '<tr>';
		$data1 .= '<td colspan=2 height=25 bordercolor=#FFFFCC><p><em>catégorie :</em> '.$row1[3].' <em> </td>';
		$data1 .= '</tr>';
		$data1 .= '</table><br>';
		
		
	}
	
	$fd1 = fopen($file_cache1, "w");
	fputs($fd1, $data1);
	fclose($fd1);

} // fin if !$en_cache1

include $file_cache1;
?>

Je ne vois pas trop comment modifier ce code ?

Merci
 
WRInaute passionné
Code:
$nombre = sizeof($tmp);

      // pour chaque <item>
      for($i=1;$i<$nombre -1;$i+=2)
Je penses que c'est là qu'il faut chercher la solution. Mais je suis pas développeur, alors je voudrais pas mettre le dawa dans ton appli ! :p
 
WRInaute occasionnel
Je me demande s'il ne serais pas plus simple d'enregistrer le xml dans la base mysql et de travailler dessus ensuite.
A ce sujet est ce que cela est possible d'ailleurs ?

Parce que la avec le xml, je ne vois pas trop comment faire..

Merci
 
WRInaute occasionnel
C'est bon j'ai réussi à intégrer un système de pagination sur le parser Xml. J'ai fait plusieurs tests, tout fonctionne correctement.
Cependant j'ai un autre soucis, je viens d'essayer de parser un gros fichier xml ( 10Mo ) et forcément j'ai eu '500 Internal Server Error' , vu qu'avant d'afficher les résultats , je mets toutes les données dans un tableau qui forcément est immense.
A votre avis comment est-ce que je pourrais faire pour ne lire qu'une partie du fichier xml puis afficher , puis lire la suite , puis afficher etc... Je pense que c'est le seul moyen de m'en sortir non ?

Merci
 
Nouveau WRInaute
Salut,

comme tu le disais precedemment, il serait peut-etre interessant de mettre tout ca dans une base MySql.

Tu utilise le XML pour une raison spéciale ?
 
WRInaute occasionnel
Le fichier Xml m'est fourni, je dois travailler avec et extraire les données. Mais la je coince un peu. Quelqu'un a-t-il déjà parser un xml volumineux ?
 
Nouveau WRInaute
Si tu ne peux pas passer par une base Mysql...

Tu peux essayer de modifier le script... et ne remplir le tableau qu'avec les données qui t'interessent.

il faut que tu modifies la fonction lit_xml1 pour qu'elle accepte 2 nouveaux paramètres, l'enregistrement de départ et le nombre d'enregistrements que tu souhaites.

function lit_xml1($fichier,$item,$champs,$depart,$nb) {


Puis tu modifes :

$nombre = sizeof($tmp);
if($nombre>$depart+$nb) $fin = $nombre;
else $fin = $depart+$nb;
for($i=$depart;$i<$fin-1;$i+=2)
// on lit les champs demandés <champ>
foreach($champs as $champ) {
$tmp2 = preg_split("/<\/?".$champ.">/",$tmp[$i]);
// on ajoute au tableau
$tmp3[$i-1][] = @$tmp2[1];
}
// et on retourne le tableau
return $tmp3;
}

Ca devrait etre un truc du genre.

Sinon cherche sur internet, il y a des scripts qui permettent de récupérer le XML (je connais pas trop).

Essaye et tiens moi au courant... :)
 
WRInaute occasionnel
jobi1722 a dit:
Si tu ne peux pas passer par une base Mysql...

Tu peux essayer de modifier le script... et ne remplir le tableau qu'avec les données qui t'interessent.

il faut que tu modifies la fonction lit_xml1 pour qu'elle accepte 2 nouveaux paramètres, l'enregistrement de départ et le nombre d'enregistrements que tu souhaites.

function lit_xml1($fichier,$item,$champs,$depart,$nb) {


Puis tu modifes :

$nombre = sizeof($tmp);
if($nombre>$depart+$nb) $fin = $nombre;
else $fin = $depart+$nb;
for($i=$depart;$i<$fin-1;$i+=2)
// on lit les champs demandés <champ>
foreach($champs as $champ) {
$tmp2 = preg_split("/<\/?".$champ.">/",$tmp[$i]);
// on ajoute au tableau
$tmp3[$i-1][] = @$tmp2[1];
}
// et on retourne le tableau
return $tmp3;
}

Ca devrait etre un truc du genre.

Sinon cherche sur internet, il y a des scripts qui permettent de récupérer le XML (je connais pas trop).

Essaye et tiens moi au courant... :)

J'ai déja essayé de faire ca , en ne remplissant que quelques enregistrements. Mais cela plante qd meme , le problème vient de

Code:
if($chaine = @implode("",@file($fichier))) {
      // on explode sur <item>
      $tmp = preg_split("/<\/?".$item.">/",$chaine);

La chaine est trop grande. C'est pour ça que je voudrais soit couper le xml en plusieurs fichiers, soit ne mettre dans la chaine qu'une partie du xml à chaque fois. hummmm....
 
WRInaute occasionnel
Je suis en train de me décider a couper le xml en plusieurs fichiers. Mais j'ai un petit soucis:

Voila la structure du xml de 10Mo, tres simple.

<item>
........
</item>
<item>
.......
</item>
.....


Voila le code que j'ai ecrit:
J'ai choisi pour l'exemple des fichiers qui ne devrait contenir que 2 items

Code:
<?php

$fichier="essai.xml";
$nbrs_item=2;
$sauv="sav";
$compteur=0;
$nbrs_fichier=1;


$fp=fopen($fichier,"r");

    while (!feof($fp)) {

		   while (($compteur <$nbrs_item )&& (!feof($fp)))
		   
		       { $ligne=fgets($fp,255);
			         $compteur=$compteur+substr_count($ligne,"</item>");
				  $chaine.=$ligne;
				  
		
			   }//fin while compteur
		
		
		
$fp2 = fopen($sauv.$nbrs_fichier.'.xml',"w"); // ouverture du fichier en écriture

fputs($fp2, "$chaine"); // on écrit le texte choisi dans le fichier

fclose($fp2); 
		
		
$compteur=0;
$nbrs_fichier+=1;
$ligne="";
$chaine.="";
		                  } // fin feof
		
		fclose($fp);
	
?>

Pour le premier fichier sauvé, sav1.xml tout va bien. J'ai bien 2 item.
Pour le 2iéme par contre il en contient 4 , il s'additionnent à ceux de sav1. Et ainsi de suite.

En fait je pensais que puisque je ne fermais pas le fichier entre 2 sauvegardes la lecture continuerait vers le bas. Mais non cela recommence du début :-(.
Je coince un peu là. Comment donc enregistrer des fichiers qui vont contenir un nombre déterminé d'item ?

Merci pour votre aide.
 
WRInaute occasionnel
c'est bon j'ai trouvé :D .

Code:
<?php 

$fichier="essai2.xml"; 
$nbrs_item=6; 
$titre="sav"; 


$compteur=0; 
$nbrs_fichier=1; 


$fp=fopen($fichier,"r"); 

    while (!feof($fp)) { 

         while (($compteur <=$nbrs_item)&&(!feof($fp))) 
          
             { $ligne=fgets($fp,255); 
               $compteur=$compteur+substr_count($ligne,"</item>"); 
              $chaine.=$ligne; 
              
             
              
         if (( $compteur==$nbrs_item)||(($compteur <=$nbrs_item )&&(feof($fp)))) 
            { 
       
            $fp2 = fopen($titre.$nbrs_fichier.'.xml',"w"); // ouverture du fichier en écriture 

              fputs($fp2, "$chaine"); // on écrit le texte choisi dans le fichier 

              fclose($fp2); 
             
            $compteur+=1; 
            } 
             
             
             
             
             
            }//fin while compteur 
       
       
       
      $chaine=""; 
    
       $nbrs_fichier+=1; 
       
      $compteur=0; 
       
      $ligne=""; 
       
      } // fin feof 
       
      fclose($fp); 
    
?>
 
Nouveau WRInaute
Moi j ai aussi un probleme avec le parsing xml :

dans un premier temps, nous effectuons une requete vers un serveur qui a un temps de reponse plus ou moins long selon les specificités de la requete;
nous arrivons a parser cette requete avec un parser :

Code:
<?
class XMLParser {
   var $filename;
   var $xml;
   var $data;
   
   function XMLParser($xml_file)
   {
       $this->filename = $xml_file;
       $this->xml = xml_parser_create();
       xml_set_object($this->xml, $this);
       xml_set_element_handler($this->xml, 'startHandler', 'endHandler');
       xml_set_character_data_handler($this->xml, 'dataHandler');
       $this->parse($xml_file);
   }
   
   function parse($xml_file)
   {
       if (!($fp = fopen($xml_file, 'r'))) {
             die('Cannot open XML data file: '.$xml_file);
               return false;
       }
 
       $bytes_to_parse = 512;
 
       while ($data = fread($fp, $bytes_to_parse)) {
           $parse = xml_parse($this->xml, $data, feof($fp));
           
           if (!$parse) {
               die(sprintf("XML error: %s at line %d",
                   xml_error_string(xml_get_error_code($this->xml)),
                       xml_get_current_line_number($this->xml)));
                       xml_parser_free($this->xml
                     );
           }
       }
 
       return true;
   }
   
   function startHandler($parser, $name, $attributes)
   {
       $data['name'] = $name;
       if ($attributes) { $data['attributes'] = $attributes; }
       $this->data[] = $data;
   }
 
   function dataHandler($parser, $data)
     {
     if($data = trim($data))
         {
         $index = count($this->data) -1;
         if(isset($this->data[$index]['content'])) 
           $this->data[$index]['content'] .= $data;
           else $this->data[$index]['content'] = $data;
         }
     }
 

   function endHandler($parser, $name)
   {
       if (count($this->data) > 1) {
           $data = array_pop($this->data);
           $index = count($this->data) - 1;
           $this->data[$index]['child'][] = $data;
       }
   }
 function ReturnData ()
 {
  return $this->data;    
 }
}
?>

Que pensez vous de ce parser ??

Sachant que nous avons de gros problemes de performances du fait de ce parsing... Le parsing prend beaucoup de ressources, et le trafic sur notre site augmentant, notre serveur sature.

Avez vous une solution ??
Merci d'avance
 
WRInaute impliqué
Je vois pas bien l'intéret d'avoir à la base un fichier XML et de tout stocker dans des tableaux, c'est un peu contre productif.

S'il y a besoin de faire des traitement sur les données, autant utiliser DOM, ce sera plus efficace et si c'est pour faire de l'affichage direct, autant le faire directement à partir du parser SAX.
 
Nouveau WRInaute
En fait on a deja une base de données et un tableau liste de resultats pour une requete donnée,
et on utilise le flux xml de partenaires pour ajouter leurs resultats aux notres par rapport a la requete donnée.

Du coup, on ne peut afficher directement les données du flux, c est pour cela qu on stocke au prealable dans un tableau, pour comparer les resultats avec les notres et les concatenér.


Avons nous une autre possibilité ?
 
Discussions similaires
Haut