Analizzare XML significa essenzialmente passare attraverso un documento XML e restituire i dati corrispondenti. E sebbene tutto Di più i servizi Web restituiscono i dati in formato JSON, ma la maggior parte utilizza ancora XML, quindi è importante padroneggiarli Analisi XML se desideri utilizzare l'intera gamma di API disponibili.
Utilizzando l'estensione SimpleXML in PHP, che è stato aggiunto in PHP 5.0, lavorare con XML è molto facile e semplice. In questo articolo, ti mostrerò come farlo.
Iniziamo con il seguente esempio lingue.xml:
>
>
>
>
Questo documento XML contiene un elenco di linguaggi di programmazione con alcune informazioni su ogni linguaggio: l'anno della sua implementazione e il nome del suo creatore.
Il primo passaggio consiste nel caricare l'XML utilizzando le funzioni simplexml_load_file(), O simplexml_load_string(). Come suggerisce il nome delle funzioni, la prima caricherà XML da un file e la seconda caricherà XML da una stringa.
Entrambe le funzioni leggono l'intero albero DOM in memoria e restituiscono un oggetto SimpleXMLElement. Nell'esempio sopra, l'oggetto è memorizzato nella variabile $languages. Puoi usare le funzioni var_dump() O stampa_r() per ottenere informazioni dettagliate sull'oggetto restituito, se lo desideri.
Oggetto SimpleXMLElement
[lang] => matrice
[ 0 ] => SimpleXMLElementObject
[@attributes] => Array
[nome] => c
[apparso] => 1972
[ creatore] => Dennis Ritchie
[ 1 ] => Oggetto SimpleXMLElement
[@attributes] => Array
[nome] => PHP
[apparso] => 1995
[ creatore] => Rasmus Lerdorf
[ 2 ] => Oggetto SimpleXMLElement
[@attributes] => Array
[nome] => Java
[apparso] => 1995
[ creatore] => James Gosling
)
)
Questo XML contiene l'elemento radice le lingue, che contiene tre elementi lang. Ogni elemento dell'array corrisponde a un elemento lingua in un documento XML.
È possibile accedere alle proprietà di un oggetto utilizzando l'operatore -> . Ad esempio, $languages->lang ti restituirà un oggetto SimpleXMLElement che corrisponde al primo elemento lingua. Questo oggetto contiene due proprietà: apparso e creatore.
$languages -> lang [ 0 ] -> apparso ;
$lingue -> lingua [ 0 ] -> creatore ;
Visualizzare un elenco di lingue e visualizzarne le proprietà è molto semplice con un ciclo standard come per ciascuno.
foreach ($lingue -> lang come $lang ) (
stampaf (
""
,
$lang["nome"] ,
$lang -> apparso,
$lang -> creatore
)
;
}
Si noti come ho effettuato l'accesso al nome dell'attributo dell'elemento lang per ottenere il nome della lingua. In questo modo è possibile accedere a qualsiasi attributo di un elemento rappresentato come oggetto SimpleXMLElement.
Mentre lavori con l'XML di vari servizi Web, incontrerai spesso spazi dei nomi degli elementi. Cambiamo il nostro lingue.xml per mostrare un esempio di utilizzo di uno spazio dei nomi:
xmlns:dc =>
>
>
>
Ora elemento Creatore collocato nello spazio dei nomi dc, che rimanda a http://purl.org/dc/elements/1.1/. Se provi a stampare i creatori di lingua utilizzando il nostro codice precedente, non funzionerà. Per leggere gli spazi dei nomi degli elementi è necessario utilizzare uno dei seguenti approcci.
Il primo approccio consiste nell'utilizzare i nomi URI direttamente nel codice quando si fa riferimento allo spazio dei nomi dell'elemento. L'esempio seguente mostra come questo è fatto:
$dc = $lingue -> lingua [ 1 ] -> bambini( "http://purl.org/dc/elements/1.1/")
;
echo $dc -> creatore ;
Metodo bambini() accetta uno spazio dei nomi e restituisce elementi figlio che iniziano con un prefisso. Richiede due argomenti, il primo è lo spazio dei nomi XML e il secondo è un argomento facoltativo impostato per impostazione predefinita falso. Se il secondo argomento è impostato su TRUE, lo spazio dei nomi verrà trattato come un prefisso. Se FALSE, lo spazio dei nomi verrà trattato come lo spazio dei nomi dell'URL.
Il secondo approccio consiste nel leggere i nomi URI dal documento e utilizzarli quando si fa riferimento allo spazio dei nomi dell'elemento. Questo è in realtà il modo migliore per accedere agli elementi perché non è necessario essere codificati in un URI.
$namespaces = $languages -> getNamespaces (true);
$dc = $lingue -> lang [ 1 ] -> bambini ($namespaces [ "dc" ] );
echo $dc -> creatore ;
Metodo OttieniSpazi dei nomi() restituisce un array di nomi di prefissi e i relativi URI associati. Richiede un parametro aggiuntivo che per impostazione predefinita è falso. Se lo installi come VERO, questo metodo restituirà i nomi utilizzati nei nodi padre e figlio. In caso contrario, trova gli spazi dei nomi utilizzati solo nel nodo padre.
Ora puoi scorrere l'elenco delle lingue in questo modo:
$lingue = simplexml_load_file ("lingue.xml" );
$ns = $lingue -> getNamespaces (true);
foreach ($lingue -> lang come $lang ) (
$dc = $lang -> figli ($ns [ "dc" ] ) ;
stampaf (
"
%s è apparso in %d ed è stato creato da %s .
" ,Diamo un'occhiata a un esempio che riceve un feed RSS da Canale Youtube e visualizza i collegamenti a tutti i video da esso. Per fare ciò, si prega di contattare il seguente indirizzo:
http://gdata.youtube.com/feeds/api/users/xxx/uploads
L'URL restituisce un elenco degli ultimi video del canale specificato in formato XML. Analizzeremo l'XML e otterremo le seguenti informazioni per ogni video:
Inizieremo cercando e caricando l'XML:
$canale = "NomeCanale" ;
$url = "http://gdata.youtube.com/feeds/api/users/". $canale. "/upload" ;
$xml = file_get_contents ($url);
$feed = simplexml_load_string ($xml);
$ns = $feed -> getNameSpaces (true );
Se guardi il feed XML, puoi vedere che ci sono diversi elementi lì. entità, ognuno dei quali memorizza informazioni dettagliate su un video specifico del canale. Ma utilizziamo solo le miniature delle immagini, l'indirizzo e il titolo del video. Questi tre elementi sono figli dell'elemento gruppo, che a sua volta è figlio di iscrizione:
…
…
…
>
…
Esamineremo solo tutti gli elementi iscrizione ed estrarre le informazioni necessarie per ciascuno di essi. notare che giocatore, miniatura E titolo sono nello spazio dei nomi del supporto. Quindi, dobbiamo procedere come nell'esempio precedente. Otteniamo i nomi dal documento e utilizziamo lo spazio dei nomi quando ci riferiamo agli elementi.
foreach ($feed -> voce come $voce ) (
$gruppo = $entry -> bambini ($ns [ "media" ] ) ;
$gruppo = $gruppo -> gruppo ;
$thumbnail_attrs = $group -> miniatura [ 1 ] -> attributi ();
$image = $thumbnail_attrs ["url"] ;
$giocatore = $gruppo -> giocatore -> attributi ();
$link = $giocatore["url"] ;
$titolo = $gruppo -> titolo ;
stampaf ( ""
,
$giocatore, $immagine, $titolo);
}
Ora che sai come usare SimpleXML per analizzare i dati XML, puoi migliorare le tue abilità analizzando diversi feed XML con diverse API. Ma è importante tenere presente che SimpleXML legge l'intero DOM in memoria, quindi se stai analizzando un set di dati di grandi dimensioni, potresti esaurire la memoria. Per saperne di più su SimpleXML leggi la documentazione.
In caso di domande, utilizzare il nostro
Extensible Markup Language XML è un insieme di regole per codificare i documenti in una forma leggibile dalla macchina. XML è un formato popolare per lo scambio di dati su Internet. I siti che aggiornano frequentemente il proprio contenuto, come siti di notizie o blog, spesso forniscono un feed XML in modo che i programmi esterni siano a conoscenza delle modifiche al contenuto. L'invio e l'analisi dei dati XML è un'attività comune per le applicazioni con una connessione di rete. Questa lezione spiega come analizzare i documenti XML e utilizzarne i dati.
Il primo passo nell'analisi di un feed è decidere a quali campi di dati sei interessato. Il parser estrae i campi dati e ignora tutto il resto.
Ecco lo snippet del canale che verrà analizzato nell'applicazione di esempio. Ogni post su StackOverflow.com appare nel feed come tag di ingresso, che contiene diversi tag nidificati:
Ho un'applicazione che richiede un file di dati...
L'applicazione di esempio recupera i dati dal tag entry e dai relativi tag secondari title, link e summary.
Il passaggio successivo consiste nell'istanziare il parser e avviare il processo di analisi. In questo frammento, il parser viene inizializzato per non gestire gli spazi dei nomi e anche per utilizzare l'InputStream fornito come input. Il processo di parsing viene avviato con una chiamata a nextTag() e chiama il metodo readFeed(), che recupera ed elabora i dati a cui l'applicazione è interessata:
Public class StackOverflowXmlParser ( // Non usiamo namespace private static final String ns = null; public List parse(InputStream in) genera XmlPullParserException, IOException ( try ( XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES , false); parser.setInput(in, null); parser.nextTag(); return readFeed(parser); ) finally ( in.close(); ) ) ... )
Il metodo readFeed() esegue l'effettivo lavoro di elaborazione del feed. Gli elementi contrassegnati con il tag "entry" sono il punto di partenza per l'elaborazione ricorsiva del canale. Se il tag successivo non è un tag di ingresso, viene saltato. Dopo che l'intero "feed" è stato elaborato in modo ricorsivo, readFeed() restituisce un elenco contenente le voci (compresi gli elementi di dati nidificati) recuperate dal feed. Questo elenco viene quindi restituito dal parser.
Elenco privato readFeed(XmlPullParser parser) genera XmlPullParserException, IOException ( Voci elenco = new ArrayList (); parser.require(XmlPullParser.START_TAG, ns, "feed"); while (parser.next() != XmlPullParser.END_TAG) ( se (parser.getEventType() != XmlPullParser.START_TAG) ( continue; ) String name = parser.getName(); // Inizia cercando il tag di ingresso if (name.equals("entry")) ( entries.add( readEntry(parser)); ) else ( skip(parser); ) ) restituisce voci; )
I passaggi per analizzare il feed XML sono i seguenti:
Questo frammento mostra come il parser analizza la voce, il titolo, il collegamento e il riepilogo.
Classe statica pubblica Entry ( public final String title; public final String link; public final String summary; private Entry(String title, String summary, String link) ( this.title = title; this.summary = summary; this.link = link ; ) ) // Analizza il contenuto di una voce. Se incontra un titolo, un sommario o un tag di collegamento, passali // ai rispettivi metodi di "lettura" per l'elaborazione. Altrimenti, salta il tag. private Entry readEntry(XmlPullParser parser) genera XmlPullParserException, IOException ( parser.require(XmlPullParser.START_TAG, ns, "entry"); String title = null; String summary = null; String link = null; while (parser.next() ! = XmlPullParser.END_TAG) ( if (parser.getEventType() != XmlPullParser.START_TAG) ( continue; ) String name = parser.getName(); if (name.equals("title")) ( title = readTitle(parser) ; ) else if (name.equals("summary")) ( summary = readSummary(parser); ) else if (name.equals("link")) ( link = readLink(parser); ) else ( skip(parser) ; ) ) return new Entry(title, summary, link); ) // Processa i title tag nel feed. private String readTitle(XmlPullParser parser) genera IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "title"); String title = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "title"); return title; ) // Elabora i tag di collegamento nel feed. private String readLink(XmlPullParser parser) genera IOException, XmlPullParserException ( String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); String relType = parser.getAttributeValue(null , "rel"); if (tag.equals("link")) ( if (relType.equals("alternate"))( link = parser.getAttributeValue(null, "href"); parser.nextTag(); ) ) parser.require(XmlPullParser.END_TAG, ns, "link"); link di ritorno; ) // Elabora i tag di riepilogo nel feed. private String readSummary(XmlPullParser parser) genera IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "summary"); String summary = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "summary"); return summary; ) // Per i tag title e summary, estrae i loro valori di testo. private String readText(XmlPullParser parser) genera IOException, XmlPullParserException ( String result = ""; if (parser.next() == XmlPullParser.TEXT) ( result = parser.getText(); parser.nextTag(); ) return result; ) ... )
In uno dei passaggi di analisi XML sopra descritti, il parser salta i tag che non ci interessano. Di seguito è riportato il codice del parser per il metodo skip():
Private void skip(XmlPullParser parser) genera XmlPullParserException, IOException ( if (parser.getEventType() != XmlPullParser.START_TAG) ( lancia new IllegalStateException(); ) int depth = 1; while (depth != 0) ( switch (parser. next()) ( case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; ) ) )
Ecco come funziona:
Pertanto, se l'elemento corrente ha elementi nidificati, la profondità non sarà 0 fino a quando il parser non avrà elaborato tutti gli eventi tra l'START_TAG originale e il corrispondente END_TAG . Ad esempio, considera come salta il parser
L'applicazione di esempio riceve e analizza il feed XML in un AsyncTask . L'elaborazione viene eseguita al di fuori del thread dell'interfaccia utente principale. Al termine dell'elaborazione, l'applicazione aggiorna l'interfaccia utente nell'attività principale (NetworkActivity).
Nello snippet seguente, il metodo loadPage() esegue le seguenti operazioni:
Di seguito è riportato il metodo loadXmlFromNetwork() che viene chiamato da DownloadXmlTask . Fa quanto segue:
" + voce.titolo + "
"); // Se l'utente imposta la preferenza per includere il testo di riepilogo, // lo aggiunge al display. if (pref) ( htmlString.append(entry.summary); ) ) return htmlString.toString(); ) // Data una rappresentazione di stringa di un URL, imposta una connessione e ottiene // un input stream.private InputStream downloadUrl(String urlString) genera IOException ( URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection() ; conn.setReadTimeout(10000 /* millisecondi */); conn.setConnectTimeout(15000 /* millisecondi */); conn.setRequestMethod("GET"); conn.setDoInput(true); // Avvia la query conn.connect( ); return conn.getInputStream(); )In questo articolo, mostrerò un esempio di come analizzare un file XML di grandi dimensioni. Se al tuo server (hosting) non è vietato aumentare il tempo di esecuzione dello script, puoi analizzare un file XML del peso di almeno gigabyte, io personalmente ho analizzato solo file da ozone del peso di 450 megabyte.
Esistono due problemi durante l'analisi di file XML di grandi dimensioni:
1. Memoria insufficiente.
2. Il tempo allocato non è sufficiente per il funzionamento dello script.
Il secondo problema con il tempo può essere risolto se questo non è proibito dal server.
Ma il problema con la memoria è difficile da risolvere, anche se parliamo del tuo server, quindi spostare file da 500 megabyte non è molto semplice, e anche su hosting e su VDS semplicemente non puoi aumentare la memoria.
PHP ha diverse opzioni di elaborazione XML integrate: SimpleXML, DOM, SAX.
Tutte queste opzioni sono dettagliate in molti articoli di esempio, ma tutti gli esempi mostrano come lavorare con un documento XML completo.
Ecco un esempio, otteniamo un oggetto da un file XML
$xml = simplexml_load_file ("1.xml" ); ?>
Ora puoi elaborare questo oggetto, MA...
Come puoi vedere, l'intero file XML viene letto in memoria, quindi tutto viene analizzato in un oggetto.
Cioè, tutti i dati entrano in memoria e se la memoria allocata non è sufficiente, lo script si interrompe.
Questa opzione non è adatta per l'elaborazione di file di grandi dimensioni, è necessario leggere il file riga per riga ed elaborare questi dati a turno.
Allo stesso tempo, viene effettuato anche il controllo di validità man mano che i dati vengono elaborati, quindi è necessario poter eseguire il rollback, ad esempio, eliminare tutto il database inserito nel caso di un file XML non valido, oppure effettuare due passa attraverso il file, prima letto per la validità, quindi letto per l'elaborazione dei dati.
Ecco un esempio teorico di analisi di un file XML di grandi dimensioni.
Questo script legge un carattere da un file, raccoglie questi dati in blocchi e li invia al parser XML.
Questo approccio risolve completamente il problema della memoria e non causa un carico, ma aggrava il problema nel tempo. Come provare a risolvere il problema nel tempo, leggi sotto.
Funzione webi_xml($file)
{
########
### funzione di gestione dei dati
{
stampa $dati ;
}
############################################
{
print $nome ;
print_r($attrs);
}
## funzione tag di chiusura
funzione endElement ($parser, $nome)
{
print $nome ;
}
############################################
($xml_parser, "dati");
// apri il file
$fp = fopen($file , "r" );
$perviy_vxod = 1 ; $dati = "" ;
{
$simvol = fgetc($fp); $dati .= $simvol ;
if($simvol != ">" ) ( continua;)
"
);
$perviy_vxod
=
0
;}
eco "
rottura;
}
$dati = "" ;
}
fchiudi($fp);
webi_xml("1.xml");
?>
In questo esempio, inserisco tutto in una funzione webi_xml () e la sua chiamata è visibile in fondo.
Lo script stesso è costituito da tre funzioni principali:
1. Una funzione che intercetta l'apertura del tag startElement()
2. Una funzione che rileva la chiusura del tag endElement()
3. E la funzione di ricezione dei dati data() .
Supponiamo che il contenuto del file 1.xml sia una ricetta
<
title
>pane semplice
title
>
<
ingredient amount
=
"3"
unit
=
"стакан"
>Farina
ingredient
>
<
ingredient amount
=
"0.25"
unit
=
"грамм"
>Lievito
ingredient
>
<
ingredient amount
=
"1.5"
unit
=
"стакан"
>acqua calda
ingredient
>
<
ingredient amount
=
"1"
unit
=
"чайная ложка"
>Sale
ingredient
>
<
instructions
>
<
step
>
Mescolare tutti gli ingredienti e impastare bene.
step
>
<
step
>
Coprire con un panno e lasciare per un'ora in una stanza calda.
step
>
<
step
>
Impastare di nuovo,
mettere su una teglia e mettere in forno.
step
>
<
step
>
Visita il sito del sito
step
>
instructions
>
recipe
>
Iniziamo chiamando la funzione generica webi_xml("1.xml");
Inoltre in questa funzione, il parser si avvia e tutti i nomi dei tag vengono tradotti in maiuscolo in modo che tutti i tag abbiano lo stesso caso.
$xml_parser = xml_parser_create();
xml_parser_set_option ($xml_parser, XML_OPTION_CASE_FOLDING, vero);
Ora specifichiamo quali funzioni lavoreranno per rilevare l'apertura del tag, la chiusura e l'elaborazione dei dati
xml_set_element_handler($xml_parser , "startElement" , "endElement" );
xml_set_character_data_handler($xml_parser, "dati");
Segue l'apertura del file specificato, itera sul file un carattere alla volta e ogni carattere viene aggiunto alla variabile stringa finché non viene trovato il carattere >
.
Se questo è il primo vero accesso al file, tutto ciò che è superfluo all'inizio del file verrà eliminato lungo il percorso, tutto ciò che sta prima
, questo è il tag con cui dovrebbe iniziare XML.
La prima volta che una variabile stringa raccoglierà una stringa
E invialo al parser
xml_parse ($xml_parser, $dati, feof ($fp));
Dopo aver elaborato i dati, la variabile stringa viene reimpostata e la raccolta dei dati in una stringa ricomincia e viene formata una stringa per la seconda volta
Nel terzo
nel quarto
pane semplice
Si noti che la variabile stringa è sempre formata dal tag completato >
e non è necessario inviare tag aperti e chiusi con dati al decompositore, ad esempio
È importante per questo gestore ottenere un intero tag ininterrotto, almeno un tag aperto e nel passaggio successivo un tag chiuso, o ottenere immediatamente 1000 righe del file, non importa, l'importante è che il tag non si rompe, per esempio
le>Pane semplice
Quindi è impossibile inviare i dati al gestore, perché il tag è rotto.
Puoi trovare il tuo metodo per inviare i dati al gestore, ad esempio raccogliere 1 megabyte di dati e inviarlo al gestore per aumentare la velocità, assicurati solo che i tag finiscano sempre e che i dati possano essere interrotti
pane
Quindi, in parti, come desideri, puoi inviare file grande al gestore.
Ora diamo un'occhiata a come vengono elaborati questi dati e come ottenerli.
A partire dalla funzione dei tag di apertura startElement ($ parser , $name , $attrs )
Supponiamo che l'elaborazione abbia raggiunto la linea
<
ingredient amount
=
"3"
unit
=
"стакан"
>Farina
ingredient
>
Quindi all'interno della funzione la variabile $name sarà uguale a ingrediente ovvero il nome del tag aperto (l'argomento non è ancora arrivato alla chiusura del tag).
Anche in questo caso sarà disponibile un array di attributi di questo tag $attrs, in cui ci saranno dati importo = "3" e unità = "vetro".
Successivamente, i dati del tag aperto sono stati elaborati dalla funzione dati ($parser, $dati)
La variabile $data conterrà tutto quello che c'è tra il tag di apertura e quello di chiusura, nel nostro caso è il testo Muk
E l'elaborazione della nostra stringa da parte della funzione è completata endElement ($parser, $nome)
Questo è il nome del tag chiuso, nel nostro caso $name sarà uguale a ingrediente
E dopo, tutto è tornato al punto di partenza.
L'esempio precedente dimostra solo il principio dell'elaborazione XML, ma per un'applicazione reale deve essere finalizzato.
Di solito, devi analizzare XML di grandi dimensioni per inserire dati nel database e, per una corretta elaborazione dei dati, devi sapere a quale tag aperto appartengono i dati, a quale livello di annidamento dei tag e quali tag sono aperti nella gerarchia sopra. Con queste informazioni, è possibile elaborare correttamente il file senza problemi.
Per fare ciò, è necessario introdurre diverse variabili globali che raccolgono informazioni su tag aperti, nidificazione e dati.
Ecco un esempio che può essere utilizzato
Funzione webi_xml($file)
{
globale $ webi_depth ; // contatore per tenere traccia della profondità di annidamento
$webi_profondità = 0;
globale $ webi_tag_open ; // conterrà un array di open in questo momento tag
$webi_tag_open = array();
globale $ webi_data_temp ; // questo array conterrà i dati di un tag
####################################################
### funzione di gestione dei dati
funzione dati ($ parser , $ data )
{
globale $ webi_depth ;
globale $ webi_tag_open ;
globale $ webi_data_temp ;
// aggiunge dati all'array con annidamento e tag attualmente aperto
$webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "data" ].= $data ;
}
############################################
####################################################
### funzione tag di apertura
funzione startElement ($ parser , $name , $attrs )
{
globale $ webi_depth ;
globale $ webi_tag_open ;
globale $ webi_data_temp ;
// se il livello di annidamento non è già zero, allora un tag è già aperto
// e i dati da esso sono già nell'array, puoi elaborarli
se ($ webi_depth)
{
"
;
stampa"
"
;
print_r($webi_tag_open); // array di tag aperti
stampa"
// dopo aver elaborato i dati, cancellali per liberare memoria
unset($GLOBALS [ "webi_data_temp" ][ $webi_depth ]);
}
// ora l'apertura del tag successivo è iniziata e l'ulteriore elaborazione avverrà nel passaggio successivo
$webi_profondità++; // aumenta l'annidamento
$webi_tag_open [$webi_depth]= $nome; // aggiunge tag aperto all'array info
$webi_data_temp [ $webi_depth ][ $name ][ "attrs" ]= $attrs ; // ora aggiungi gli attributi del tag
}
###############################################
#################################################
## funzione tag di chiusura
funzione endElement ($ parser , $ nome ) (
globale $ webi_depth ;
globale $ webi_tag_open ;
globale $ webi_data_temp ;
// l'elaborazione dei dati inizia qui, ad esempio, l'aggiunta al database, il salvataggio in un file, ecc.
// $webi_tag_open contiene una catena di tag aperti per livello di nidificazione
// ad esempio $webi_tag_open[$webi_depth] contiene il nome del tag aperto le cui informazioni sono attualmente in fase di elaborazione
// Livello di nidificazione tag $webi_depth
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["attrs"] array di attributi di tag
// $webi_data_temp[$webi_depth][$webi_tag_open[$webi_depth]]["data"] dati dei tag
Stampa "dati". $webi_tag_open [ $webi_depth ]. "--" .($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "dati" ]). "
"
;
print_r ($webi_data_temp [ $webi_depth ][ $webi_tag_open [ $webi_depth ]][ "attrs" ]);
stampa"
"
;
print_r($webi_tag_open);
stampa"
Unset($GLOBALS [ "webi_data_temp" ]); // dopo aver elaborato i dati, cancella l'array con i dati nel loro insieme, poiché il tag è stato chiuso
unset($GLOBALS [ "webi_tag_open" ][ $webi_depth ]); // rimuove le informazioni su questo tag aperto... poiché è stato chiuso
$webi_profondità --; // riduce l'annidamento
}
############################################
$xml_parser = xml_parser_create();
xml_parser_set_option ($xml_parser, XML_OPTION_CASE_FOLDING, vero);
// specifica quali funzioni funzioneranno durante l'apertura e la chiusura dei tag
xml_set_element_handler($xml_parser , "startElement" , "endElement" );
// specifica una funzione per lavorare con i dati
xml_set_character_data_handler($xml_parser, "dati");
// apri il file
$fp = fopen($file , "r" );
$perviy_vxod = 1 ; // flag per il controllo del primo input nel file
$dati = "" ; // qui raccogliamo parti dei dati dal file e li inviamo al parser xml
// ciclo fino alla fine del file trovato
while (! feof ($fp ) e $fp )
{
$simvol = fgetc($fp); // legge un carattere dal file
$dati .= $simvol ; // aggiunge questo carattere ai dati da inviare
// se il carattere non è il tag di fine, torna all'inizio del ciclo e aggiungi un altro carattere ai dati, e così via finché non viene trovato il tag di fine
if($simvol != ">" ) ( continua;)
// se è stato trovato il tag di chiusura, ora invia questi dati raccolti all'elaborazione
// controlla se questa è la prima voce nel file, quindi cancella tutto prima del tag
// poiché a volte potrebbero esserci dei rifiuti prima dell'inizio dell'XML (editor goffi o il file è stato ricevuto dallo script da un altro server)
if($perviy_vxod ) ( $dati = strstr ($dati , ""
);
$perviy_vxod
=
0
;}
// ora inseriamo i dati nel parser xml
if (! xml_parse ($xml_parser , $data , feof ($fp ))) (
// qui puoi elaborare e ottenere errori per la validità...
// non appena si verifica un errore, l'analisi si interrompe
eco "
Errore XML: " .xml_error_string (xml_get_error_code ($xml_parser ));
echo "alla linea" . xml_get_current_line_number($xml_parser );
rottura;
}
// dopo l'analisi, eliminiamo i dati raccolti per il passaggio successivo del ciclo.
$dati = "" ;
}
fchiudi($fp);
xml_parser_free($xml_parser );
// elimina le variabili globali
unset($GLOBALS [ "webi_depth" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);
webi_xml("1.xml");
?>
L'intero esempio è stato accompagnato da commenti, ora prova e sperimenta.
Si noti che nella funzione di manipolazione dei dati, i dati non vengono semplicemente inseriti nell'array, ma vengono aggiunti utilizzando " .="
poiché i dati potrebbero non presentarsi in una forma completa e se esegui solo un incarico, di volta in volta riceverai i dati in blocchi.
Bene, questo è tutto, ora ci sarà memoria sufficiente durante l'elaborazione di un file di qualsiasi dimensione, ma il tempo di esecuzione dello script può essere aumentato in diversi modi.
Inserisci una funzione all'inizio dello script
set_time_limit(6000);
O
ini_set("tempo_max_esecuzione" , "6000" );
Oppure aggiungi del testo al file .htaccess
php_value max_execution_time 6000
Questi esempi aumenteranno il tempo di esecuzione dello script a 6000 secondi.
È possibile aumentare il tempo in questo modo solo in modalità provvisoria.
Se hai accesso alla modifica di php.ini puoi aumentare il tempo con
max_execution_time = 6000
Ad esempio, sull'hosting masterhost, al momento della stesura di questo documento, è vietato aumentare il tempo di script, nonostante sia disabilitato modalità sicura, ma se sei un professionista, puoi creare il tuo php sul masterhost, ma questo non è in questo articolo.
Ora studieremo come lavorare con XML. XML è un formato per lo scambio di dati tra siti. È molto simile all'HTML, solo XML consente i propri tag e attributi.
Perché XML è necessario per l'analisi? A volte capita che il sito che devi analizzare abbia un'API che ti permetta di ottenere ciò che desideri senza troppi sforzi. Pertanto, consiglio immediatamente: prima di analizzare il sito, controlla se ha un'API.
Cos'è un'API? Si tratta di un insieme di funzioni con le quali è possibile inviare una richiesta a questo sito ed ottenere la risposta desiderata. Questa risposta arriva molto spesso in formato XML. Quindi iniziamo a studiarlo.
Diciamo che hai XML. Può trovarsi in una stringa, memorizzato in un file o offerto su richiesta a un URL specifico.
Lascia che l'XML sia memorizzato in una stringa. In questo caso, è necessario creare un oggetto da questa linea utilizzando nuovo SimpleXMLElement:
$str = "
Ora abbiamo in una variabile $xml viene memorizzato un oggetto con XML analizzato. Accedendo alle proprietà di questo oggetto è possibile accedere al contenuto dei tag XML. Come esattamente - analizzeremo un po 'più in basso.
Se l'XML è memorizzato in un file o restituito accedendo a un URL (che è il caso più frequente), allora dovresti usare la funzione simplexml_load_file che fa lo stesso oggetto $xml:
$xml = simplexml_load_file(percorso file o url);
Negli esempi seguenti, il nostro XML è memorizzato in un file o in un URL.
Sia dato il seguente XML:
Prendiamo il nome, l'età e lo stipendio di un dipendente:
$xml = simplexml_load_file(percorso file o url); echo $xml->nome; //visualizza "Kolya" echo $xml->età; //emette 25 echo $xml->stipendio; // restituisce 1000
Come puoi vedere, l'oggetto $xml ha proprietà corrispondenti ai tag.
Potresti aver notato che il tag
$xml = simplexml_load_file(percorso file o url); echo $xml->nome; //visualizza "Kolya" echo $xml->età; //emette 25 echo $xml->stipendio; // restituisce 1000
Può esserci un solo tag root in XML, proprio come il tag root in semplice HTML.
Modifichiamo un po' il nostro XML:
In questo caso, otteniamo una catena di chiamate:
$xml = simplexml_load_file(percorso file o url); echo $xml->lavoratore->nome; //visualizza "Kolya" echo $xml->lavoratore->età; //output 25 echo $xml->lavoratore->salario; // restituisce 1000
Lascia che alcuni dati vengano memorizzati negli attributi:
$xml = simplexml_load_file(percorso file o url); echo $xml->lavoratore["nome"]; //visualizza "Kolya" echo $xml->lavoratore["età"]; //emette 25 echo $xml->lavoratore["salario"]; //emette 1000 echo $xml->worker; //stampa "Numero 1"
In XML sono consentiti i tag (e gli attributi) con un trattino. In questo caso, si accede a tali tag in questo modo:
$xml = simplexml_load_file(percorso file o url); echo $xml->lavoratore->(nome); //visualizza "Kolya" echo $xml->lavoratore->(cognome); //visualizza "Ivanov"
Lascia che ora non abbiamo un lavoratore, ma diversi. In questo caso, possiamo iterare sul nostro oggetto con un ciclo foreach:
$xml = simplexml_load_file(percorso file o url); foreach ($xml as $lavoratore) ( echo $lavoratore->nome; //stampa "Kolya", "Vasya", "Petya" )
Se non ti senti a tuo agio a lavorare con un oggetto, puoi convertirlo in un normale array PHP con il seguente trucco:
$xml = simplexml_load_file(percorso file o url); var_dump(json_decode(json_encode($xml), true));
Spesso un sito ha un file sitemap.xml. Questo file memorizza i collegamenti a tutte le pagine del sito per comodità di indicizzazione da parte dei motori di ricerca (l'indicizzazione è, infatti, l'analisi del sito da parte di Yandex e Google).
In generale, non dovremmo preoccuparci molto del motivo per cui questo file è necessario, l'importante è che se esiste, non puoi scalare le pagine del sito con metodi complicati, ma semplicemente utilizzare questo file.
Come verificare la presenza di questo file: analizziamo il sito site.ru, quindi facciamo riferimento a site.ru/sitemap.xml nel browser: se vedi qualcosa, allora è lì e se non lo vedi, allora ahimè.
Se esiste una mappa del sito, contiene collegamenti a tutte le pagine del sito in formato XML. Sentiti libero di prendere questo XML, analizzarlo, separare i collegamenti alle pagine di cui hai bisogno in qualsiasi modo conveniente per te (ad esempio, analizzando l'URL descritto nel metodo spider).
Di conseguenza, ottieni un elenco di collegamenti per l'analisi, non resta che andare su di essi e analizzare il contenuto di cui hai bisogno.
Maggiori informazioni sul dispositivo sitemap.xml su wikipedia.
Inizia a risolvere i problemi al seguente link: compiti per la lezione.
Quando tutto è deciso, vai allo studio di un nuovo argomento.