Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Javascript e XML

Una panoramica su metodi e tecniche per manipolare documenti XML con Javascript
Una panoramica su metodi e tecniche per manipolare documenti XML con Javascript
Link copiato negli appunti

Il grande vantaggio introdotto dall'XML trovo consista nell'aver facilitato lo scambio di
informazioni. Utilizzare questo formato ha risolto quasi tutti i problemi riguardo lo scambio
di dati  tra sistemi strutturalmente diversi e che altrimenti avrebbero avuto
bisogno di complicate interfacce per comunicare. Non credo di sbagliare sostenendo
che se AJAX è il cemento del Web 2.0 sicuramente XML è il mattone di questo nuovo
modo di utilizzare e progettare il web. Un documento XML ovviamente, necessita
di essere manipolato (spesso trasformato) affinchè le informazioni riportate al
suo interno possano essere fruite. In questo articolo vedremo quindi
come un file XML possa essere letto  con Javascript , le differenze del DOM nella
manipolazione tra HTML e XML e infine, come applicare un foglio XSLT ad un XML usando sempre
Javascript.

Leggere un file XML: un metodo alternativo a XMLHTTPRequest

È noto, e direi piuttosto scontato, che leggere un file XML in remoto con Javascript
può essere possibile
usando XMLHTTPRequest. Non molti sanno però che all'oggetto su cui si fonda AJAX
si affianca una valida alternativa che permette anch'essa di leggere file XML (e
solo file di questo tipo). Al solito il metodo viene invocato nei due browser piu
diffusi, Internet Explorer e Firefox, in maniera differente ma a fronte di alcuni
svantaggi, si dimostra essere maggiormente adatto alla manipolazione di documenti XML. Vediamo
allora come inizializzare i nostri oggetti e commentiamo insieme il codice che segue:

if (document.implementation && document.implementation.createDocument)
{
   
xmlDoc = document.implementation.createDocument("", "", null);
   
xmlDoc.onload = readXML();
}
else (window.ActiveXObject)
{
   
xmlDoc = new ActiveXObject("MSXML2.DOMDocument");
   
xmlDoc.onreadystatechange = function () {
       
if (xmlDoc.readyState == 4) readXML()
    
};
}
xmlDoc.load("fileXMLdacaricare");

Per Firefox, questo metodo alternativo si invoca usando document.implementation
mentre per Explorer occorre creare una instanza ActiveX dell'oggetto MSXML2.DOMDocument.
I metodi sono entrambi asincroni per default (ma possono essere resi sincroni ponendo
la proprietà async a false):

xmlDoc.async = false

e mentre per document.implementation esiste una funzione onload che ci dice quando il documento XML è stato creato, per MSXML occorre fare
un controllo sulla proprietà readyState
i cui valori possono variare da 1 a 4:
quando readyState è pari a 4 appunto, significa che il file XML è stato completamente caricato (un po come con XMLHTTPRequest).

In particolare nella nostra funzione, controlliamo che il documento sia stato
caricato e poi facciamo partire la funzione
readXML() che nel nostro esempio ci
servirà per studiare i vari metodi messi a disposizione per manipolare i dati del
file XML.

Torniamo brevemente al metodo usato con Firefox: come si vede dal codice, la funzione
document.implementation.createDocument ha tre
argomenti che nel nostro caso sono vuoti. In ordine essi sono: namespace, il tag root del documento
e null perché le funzioni associate a questo parametro non sono state
ancora implementate.
Usandoli possiamo creare anche documenti XML vuoti che potremmo riempire con le
API del DOM. Analogamente, ma in modo più macchinoso, anche Internet Explorer mette
a disposizione le funzioni per creare documenti XML vuoti. A cosa può servire questo?
Ad esempio a creare un output XML per una base
di dati sui cui dati potremo lavorare manipolando poi l'XML salvato in locale, senza gravare ulteriormente sul nostro server.

Ritorniamo a parlare delle differenze tra XMLHTTPRequest e il metodo alternativo
che stiamo usando. XMLHTTPRequest può essere usato per qualsiasi tipo di documento
di testo (non solo XML quindi) mentre il metodo alternativo funziona solamente con
file XML. XMLHTTPRequest funziona solo con il protocollo HTTP e quindi qualsiasi
altro protocollo non è utilizzabile per accedere ai file. Come avete intuito,
il metodo alternativo non è invece legato a nessun protocollo in particolare e
quindi può caricare anche file XML che si trovano sul file system del vostro server
(oppure su un server ftp). Infine, quando usiamo il metodo alternativo, con HTTP possono
essere generate solamente richieste di tipo GET e non di tipo POST.

Come lo leggo?

Una volta compreso che la lettura del file XML può essere effettuata in due modi, passiamo a vedere come con il DOM sia possibile usare le informazioni contenute nel nostro file XML. La funzione
che segue legge un qualsiasi file XML e ne mostra il nome del tag e il suo contenuto:

function readXML(app)

  {

   var x = xmlDoc.getElementsByTagName('item');

   var text = '';

   for (i=0;i < x.length;i++)

      {

       for (j=0;j < x[i].childNodes.length;j++)

         {
          if (x[i].childNodes[j].nodeType != 1) continue;

          //text += x[i].childNodes[j].nodeName + ": "
+ x[i].childNodes[j].firstChild.nodeValue + "";

          text += x[i].childNodes[j].nodeName + ": " +
x[i].childNodes[j].firstChild.nodeValue + "";

         }

       }

       alert(text); 
       var app = document.getElementById('textAPP');

       app.innerHTML = text; 
   }

Analizziamo brevemente il codice: accedere ad un nodo dell'XML si riduce a navigare
i suoi rami fino a raggiungere l'elemento desiderato. Nel nostro caso (ripeto, un
RSS)  vogliamo visualizzare tutti gli elementi figli di tutti gli elementi
item. Quindi instanziamo un array di elementi item (var x = xmlDoc.getElementsByTagName('item'))
dopodiché iteriamo su quest'array e per ogni figlio dell'elemento (x[i].ChildNodes[j]).

L'esempio mostra le due caratteristiche principali di childNodes: NodeName,
che ci permette di ottenere il nome del tag e firstChild.nodeValue, che
invece restituisce il valore eventualmente contenuto tra i tag. Come avrete notato
c'è una riga che non è stata commentata: if(x[i].childNodes[j].nodeType != 1). In realtà si tratta di un hack per Firefox. Il browser della Mozilla Foundation
infatti, interpreta come firstChild il nodo tra item e description che, in questo
caso però, non ha nessuno value da mostrare. Ciò causa un errore che blocca l'esecuzione
dello script. È buona norma quindi (una volta individuato il nodo padre) inserire
questo piccolo hack.

HTML e XML: le differenze nel DOM (e non solo...)

Abbiamo appena visto che per accedere i valori di un file XML usiamo un approccio
che ricorda molto da vicino il DOM ben noto per le varie applicazioni Javascript
tipiche del Web 2.0 (e non solo).

In effetti quando il W3C progettò le API per
DOM, l'idea era quella di renderle valide per ogni linguaggio compreso chiaramente
XML: anzi, diciamo pure che XML ha inspirato la progettazione delle API tant'è che
HTML viene gestito dal DOM grazie ad una estensione delle API originali. Ma qual è
la differenza fondamentale tra il DOM usato per l'XML e quello usato per HTML? Facile:
l'utilizzo della funzione getElementById. Infatti mentre in HTML questo è il metodo
per accedere ad un elemento della pagina (ovviamente se identificato
da un id univoco)
in XML è probabile che il valore restituito usando questa funzione, sarà null.
Questo perché in XML non è sufficiente dichiarare un attributo id
 in un tag e accedere poi a quel tag con getElementById: occorre anche
"tipizzare" l'attributo, e per farlo va definito il DTD per il documento XML e poi
dichiararlo nel DOCTYPE.

Un'altra differenza tra HTML e XML è che HTML ha
una proprietà body che si riferisce al tag <body> mentre per XML solo la proprietà
documentElement si riferisce al tag root del documento. Infine, per accedere al valore di un attributo
di un tag in XML va utilizzato getAttribute(nomeAttributo) mentre per
modificarlo si usa setAttribute(nomeAttributo). Quindi:  se abbiamo il tag: <esempioTag
attr="ciao">
e vogliamo accedere al valore dell'attributo attr, si scrive: getAttribute(attr).
Ovviamente questa operazione non è permessa con documenti HTML.

Javascript, XML e XSLT

La naturale estensione di XML per la trasformazione di un documento XML in formati
fruibili all'utente finale è senz'altro XSL. In Javascript è possibile applicare
un file XSL ad un file XML sia in Internet Explorer che in Firefox, con la solita
discrepenza sui metodi di base e sulle modalità di inizializzazione. Occorre però
precisare in questo caso, che il W3C non ha ancora definito nessuna API standard
per le trasformazioni XSL con il DOM o con XML per Javascript e quindi per una volta,
giustifichiamo scelte diverse a fronte di una poco matura situazione ad "alti livelli".

Passiamo al concreto e partiamo con Firefox le cui API proprietarie per la trasformazione
di documenti XML con XSL viene garantita dall'oggetto XSLTProcessor. In Internet
Explorer invece l'oggetto predisposto è TransformNode(). Vediamo nel seguente esempio
come creare una funzione cross browser per applicare un file XSL (che supponiamo di avere in  remoto, cioè un URL) ad uno specifico
nodo del nostro file XML (supponiamo di aver già riconosciuto quale browser stiamo
utilizzando e riusiamo la funzione per caricare file XML che abbiamo visto in precedenza,
ovvero l'oggetto ottenuto, XMLDoc che chiamiamo XSLDoc quando carichiamo il file
XSL):

XSLDoc.load(URLdelFileXSL);
if (typeof XSLTProcessor != "undefined") {
   //stiamo usando Firefox
   var xsltProcessor = new XSLTProcessor();
   xsltProcessor.importStylesheet(XSLDoc);
   var app = xsltProcessor.transformToFragment(nodoDelDOMDaTrasformare);
} else {
  //stiamo usando Internet Explorer
  //quindi il nodo che vogliamo trasformare ha la funzione transformNode tra
i suoi metodi
  var app = nodoDelDOMDaTrasformare.TransformNode(XSLDoc)
}

In Firefox è possibile usare anche un altro metodo al posto di transformToFragment
(che come TransformNode per IE, restituisce un nodo) ed è transformToDocument:
l'oggetto che se ne ricava è un document HTML se l'XSL produce come output un HTML
oppure un documento XML se l'XSL produce un file XML.

Javascript e XPath

Chiudiamo con un accenno alle espressioni XPath e le relative API del W3C per la
selezione dei nodi nel DOM usando questo approccio. Al solito anche qui, Firefox
ha implementato le API usando il metodo evaluate() del document object, che compila
una espressione XPath in modo che sia possibile valutarla diverse volte in modo
efficiente. Internet Explorer invece, fornisce i due metodi selectSingleNode() e
selectNodes() esclusivamente per documenti XML (e quindi non funzionano con documenti HTML!).
XPath è ovviamente una parte che richiederebbe una serie di articoli per essere
analizzata a fondo e per questo mi fermo qui, limitandomi all'introduzione degli
strumenti che dovete usare se volete cercare nodi all'interno dei vostri documenti,
usando appunto Javascript.

Considerazioni Finali

Abbiamo visto quindi come Javascript si sia ormai evoluto, in un linguaggio che
permette sofisticate operazioni un tempo appannaggio esclusivamente dei linguaggi
server side. Come già detto, molte di queste innovazioni hanno fatto si che nascesse
il Web come lo conosciamo oggi, e ovviamente XML è una parte fondamentale per l'evoluzione
(anche) futura della user experience durante la navigazione e la fruizione dei contenuto sul web. Javascript copre completamente
ogni aspetto necessario a maneggiare le informazioni in questo formato e in questo articolo
ho cercato di toccare un po' tutti gli aspetti. Come avrete notato inoltre, i browser
che ho citato sono stati solamente Internet Explorer e Firefox: questo perché il
resto dei browser non ha ancora un supporto Javascript ad XSLT né tanto
meno ad XPath: in questi casi viene consigliato l'utilizzo di AJAXSLT una libreria sviluppata da Google. Questo è tutto. Alla prossima e buon divertimento!

Ti consigliamo anche