PHP: Leggere i File XML


Quante volte ci è capitato di dover fare uno script o un sito, ma l’host del cliente o il nostro non ha i database?

Oppure semplicemente non vogliamo scomodare i database per fare un semplicissimo script!

In questo caso possiamo usare le soluzioni Flat, e cioè quelle che usano file di testo come database.

Abbiamo i vari: TXT, SQLite e XML.

Oggi voglio parlavi degli xml, e per questo motivo ho creato anche una classe gia pronta per voi!


In Anzitutto, per leggere (parsare) un XML, possiamo usare qualche estensione per php tipo la SimpleXML o altre. Ma che succede se il nostro host non le supporta? Non potremo utilizzare neanche gli XML! Però vi basterà parsare l’XML come un semplice file di testo per poterlo utilizzare ovunque!

Come? Con la mia Stupenda Classe PHP che legge gli xml usando le RegEx!

Iniziamo con il codice della classe da salvare(io l’ho chiamato regexml.inc.php):

< ?php
	
/*****************************************************
 *						     RegEXml	 				  *
 *							   by						  *
 *						    Stefano V.					  *
 *					   [email protected]			  *
 *****************************************************/


class RegEXml {
	
	/**
	 * Apre un File
	 *
	 * Apre un File in Lettura e ne Restituisce il Contenuto.
	 *
	 * @author Stefano V. <[email protected]>
	 *
	 * @param string $file Nome del File da Aprire
	 * @return string Contenuto del File
	 */
	
	function get_file($file)
	{
		// azzera la var
		$string = "";
		
		// apre il file in lettura
		$fd = fopen($file, "r");
		
		// se  non si può aprire da errore
		if($fd=="")
			die("Impossibile Aprire il File");
		while (!feof ($fd)) { // legge fino alla fine
			// prende un chunk di 4096 bytes
			$buffer = fgets($fd, 4096);
			
			// aggiunge il chunk alla stringa
			$string.=$buffer;
		}
		
		// chiude il file
		fclose ($fd);
		
		// ritorna il valore
		return $string;
	}
	
	/**
	 * Restituisce un elemento XML
	 *
	 * Restituisce un elemento XML da un file passato come parametro.
	 *
	 * @author Stefano V. <info @svsoftwares.org>
	 *
	 * @param string $tag Nome del Tag XML da cercare
	 * @param string $xml Nome del file XML da processare
	 * @return string Stringa contenente il valore del Tag XML
	 */
	function get_xml_tag($tag, $xml)
	{
		// se l'elemento non esiste, restituisce una stringa vuota
		if (!eregi("(< $tag>|< $tag &#91;^>]+>).*", $xml)) {
			return "";
		}
		
		// in buff vengono tolti i tag di apertura e chiusura
		$buff = ereg_replace(".*(< $tag>|< $tag &#91;^>]+>)", "", $xml);
		$buff = ereg_replace(".*", "", $buff);
		
		// restituisce la stringa
		return $buff;
	}
	
	/**
	 * Restituisce l'array di un ramo di elementi XML
	 *
	 * Restituisce l'array di un ramo di elementi XML da un file passato come parametro.
	 *
	 * @author Stefano V. </info><info @svsoftwares.org>
	 *
	 * @param string $tag Nome del ramo di elementi XML da cercare
	 * @param string $xml Nome del file XML da processare
	 * @return array Array contenente il ramo di elementi XML
	 */
	function get_array_tag($tag, $xml)
	{
		// splitta per 
		$buff = explode("", $xml);
		
		// elimina l'ultimo
		array_splice ($buff, count($buff)-1);
		
		// svuota la var
		$buffelement = "";
		
		// crea un nuovo array
		$newbuff = array();
		
		// per ogni elemento in $buff
		foreach($buff as $buffelement){
			// mette i tag in newbuff
			$newbuff[] = eregi_replace("^.*(\< $tag\>|\< $tag &#91;^>]+\>)","",ltrim($buffelement));
		}
		
		// restituisce l'array
		return $newbuff;
	}
	
	
	
	/**
	 * Restituisce l'attributo di un Tag
	 *
	 * Restituisce il contenuto dell'attributo di un tag
	 *
	 * @author Stefano V. </info><info @svsoftwares.org>
	 *
	 * @param string $tag Nome del ramo di elementi XML da cercare
	 * @param string $attrib Nome dell'attributo da cercare
	 * @param string $xml Nome del file XML da processare
	 * @return string Stringa contenente il contenuto dell'attributo
	 */
	function get_tag_attrib($tag, $attrib, $xml)
	{
		// pattern che ottiene  < - TAG - PROP='VAL' - >
		$diviso = eregi(".*(< )($tag) (&#91;^>]+)(>)", $xml, $reqs);
		
		// ottiene solo la 3a parte
		$attributi = trim($reqs[3]);
		
		// pattern che ottiene: TESTO - $attrib - VAL - TESTO
		$attributo = eregi("(.*)($attrib=)(\"[^\"]+\"|'[^']+')(.*)",$attributi, $req);
		
		// prende solo la 2a e 3a parte trimmando
		$attributo = trim($req[2].$req[3]);
		
		// splitta per " o '
		$final = spliti("(\"|')",$attributo);
		
		// restituisce l'array 1
		return $final[1];
	}
	
	
	/**
	 * Restituisce un Array di Attributi
	 *
	 * Restituisce un Array contenente gli Attributi del Tag e i Relativi Valori
	 *
	 * @author Stefano V. </info><info @svsoftwares.org>
	 *
	 * @param string $tag Nome del ramo di elementi XML da cercare
	 * @param string $xml Nome del file XML da processare
	 * @return array Array contenente gli attributi del tag con relative proprietà
	 */
	function get_array_attrib($tag, $xml)
	{
		// pattern che ottiene tra <tag e >
		$diviso = eregi(".*< $tag(&#91;^>|^/>]+)(/>|>)", $xml, $reqs);
		
		// prende solo la prima occorrenza
		$attributi = trim($reqs[1]);
		
		// pattern che ottiene un array con tutti i: PROP = "VAL"
		$finale = preg_match_all("#([^=]+)=[\"|']([^\"|^']*)[\"|']#", $attributi, $arry);
		
		// conta il numero di elementi
		$ca = count($arry[1]);
		
		// per ogni elemento trovato
		for($i=0; $i< $ca; $i++)
		{
			// aggiunge all'array finale un array in coda formato da &#91;PROP&#93; => VAL
			$array_finale[$arry[1][$i]] = $arry[2][$i];
		}
		
		// restituisce il valore
		return $array_finale;
	}
	
}	
?>

Ora, prendiamo un esempio di file xml (lo chiameremo messaggi.xml) e dentro ci mettiamo il codice xml, in questo caso:

<chat>
	<messaggio>
		<autore>StefanoV</autore>
		<testo>Prova Messaggio 1</testo>
	</messaggio>
	<tag attributo="prop rietà" spazio=" " altro='proprie tà2' tab="	" prop_rietà='valore' vuoto='' />
	<messaggio>
		<autore>StefanoV</autore>
		<testo>Prova Messaggio 2</testo>
	</messaggio>
</chat>

Ora passiamo alla spiegazione su come usare la classe!

Tag XML Supportati:
<tag>contenuto</tag>   <– Tag con Contenuto
<tag attributo=”proprietà”>contenuto</tag>   <– Tag con Contenuto e Attributo
<tag attributo=”proprietà” />   <– Tag Autochiudente con Attributo

Ecco il codice:

include ‘libs/regexml.inc.php’; // includo la classe (io l’ho messa in una cartella chiamata libs)

$xml_c = new RegEXml; // la variabile valorizzata

$fd = $xml_c->get_file(“messaggi.xml”); // leggo l’xml come un file di testo

$chat = $xml_c->get_xml_tag(“chat”,$fd); // ottengo il contenuto del tag <chat>

$messaggi = $xml_c->get_array_tag(“messaggio”,$chat); // Ottengo in un Array tutti i contenuti dei tag <messaggio>

// (con count($messaggi) possiamo contare il numero di messaggi ovviamente, essendo un array)

foreach($messaggi as $messaggio) // ciclo il contenuto dei messaggi
{
// ottengo il contenuto dei tag <autore> e <testo> di ogni messaggio
$autore = $xml_c->get_xml_tag(“autore”,$messaggio);
$testo = $xml_c->get_xml_tag(“testo”,$messaggio);

// stampo i dati se voglio
print(“Autore: “.$autore.”<br/>Messaggio: “.$testo.”<br/><br/>”);
}

Ora, come facciamo ad ottenere il valore di un attributo di un tag (ovviamente il tag deve essere univoco)? Basta scrivere:

$xml_c->get_tag_attrib(“tag”, “attributo”, $chat); // tag è il nome del tag,attributo è il nome della proprietà, $chat è la risorsa dove andrà a cercare, cioè nel tag chat dell’xml aperto.

E se invece volessimo ottenere in un array tutte le le proprietà (attributi) di un tag? Scriveremo:

$aa = $xml_c->get_array_attrib(“tag”, $chat); // tag è il nome del tag, e $chat come prima è la risorsa.

// con count($aa) possiamo contare gli attributi come un normale array e con un foreach estrapoliamo i dati

Tutti i File della Guida sono Scaricabili da questo Link: SCARICA FILE

Alla Prossima! 😉



14 Commenti

  1. Livio ha detto:

    già fatto 😀

  2. Livio ha detto:

    Ciao, volevo chiederti, se invece ho un file xml con dentro un oggetto cdata come faccio a prendere il testo ?

    Ciao e grazie mille per il tuo lavoro

  3. StefanoV ha detto:

    Mandami una mail a info sv-design org 😉

  4. Livio ha detto:

    Niente, lo cancella in ogni caso…

  5. StefanoV ha detto:

    Ciao Livio, purtroppo wordpress ha tolto tagliato la frase, prova a scrivere il tag diversamente … tipo mettendo le parentesi tonde al posto delle angolari…

  6. StefanoV ha detto:

    Ah mi fa piacere trovare un compaesano programmatore 😉

  7. Ivan ha detto:

    Minime distrazioni che possono capitare.. e poi se non ci si da una mano tra sviluppatori ( e tra calabresi ) che brutto lavoro sarebbe.. sicuramente lo avresti trovato anche te l'errore, anzi la distrazione!

  8. StefanoV ha detto:

    Ops allora mi scuso per la disattenzione, avrò corretto successivamente la funzione nel file, e mi sarò dimenticato di aggiornare il codice scritto nel post. Grazie per avermi preceduto Ivan 😉

  9. Ivan ha detto:

    no ho capito .. in poche parole nel codice di esempio che fai scaricare la funzione è corretta mentre nella pagina qui sopra hai scritto $buff = explode("", $xml);

    ( che è errato ). Me ne sono accorto perchè per fare dei test ho fatto la copia del codice che c'è qui nella pagina poi dopo ho scaricato la classe per vedere se effettivamente funzionava. cmq è li l'errore. 🙂

    p.s. ottimo lavoro cmq complimenti!!

  10. StefanoV ha detto:

    Come ho risposto a franca: vorrei vedere il vostro codice, cosi da capire dove sta l'errore… se potreste inviarmelo per email provvederei subito a controllare (PHP e XML) 😉

  11. Ivan ha detto:

    Ciao ho provato a utilizzare la tua classe ma mi da lo stesso problema che indica la ragazza nel posto precedente al mio.. array_tag non funge.. come mai?

  12. StefanoV ha detto:

    Ciao, puoi inviarmi il codice via email, cosi controllo se ci sono errori nel mio codice, o se sbagli qualcosa tu? 😉

  13. franca ha detto:

    scusami ma se un tag non è univoco (ho una serie di elementi con lo stesso tag) perchè non riesco a scorrerli come un array ed a leggere i loro attributi?

    inoltre il get:array_tag non funziona quando il mio tag non è nella forma content ma … la funzione non fa l'explode corretto 🙁

Lascia un commento a StefanoV

%d blogger hanno fatto clic su Mi Piace per questo: