Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: analiza danych duzego pliku XML
Forum PHP.pl > Forum > PHP
AcidBurnt
Witam

Sprawa taka pliczek XML wazy 32 mb, w nim mam dane na temat SMSów logosłow, dzwonków, itp z PP wapster.pl no i problem z racji wielkosc pliku nie zabardzo moge Sobie poradzic z jego przecytaniem, wczytaniem do tablicy itp z racji ograniczenia pamieci na moim serwerze do 20. wiec wpadlem na pomysl i dziele Sobie plik na kilka mniejszych

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <wapsterdump>
  3.  <authors>
  4.    <item id="1674" name="000" />
  5.    .
  6.    .
  7.    .
  8.    <item id="1121" name="50 Cent feat. Olivia" />
  9.    <item id="824" name="52 Dębiec" />
  10.  </authors>
  11.  <manufacturer name="Nokia" id="1">
  12.   ..,  tutaj informacje na temat dzwonków logosów itp
  13.  </manufacturer>
  14.  <manufacturer name="Siemens" id="2">
  15.  .
  16.  .
  17.  .
  18.  </manufacturer>


no i napisałem Sobie dla niego coś takieg:

  1. <?php
  2. error_reporting(E_ALL^E_NOTICE);
  3. echo time()."<br />";
  4. $uchwyt = fopen ("newdump.xml", "r");
  5. if ($uchwyt) {
  6. while (!feof($uchwyt)) {
  7. $buffer = fgets($uchwyt, 4096);
  8.  
  9. if($authors_open){
  10. fwrite($authors, $buffer);
  11. }
  12. if(preg_match('/<authors>/', $buffer)){
  13. $authors = fopen("authors.xml", 'w+');
  14. fwrite($authors, $buffer);
  15. $authors_open = 1;
  16. }
  17. if(preg_match('/</authors>/', $buffer)){
  18. fclose($authors);
  19. $authors_open = 0;
  20. }
  21.  
  22. if($com_open){
  23. fwrite($com, $buffer);
  24. }
  25. if(preg_match('/<manufacturer(.*?)>/', $buffer)){
  26. preg_match('/<manufacturer name="(.*?)" id="[0-9]{1,2}">/', $buffer, $m);
  27. $com = fopen("".$m[1].".xml", "w+");
  28. fwrite($com, $buffer);
  29. $com_open = 1;
  30. }
  31.  
  32. if(preg_match('/</manufacturer>/', $buffer)){
  33. fclose($com);
  34. $com_open = 0;
  35. }
  36. }
  37. fclose ($uchwyt);
  38. }
  39. echo time()."<br />";
  40. ?>


czyli lece przez cały plik wiersz po wierszu i dziele duzy na małe podzionego na poszczegolne telefony: nokia, siemes tip

no tylko pytanie czy moge to jakos zoptymalizowac czasowo, gdyz operacja ta trwa na serwerze w nazwa.pl 24-28 sekund ;/ moj komp potrzebuje prawie 40.. no a do tego jeszcze bedzie miala dojsc analiza poszczegolnych modeli, sprawdzenie roznic miedzy moja baza a tymi danymi, i wlasnie tez sie tutaj zastanawiam czy docelowo przewalac wszystko do bazy, czy trzymac reszte danych tylko w plikach XML, podzielic konkretne modele na wiecej plików, no w jednym informacje o logach, w innym o dzwonkach, i nie korzystac z bazy....

jakies pomysły? z góry dzieki za wszelkie sugestie.

aha i po tym podziele najwiekszym plikiem jest NOKIA.xml wazy okolo 7.5 MB, no i niesteyt dalej wczyanie tego do jakies tablicy czy cos jest problemem
erix
Lepiej by bylo uzyc do tego bazy.

Tylko to sie mija z celem, jesli plik XML jest co chwila uaktualniany.

Niestety, nie podales w jakich odstepach nastepuje update pliku...

IMHO, gdybys poszedl na kompromis i uaktualnial go raz na dobe, to napisalbys sobie skrypt, co by parsowal XML-a i wrzucal go do bazy.
AcidBurnt
xml jest uaktualniany wlasnie raz na dobre

no i wlasnie chyba tak zrobie i powoli pisze dodawanie tego do bazy, bo chyba inna opcja mi nie zostala... jak napisze to zostawie to tutaj dla potomnych moze ktos jeszcze kiedys bedze walczyl z wapsterem smile.gif


tylko problem jest caly czas z wielkoscia pliku, nie moge go przerobic za pomoca czegos jak SIMLPE XML czy cos bo brakuje mi 20mb dostapnej pamieci winksmiley.jpg jak narazie napisałem Sobie aktualniacje danych na temat autorów

sprawdza to najpierw czy są jakies nowe wpisy w XML a pozniej czy z XML nie zostaly usuniete jakies wpisy

  1. <?php
  2. require('./lib/adodb/adodb.inc.php');
  3. require('./lib/adodb/adodb-errorhandler.inc.php');
  4. require('./config.php');
  5. /* ładowanie steronika do bazy, i logowanie */
  6. $db = ADONewConnection('postgres7');
  7. $db->SetFetchMode(ADODB_FETCH_ASSOC);
  8. $db->debug = false;
  9. $db->Connect($db_server, $db_user, $db_password, $db_database);
  10. $auth = $db -> GetAll("SELECT * FROM sms_authors");
  11. foreach($auth as $a => $line){
  12. $authors[$line['id_author']] = $line['name_author'];
  13. }
  14. unset($auth);
  15. $uchwyt = fopen ("xml/authors.xml", "r");
  16. if ($uchwyt) {
  17. while (!feof($uchwyt)) {
  18. $buffer = fgets($uchwyt, 4096);
  19. preg_match('/<item id="(.*?)" name="(.*?)" />/', $buffer, $a);
  20. if(!empty($a) && !array_key_exists($a[1], $authors))
  21. $db -> Execute("INSERT INTO sms_authors VALUES('".$a[1]."', '".iconv('UTF-8', 'ISO-8859-2',(addslashes($a[2])))."')");
  22.  
  23. $in_xml[$a[1]] = $a[2];
  24. }
  25. }
  26. $auth = $db -> GetAll("SELECT * FROM sms_authors");
  27. foreach($auth as $a => $line){
  28. if(!array_key_exists($line['id_author'], $in_xml))
  29. $db -> Execute("DELETE FROM sms_authors WHERE id_author = '".$line['id_author']."'");
  30. }
  31. ?>



u mnie na kompie 1.5hg, 1gb ram schodzi do 0.7 sekundy no ale konkretnie tutaj jest taki pliczek XML

  1.  <authors>
  2.    <!--Kolekcja [wapsterdump/authors], zawiera listę autorów dzwonków, id - to id autora wykorzystywany później przy opisie dzwonków, name - nazwa autora-->
  3.    <item id="1674" name="000" />
  4.    <item id="1480" name="05 &amp; Radeček" />
  5.    <item id="1649" name="2 + 1" />
  6.    <item id="1388" name="2 Unlimited" />
  7.    <item id="1287" name="24 Love" />
  8.    <item id="1267" name="2Pac" />
  9.    <item id="975" name="3rd Wish" />
  10.    <item id="583" name="4 The Cause" />


z 1551 wpisów takze nic strasznego

a zawartosc pliku info o gadzetach na NOKIE to 167 tysieci LINI SIC!!!
FiDO
Od analizy duzych XML'i jest inny parser (expat), ktorzy rowniez jest dostepny z poziomu php: http://www.php.net/manual/en/ref.xml.php
Pisanie pod to jest znacznie mniej wygodne niz simplexml czy inne, ale dzieki temu zuzycie pamieci jest minimalne niezaleznie od wielkosci pliku. Dodatkowym atutem jest szybkosc parsowania.
AcidBurnt
eh niestety tez nie za bardzo chce dzialac, samo "przelecenie" przez pliczek 7.5 zajelo mu az 23 sekundy takze nie ma nawet raczej mowy o akichkolwiek operaciach ;/
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.