Bonjour,
Je me tourne vers vous car je cherche une solution à mon problème d'analyse de fichier XML. Solution que je trouve absolument pas grosse galère..
Je dois analyser des fichiers assez important > 1gb et je possède un serveur mutualisé
Mes analyses de fichier sont effectuées automatiquement via mon hébergement et les tâches planifiées en SSH.
J'utilise XMLReader via PHP pour analyse des fichiers et SimpleXMLElement pour créer les arbres de mes noeuds au fur et à mesure pour simplifier l'analyse et la récupération des données.
Mon problème est que les tâches planifiées en mutualisées sont limitées à 1h d'éxécution.. et je ne peux pour le moment pas passer sur un dédié car trop cher pour le moment et à priori j'ai au moins besoin de 3h pour lire le fichier complet
J'ai donc trouvé une solution :
Au premier lancement de la tâche j'ouvre le fichier et je l'analyse. Au bout de 55 minutes d'analyses je tue la tâche via un die() et j'enregistre la dernière valeur analysée dans ma base de données ce qui fait que j'ai un genre de checkpoint pour l'analyse suivante commençant 10minutes après.
A partir de la seconde mise à jour je récupère la référence du dernier noeud id dans ma base de donnée et tant que je ne le rencontre pas, lors de la nouvelle lecture du fichier, je n'effectue pas de mise à jour. Seulement si le fichier est supérieur à 1gb je peux mettre 20 minutes voir plus à retrouver l'ancienne référence.. je perds donc un temps fou.
Help :
Est-il possible via Xmlreader d'utiliser une fonction de type movetoelement ou vers l'attribut prenant en compte ma dernière référence sans avoir à relire tout le fichier ? Ceci me ferait gagner un temps considérable.
Dans le fichier ci-dessous le but serait moveToAttribute('3'); mais je pense mal le mettre en place...
Voici un exemple de fichier XML que je dois analyser :
Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 <?xml version="1.0" encoding="utf-8"?> <PRODUITS> <PRODUIT id="1"> <CAPACITE>4</CAPACITE> <LOGEMENT><![CDATA[Résidence]]></LOGEMENT> <HEBERGEMENT><![CDATA[Studio 4 personnes]]></HEBERGEMENT> <REGION><![CDATA[Alpes du Nord]]></REGION> <PAYS><![CDATA[France]]></PAYS> <CODEPOSTAL>73500</CODEPOSTAL> </PRODUIT> <PRODUIT id="2"> <CAPACITE>4</CAPACITE> <LOGEMENT><![CDATA[Résidence]]></LOGEMENT> <HEBERGEMENT><![CDATA[Studio 4 personnes]]></HEBERGEMENT> <REGION><![CDATA[Alpes du Nord]]></REGION> <PAYS><![CDATA[France]]></PAYS> <CODEPOSTAL>73500</CODEPOSTAL> </PRODUIT>
Voici comment j'analyse mes fichiers :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 <?php if(file_exists("$file_xml")) { $reader = new XMLReader(); $reader->open("$file_xml"); while($reader->read()) { if( ($reader->name === 'PRODUIT') && ($reader->nodeType==XMLReader::ELEMENT) ) { $node = new SimpleXMLElement($reader->readOuterXML()); $id= mysql_real_escape_string(utf8_decode($node['id'])); // Si il s'agit d'une seconde mise à jour et que la référence précédente n'est pas vide alors je test la référence et tant que je ne la retrouve pas je ne fais pas la mise à jour if( ($id!="0") && ($id!="3") ) { // On ne fait rien le produit a déjà été enregistré } else { // Sinon c'est bon on continu la mise à jour $id = 0; $num = mysql_real_escape_string(utf8_decode($node['num'])); .... } } } $reader->close(); }
Si jamais cette fonction n'est pas possible, est-il possible de supprimer le noeud lu du fichier xml lu et ensuite de le sauvegarder en l'écrasant au bout de 50 mn ? Ceci permettant de retrouver directement le noeud où j'en étais sans avoir à bidouiller ?
Merci pour votre aide.
Guillaume
Partager