Javascript è un linguaggio gentile e riservato: se qualche istruzione manca di senso l'esecuzione cerca di procedere senza disturbarci. L'unico caso in cui il sistema si arrabbia seriamente è quando il codice cerca di operare su di una variabile vuota. Questa situazione è molto frequente lavorando con XML: esplorando progressivamente l'albero si arriva prima poi a rami terminali e si può rischiare di "procedere nel vuoto". Ecco un esempio tipico di un'istruzione a serio rischio di blocco:
var figlio = nodo_attuale.firstChild;
alert (figlio.nodeName)
Se nodo_attuale non ha figli la prima riga viene eseguita senza problemi, ma la variabile figlio assume valore nullo. Al passo successivo l'esecuzione si blocca perché figlio non è un oggetto XML e quindi non supporta l'attributo .nodeName. Il sistema emette un segnale di errore con la spiegazione "Oggetto mancante".
Come evitare questo genere di errori? In genere è più che sufficiente porsi sempre due domande mentre si scrive il codice:
- in quale "mondo" esiste il mio oggetto XML?
- dove termina il mio albero?
In quale "mondo" esiste il mio oggetto XML?
La risposta è semplice ma molto importante: tutte le variabili di uno script rimangono dichiarate e posseggono un valore finchè la pagina web che contiene lo script stesso rimane attiva nel browser. Appena effettuiamo un click per spostarci perdiamo ogni parte del nostro codice e della sua esecuzione. Se torniamo indietro ritroviamo i nostri oggetti resettati.
L'oggetto XML dichiarato tramite l'istruzione "new ActiveXObject" segue questo destino e con esso ogni variabile che abbiamo generato nella navigazione.
Questa struttura a "scomparti stagni" è un grosso vincolo per i creatori di script. Esiste un metodo per permettere il colloquio fra scomparti? Certamente sì, se avete letto i paragrafi precedenti lo avete già utilizzato: il file di testo XML. Una fonte esterna XML in cui leggere e scrivere permette agli script di pagine diverse di passarsi dati. Per ora siamo capaci di leggere, nei prossimi capitoli impareremo anche a scrivere.
Riassumendo: l'oggetto XML ottenuto per parserizzazione ed ogni parte del suo albero "vivono" finchè il nostro utilizzatore non fa click verso un'altra pagina. Tuttavia possiamo usare il file XML di testo per salvare e riutilizzare i dati.
Dove termina il mio albero?
Esistono alcune istruzioni che ci permettono di non "avanzare nel vuoto" quando ci muoviamo verso la periferia dell'albero, cioè di verificare se un nodo ha figli o attributi prima di provare a leggerli.
- Verificare l'esistenza dei figli: ecco come l'esempio visto a inizio paragrafo può essere reso sicuro da errori:
if (nodo_attuale.hasChildNodes())
{
var figlio = nodo_attuale.firstChild;
alert (figlio.nodeName)
}
else alert ("Fine dell'albero")
Il metodo hasChildNodes() restituisce il valore booleano true se il nodo ha figli (compreso il nodo figlio di testo), false altrimenti.
Verificare che un nodo esista prima di leggerlo: abbiamo visto che assegnare una variabile nulla, ma accorgersi del suo stato prima di operarvi, non genera errore. Questo controllo è particolarmente utile quando non possiamo interrogare il padre (con l'istruzione hasChildNodes) oppure nelle condizioni di uscita dei cicli che leggono i vettori di nodi figli:
if (nodo attuale != null)
{
/* operazione sul nodo */
}
var figlio = nodo_attuale.firstChild
while (figlio != null)
{
/* operazione sul nodo */
figlio = figlio.nextSibling
}
Per concludere questo paragrafo raccomandiamo di ricordare che ognuno hai i suoi alberi preferiti, cioè che i file XML degli utilizzatori possono avere forme molto diverse, a cui un programma deve esser preparato. È nella filosofia di XML l'essere un linguaggio universale: imporre degli standard come quello di fissare i nomi dei nodi o la loro posizione non rientra in questa filosofia.