• User

    Convertire CSV in XML...

    Salve a tutti, sto preparando la mia tesina per l'esame di maturità e ho bisogno di uno script in PHP per convertire i file csv in xml. Mi serve in PHP in quanto verrà integrato come utility nel sito web che sto realizzando per gestire l'OpenData.

    In rete se ne trovano di funzionali ma non ottengo il risultato desiderato.
    Il mio file CSV è come l'esempio riportato sotto:

    Matricola;AnnoScolastico;ClasseFreq;Esito;DomicilioComune;DomicilioProvincia;Alunno

    11111;2004-2005;1AS;AMMESSO;VERONA;VERONA;Mario Rossi
    11112;2004-2005;1AS;AMMESSO;VERONA;VERONA;Mario Rossi
    11113;2005-2006;2AS;AMMESSO;VERONA;VERONA;Mario Rossi
    11114;2005-2006;2AS;AMMESSO;VERONA;VERONA;Mario Rossi
    11115;2006-2007;3AS;AMMESSO;VERONA;VERONA;Mario Rossi
    11116;2006-2007;4AS;AMMESSO;VERONA;VERONA;Mario Rossi

    Ovviamente il file originale contiene molte più righe, circa 960.

    Il risultato che vorrei ottenere è questo:
    [PHP]
    <2004-2005>
    <1AS>
    <11111>
    <esito>AMMESSO</esito>
    ....
    <alunno>Mario Rossi</alunno>
    </11111>
    <11112>
    ......
    </11112>
    </1AS>
    </2004-2005>
    ......

    [/PHP]
    Ovviamente lo script deve poter trasformare file csv con struttura diversa, e permettere di scegliere la struttura del file XML di output.

    Mi andrebbe bene anche un programma fatto in un linguaggio diverso dal php, posso sempre tradurlo.

    Grazie a tutti per il vostro tempo 😉


  • ModSenior

    Non capisco bene quale algoritmo usare. Vedendo 11111 come prima colonna mi verrebbe da pensare che dovrebbe essere il primo nodo in XML o sbaglio? Lo vedo come terzo invece.


  • User

    Il file CSV contiene nella prima riga i descrittori e poi dalla seconda in avanti tutti i valori.

    A me serve una classe in cui passo come parametri i nodi in ordine, ovvero: AnnoScolastico, ClasseFreq, Matricola

    Il programma deve estrarre il primo anno disponibile, poi la classe, successivamente la matricola e per finire tutte le informazioni che appartengono a quella determinata matricola. Il risultato dovrà quindi essere:

    [PHP]
    <2004-2005> --> AnnoScolastico
    <1AS> --> ClasseFreq
    <11111> --> Matricola
    <esito>AMMESSO</esito> --> Informazioni dello studente
    ....
    <alunno>Mario Rossi</alunno>
    </11111>
    <11112>
    <esito>AMMESSO</esito>
    ....
    <alunno>Mario Rossi</alunno>
    </11112>
    </1AS>
    </2004-2005>
    <2005-2006> --> AnnoScolastico
    <2AS> --> ClasseFreq
    <11113> --> Matricola
    <esito>AMMESSO</esito>
    ....
    <alunno>Mario Rossi</alunno>
    </11113>
    <11114>
    <esito>AMMESSO</esito>
    ....
    <alunno>Mario Rossi</alunno>
    </11114>
    </2AS>
    </2005-2006>
    Ecc.....
    [/PHP]

    Spero di essermi spiegato.
    Grazie per l'interessamento :smile5:


  • ModSenior

    Mi piacciono le sfide... 😄 Provo a vedere ... senza impegno... Cosa riesco a fare.. 🙂
    Spero solo di aver capito bene il tutto.
    L'ordine delle colonne nel file CSV resta comunque quello vero?


  • User

    Grazie per la tua disponibilità.

    Il mio vero problema sta nel fatto che il file CSV che acquisisco può cambiare, nel senso che può contenere un diverso numero di colonne, argomenti, ecc...

    Se rimanesse tutto così riuscirei a farlo. Il mio obiettivo era quello di trovare un algoritmo generale che mi permetta di generare il file XML partendo dal CSV, passando come parametri la struttura del file XML.


  • ModSenior

    Allora l'unica cosa che vedo è che per forza di cose, la prima colonna debba essere il primo nodo, la secoda colonna il nodo figlio e cosi via. Ordinati questo si...


  • User

    Allora provo a fare come dici te, ordino in base ai nodi.

    Quindi sarebbe da ordinare le righe secondo l'ordine delle colonne, in modo tale da avere le righe in successione.

    Ovvero ordinare prima per annoScolastico, poi per Classe e infine per matricola


  • ModSenior

    Si quindi iniziare un nuovo nodo nel momento in cui il nodo successivo non cambia.
    Sembra banale ma credo ci si debba lavorare un pò... 😄


  • User

    Mi sei stato molto d'aiuto...
    Domani mattina provo a buttare giù un pò di codice.


  • ModSenior

    Fai informatica?
    L'ho fatta anche io a mio tempo... 😄
    Magari se hai un pò di codice butta anche qua che se qualcuno passa...
    L'unione fa la forza... 🙂
    Ultima notizia... numero di colonne variabili?


  • User

    Si faccio l'ABACUS a Verona...

    Ovviamente dopo posto tutto. Le colonne possono andare da un minimo di 3 ad un massimo di 15.


  • User Attivo

    La soluzione che ti propongo è di leggere il file CSV, creare un array associativo con la struttura che ti serve (ti basta esplodere la riga e usare key/value che ti servono) e poi fare un dump XML del tutto.

    Qui trovi un esempio di come convertire un hash in un documento XML: h t t p ://stackoverflow.com/questions/99350/php-associative-arrays-to-and-from-xml

    HTH, ciao! 🙂


  • User

    Interessante il link che hai postato, provo a vedere come potrei sfruttarlo.

    Questa mattinata ho concluso questo:

    [PHP]
    function csv2xml($lastTag){
    $myXml = "";
    $csv = $this->openCsv();
    //Suddivido tutto le righe
    $rowCsv = explode("\n", $csv);

        //Suddivido ogni singola riga in un sottoarray
        for($j=0; $j<count($rowCsv); $j++){
        	$rowCsv[$j] = explode(";", $rowCsv[$j]);
        }
        
        //Determino la posizione dell'ultimo tag
        $posLastTag = array_search($lastTag, $rowCsv[0]);
        
        //Analizzo ogni singola riga
        $tagInsert = array();
        for($i=1; $i<count($rowCsv); $i++){
        	//echo "RIGA: $i";
        	for($j=0; $j<count($rowCsv*); $j++){
        		if($j <= $posLastTag and in_array($rowCsv*[$j], $tagInsert) === false){
        			
        			$jump = false;
        			if($i > 1 and $j <= $posLastTag){
        				$jump = true;
        				for($k=$posLastTag; $k >= $j; $k--){
        					//echo "chiudo un TAG (".$tagInsert[$k].") $j<br/><br/>";
        					$myXml .= "</".$tagInsert[$k].">\n\n";
        					$tagInsert[$k] = "";
        				}
        			}
        			if($i > 1 and $jump == false){
        				//echo "chiudo un tag (".$rowCsv[$i-1][$j].")<br/><br/>";
        				$myXml .= "</".$rowCsv[$i-1][$j].">\n\n";
        				unset($tagInsert[array_search($rowCsv[$i-1][$j], $tagInsert)]);
        			}
        			//echo "aggiungo il tag (".$rowCsv*[$j].")<br/><br/>";
        			$tagInsert[$j] = $rowCsv*[$j];
        			$myXml .= "<".$rowCsv*[$j].">\n\n";
        		}
        		if($j > $posLastTag){
        			//echo "Scrivo tag alunno<br/>";
        			$myXml .= "<".trim($rowCsv[0][$j]).">".trim($rowCsv*[$j])."</".trim($rowCsv[0][$j]).">\n";
        		}
        		
        		//print_r($tagInsert);
        		//echo "<br/>";
        	}
        }
        
        return $myXml;
        
    }
    

    [/PHP]

    Il parametro della funzione è l'ultimo nodo necessario, ovvero la matricola nel mio caso.


  • ModSenior

    L'ho trovato anche io quel riferimento ieri. 🙂
    Non mi convince molto però l'xml che ne crea...