XML è stato progettato per memorizzare e comunicare dati.
Come HTML, anche xml è un linguaggio a marcatori. Non esistono marcatori (tag) predefiniti, ma è compito del programmatore scegliere i nomi da assegnare ai marcatori. Lo scopo finale è quello di descrivere dei dati. Sarà compito del software interpretare i dati.
si consideri il seguente esempio:
<?xml version="1.0" encoding="ISO-8859-1"?>
<appuntamento>
<giorno>
Venerdi
</giorno>
<ore>
18:00
</ore>
<con>
Dentista
</con>
<scopo>
Estrazione di un molare
</scopo>
</appuntamento>
Tutte le istruzioni XML iniziano con <? e terminano con ?>. La prima riga di un documento XML è:
<?xml version="1.0" encoding="UTF-8"?>
che indica che si sta usando XML versione 1.0 e la codifica dei caratteri UTF-8, una versione ridotta a 8 bit della codifica Unicode.
Subito dopo si apre un nuovo marcatore (tag), in questo caso: <appuntamento>.
Il nome scelto per definire un nuovo tag deve rispettare le regole: iniziare con una lettera o un trattino di sottolineatura, essere seguito da lettere, cifre, punti, trattini o sottolineatura, non contenere spazi.
I tag iniziano sempre con < e terminano con >.
I documenti XML sono composti da elementi. Gli elementi sono individuati da un tag di apertura, come <appuntamento>, seguito dal contenuto dell'elemento e terminato da un tag di chiusura corrispondente che inizia con </, come </appuntamento>. L'intero documento xml, escluse le istruzioni di elaborazione, è delimitato dall'elemento radice, in questo caso <appuntamento>:
<?xml version="1.0" encoding="ISO-8859-1"?>
<appuntamento>
...
...
...
</appuntamento>
All'interno dell'elemento radice vengono inseriti altri elementi, ognuno dei quali contiene un testo.
<?xml version="1.0" encoding="ISO-8859-1"?>
<appuntamento>
<giorno>Venerdi</giorno>
<ore>18:00</ore>
<con>Dentista</con>
<scopo>Estrazione di un molare</scopo>
</appuntamento>
Nell'esempio, l'elemento radice contiene quattro elementi.
La descrizione dei dati, presente nel file avente estensione .xml, può essere utilizzata in due modi. Il primo consiste nell'usare un foglio di stile per indicare al browser come presentare gli elementi creati e il secondo consiste nell'usare un linguaggio di programmazione come JavaScript, per gestire il documento XML.
Gli stili dei documenti XML possono essere specificati con i CSS o con il linguaggio XSL (eXtensible Style Language).
Per indicare al browser quale foglio di stile si deve applicare al file xml, si usa la seguente linea:
<?xml-stylesheet type="text/css" href="agenda.css"?>
L'attributo href specifica il nome del file contenente le definizioni delle proprietà di stile.
il file completo adesso è:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/css" href="agenda.css"?>
<appuntamento>
<giorno>Venerdi</giorno>
<ore>18:00</ore>
<con>Dentista</con>
<scopo>Estrazione di un molare</scopo>
</appuntamento>
Mentre il foglio di stile associato è:
giorno {
display:block;
text-align:center;
font-size:24pt;
color:#FF0000;
}
ore, con, scopo {
display:block;
font-size:18pt;
color:#0000FF;
}
Ogni elemento deve possedere il tag di chiusura.
In Html esistono tag che non hanno il corrispondente di chiusura, come <BR>, <img ... >. In XML è obbligatorio specificare sempre dove si chiude un elemento.
In XML i tag sono case sensitive.
Gli elementi devono essere correttamente nidificati.
Il documento XML deve avere un elemento radice.
I valori assegnati agli attributi devono essere racchiusi tra apici.
Come i tag di Html hanno degli attributi (esempio l'attributo type per il tag input) a cui si assegnano dei valori (esempio: < input type ="text">), anche ai marcatori XML si possono assegnare degli attributi, in questo caso il valore che viene dato all'attributo deve essere racchiuso tra apici. Es: <studente IDstud="Inf3B01">Giovanni</studente>
Alcuni caratteri sono riservati e non possono comparire nel file, devono essere sostituiti con le seguenti sequenze di caratteri:
< | < |
> | > |
& | & |
' (apice) | ' |
" | " |
In Html una sequenza di spazi viene rappresentata come un unico spazio, in XML i caratteri spazio non vengono collassati in uno.
Un elemento può essere completato con uno o più attributi. Un attributo descrive ulteriori caratteristiche dell'elemento. All'attributo bisogna assegnare un valore (racchiuso tra virgolette o tra apici).
esempio:
<studente classe="Inf3B"> Giuseppe </studente>
Se non si ritiene necessario usare un attributo si è comunque liberi di inserire, al suo posto, un nuovo elemento, come nel seguente esempio:
<classe> Inf3B </classe> <studente > Giuseppe </studente>
Nella casella sottostante si può incollare il proprio file xml e, premendo il tasto "convalida", si ottiene il controllo di validità. L'esempio presente nella casella contiene un errore: premere il pulsante di convalida per leggere la descrizione dell'errore. Dopo averlo corretto premere nuovamente il pulsante per ottenere l'analisi del file.
Un documento XML che rispetta la sintassi specificata, deve essere conforme ad un insieme di regole descritte nel Document Type Definition (DTD)
L'esempio dell'agenda può essere integrato da una linea che indica il file contenente la DTD:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/css" href="agenda.css"?>
<!DOCTYPE appuntamento SYSTEM "agenda.dtd">
<appuntamento>
<giorno>Venerdi</giorno>
<ore>18:00</ore>
<con>Dentista</con>
<scopo>Estrazione di un molare</scopo>
</appuntamento>
La dichiarazione DOCTYPE è un riferimento ad un file con estensione .dtd che descrive la struttura del documento XML.
<!DOCTYPE appuntamento
[
<!ELEMENT appuntamento (giorno, ore, con, scopo)>
<!ELEMENT giorno (#PCDATA)>
<!ELEMENT ore (#PCDATA)>
<!ELEMENT con (#PCDATA)>
<!ELEMENT scopo (#PCDATA)>
]>
Per specificare che la dichiarazione (DTD) è contenuta nello stesso file .xml si usa la sintassi:
<!DOCTYPE radice [dichiarazioni degli elementi]>
Confrontare con il file "agenda.dtd".
Le righe del file "agenda.dtd" sono interpretate nel modo seguente:
!DOCTYPE appuntamento definisce che l'elemento radice di questo documento è appuntamento.
!ELEMENT appuntamento definisce che l'elemento appuntamento contiene quattro elementi: "giorno, ore, con, scopo"
!ELEMENT giorno: l'elemento giorno deve essere di tipo "#PCDATA"
!ELEMENT ore l'elemento ore deve essere di tipo "#PCDATA"
!ELEMENT con l'elemento con deve essere di tipo "#PCDATA"
!ELEMENT scopo l'elemento scopo deve essere di tipo "#PCDATA"
Se la DTD è contenuta in un file esterno si usa la seguente sintassi:
<!DOCTYPE radice SYSTEM "nome file"
In questo caso il file .dtd contiene solo le righe !ELEMENT.
<!ELEMENT appuntamento (giorno, ore, con, scopo)>
<!ELEMENT giorno (#PCDATA)>
<!ELEMENT ore (#PCDATA)>
<!ELEMENT con (#PCDATA)>
<!ELEMENT scopo (#PCDATA)>
Il tipo PCDATA (acronimo di parsed character data) significa stringhe esaminate sintatticamente. L'analizzatore sintattico si serve dei marcatori per individuare le entità che descrivono la struttura del documento.
Il tipo CDATA (acronimo di character data) è il testo che l'analizzatore sintattico non deve interpretare.
Gli attributi di un elemento vengono dichiarati con ATTLIST
Sintassi:
<!ATTLIST Nome-Elemento Nome-Attributo tipo-attributo>
Gli oggetti che si possono creare in JavaScript posseggono proprietà e metodi.
Se si suppone che x sia un oggetto, alcune sue proprietà sono: il nome, il valore, il genitore, i successori e gli attributi del nodo x. Tra i metodi, invece, ci sono le funzioni per accedere al contenuto racchiuso da una coppia di marcatori, la funzione per inserire un nodo successore o la funzione per eliminare un nodo successore.
Negli esempi che seguono si userà il seguente documento .xml come riferimento:
biblioteca.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<biblioteca>
<libro genere="cucina">
<titolo lingua="it">Ricette primi piatti</titolo>
<autore>Gennaro Esposito</autore>
<prezzo>30.00</prezzo>
</libro>
<libro genere="romanzo">
<titolo lingua="en">Harry Potter</titolo>
<autore>J. K. Rowling</autore>
<prezzo>29.99</prezzo>
</libro>
<libro genere="storia">
<titolo lingua="it">Storia d'Italia</titolo>
<autore>Indro Montanelli</autore>
<autore>Roberto Gervasio</autore>
<prezzo>50.00</prezzo>
</libro>
</biblioteca>
Javascript offre al programmatore i metodi per accedere ad un file XML, attraversare l'albero dei nodi, inserire o cancellare nodi.
Per elaborare un documento XML occorre prima di tutto caricarlo in un oggetto.
Il seguente script carica un documento XML:
xhttp.open("GET","biblio.xml",false)
xhttp.send()
xmlDoc=xhttp.responseXML
Il seguente script accede al primo elemento e ne acquisisce il valore:
<!DOCTYPE html>
<html>
<body>
<script>
xhttp=new XMLHttpRequest()
xhttp.open("GET","biblio.xml",false)
xhttp.send()
xmlDoc=xhttp.responseXML
document.write("Il documento XML è stato caricato in un oggetto di javascript.")
txt=xmlDoc.getElementsByTagName("titolo")[0].childNodes[0].nodeValue
document.write("<br />"+txt)
</script>
</body>
</html>
Lo script, della pagina web sopra, mostra il titolo del primo libro contenuto nel file XML: "Ricette primi piatti"
xmlDoc è l'oggetto creato dall'interprete Javascrpt quando esegue l'istruzione XMLHttpResponse. A questo punto il file biblio.xml è disponibile tramite le proprietà e i metodi dell'oggetto xmlDoc
il metodo getElementsByTagName("titolo")[0] dell'oggetto xmlDoc prende un riferimento al primo elemento titolo.
childNodes[0] ottiene un riferimento al primo successore (quello con indice 0).
nodeValue restituisce il valore dell'elemento.
Le seguenti righe, aggiunte in coda allo script precedente, sostituiscono il titolo del primo libro.
xmlDoc.getElementsByTagName("titolo")[0].childNodes[0].nodeValue="cucinare è facile"
txt=xmlDoc.getElementsByTagName("titolo")[0].childNodes[0].nodeValue
document.write("<br />"+txt)
Si tenga presente che la modifica viene effettuata sugli elementi contenuti nella lista gestita dall'oggetto xmlDoc, il file .xml non viene modificato.
La proprietà length del documento XML restituisce il numero di nodi.
x=xmlDoc.getElementsByTagName('titolo').length
Il metodo getElementsByTagName() dell'oggetto xmlDoc restituisce una lista contenente tutti gli elementi appartenenti al tag specificato. Gli elementi compaiono nell'elenco nello stesso ordine con cui sono presenti nel file .xml.
Il seguente script ottiene il numero di nodi della lista e, con un ciclo, stampa tutti i titoli.
qta = xmlDoc.getElementsByTagName("titolo").length
for (i=0; i<qta; i++) {
document.write(xmlDoc.getElementsByTagName('titolo')[i].childNodes[0].nodeValue)
document.write("<br />")
}
La proprietà childNodes restituisce la lista dei nodi successori del nodo specificato.
La proprietà nodeValue restituisce il valore del nodo.
Il metodo removeChild() elimina uno specificato nodo e tutti i suoi successori. Il nodo da eliminare viene passato come parametro al nodo.
L'esempio che segue elimina il primo libro (indice 0) dal documento xml caricato in memoria.
document.write("Numero di libri: ")
document.write(xmlDoc.getElementsByTagName("libro").length)
document.write("<br>")
y = xmlDoc.getElementsByTagName("libro")[0]
xmlDoc.documentElement.removeChild(y)
document.write("Numero di libri dopo removeChild(): ")
document.write(xmlDoc.getElementsByTagName("libro").length)
Editore = xmlDoc.createElement("edizione")
x = xmlDoc.getElementsByTagName("libro")[0]
x.appendChild(Editore)
document.write("<br>" + x.getElementsByTagName("edizione")[0].nodeName + "<br>")
Con l'oggetto XMLHttpRequest si può:
Aggiornare una pagina web senza richiederla al server,
Richiedere dati a un server web dopo aver ricevuto la pagina
Ricevere dati da un server web dopo aver ricevuto la pagina
Inviare dati al server
Nota: Le regole XML sono riconosciute dai browser più recenti, quindi non sono riconosiute da IE7 e versioni precedenti.
La sintassi per creare un oggetto XMLHttpRequest è:
xmlhttp = new XMLHttpRequest();
Inviare una richiesta al server:
open(metodo, url, async) | Specifica il tipo della richiesta, l'URL, e se la richiesta deve essere asincrona o no. metodo: può assumere i valori GET o POST url: L'indirizzo del file async: può assumere i valori true (asincrona) o false (sincrona) |
send(stringa) | Invia la richiesta al server. Il parametro stringa deve essere specificato solo per il metodo POST |
Il metodo GET accoda i dati all'indirizzo, mentre il metodo POST invia i dati inserendoli nel pacchetto di richiesta spedito al server, quindi il metodo POST conviene quando i dati da inviare occupano più di 2 KB.
L'URL è l'indirizzo del file sul server. Il tipo del file non è prestabilito, può essere un file .txt. .xml, .asp, .php, ecc.
Le richieste asincrone migliorano le prestazioni dello script, perchè le operazioni svolte dal server potrebbero essere lente. La richiesta asincrona permette a JavaScript di non restare in attesa della risposta, ma continuare a eseguire altri script mentre il server si prepara a soddisfare la richiesta. Solo quando verrà ricevuta la risposta JavaScript completerà l'elaborazione dei dati.
Quando si assegna il valore true al parametro async, lo script viene portato in attesa e, quando la risposta sarà ricevuta, potrà essere ripreso al verificarsi dell'evento onreadystatechange
Se si usa async = false lo script verrà continuato, anche se il server ritarda a inviare la risposta.
Per acquisire la risposta del server esistono le proprietà responseText o responseXML dell'oggetto XMLHttpRequest
responseText | i dati della risposta vengono considerati una stringa di caratteri. |
responseXML | i dati della risposta vengono trattati in formato XML. |
I dati in formato stringa possono venir trattati come un testo, un elenco di numeri, a seconda delle esigenze di elaborazione, ma i dati in formato XML devono essere analizzati sintatticamente.
Dopo aver inviato una richiesta al server, l'evento onreadystatechange si verifica quando cambia la proprietà readyState dell'oggetto XMLHttpRequest.
L'oggetto XMLHttpRequest possiede, tra le altre, le proprietà:
onreadystatechange | Memorizza una funzione che deve essere richiamata automaticamente ogni volta che la proprietà readyState cambia. |
readyState | Contiene un codice di stato di XMLHttpRequest. 0: richiesta non inizializzata 1: la connessione al server è stata stabilita 2: richiesta ricevuta 3: richiesta in corso di elaborazione 4: richiesta soddisfatta e risposta pronta |
status | 200: "OK" 404: Page not found |
Alla proprietà onreadystatechange si assegna il nome della funzione da richiamare quando la risposta del server diventa pronta, cioè quando la proprità readyState diventa 4 e lo stato diventa 200:
xmlhttp.onreadystatechange=funzione() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("unaDiv").innerHTML=xmlhttp.responseText
}
}
Tutti i più recenti browser riconoscono l'oggetto XMLHttpRequest. La sintassi per creare un oggetto di classe XMLHttpRequest è:
xmlhttp = new XMLHttpRequest();
Verificare le credenziali memorizzate in un file XML per consentire l'accesso in un'area riservata.
<?xml version="1.0" encoding="UTF-8"?>
<studenti>
<studente idStud="Inf3B01">
<user>marco</user>
<pwd>PW123</pwd>
<email>marco@frapec.it</email>
</studente>
<studente idStud="Inf3B02">
<user>paolo</user>
<pwd>PW456</pwd>
<email>paolo@frapec.it</email>
</studente>
<studente idStud="Inf3B03">
<user>mario</user>
<pwd>PW789</pwd>
<email>mario@frapec.it</email>
</studente>
<studente idStud="Inf3B04">
<user>luigi</user>
<pwd>PW246</pwd>
<email>luigi@frapec.it</email>
</studente>
</studenti>
<html>
<head>
<title></title>
<script>
var xmlDoc = 0
var xhttp = 0
function autentica() {
var user = document.login.nomeUtente.value
var pass = document.login.Pw.value
if(user == "" || pass == "") {
if (user == "") {
alert("Inserisci il nome Utente")
}
if(pass == "") {
alert("Inserisci la Password")
}
return false
}
xhttp = new XMLHttpRequest()
xhttp.onreadystatechange = entra
xhttp.open("GET","utenti.xml",false)
xhttp.send()
}
function entra() {
var log = 2
var user = document.login.nomeUtente.value
var pass = document.login.Pw.value
if (xhttp.readyState == 4) {
log = 0
xmlDoc = xhttp.responseXML
var xmlUsers = xmlDoc.getElementsByTagName('user')
var xmlPasswords = xmlDoc.getElementsByTagName('pwd')
var userLen = xmlDoc.getElementsByTagName('studente').length
var xmlStudenti = xmlDoc.getElementsByTagName('studente')
for (var i = 0; i < userLen; i++) {
var xmlUser = xmlUsers[i].childNodes[0].nodeValue
var xmlPass = xmlPasswords[i].childNodes[0].nodeValue
var xmlId = xmlStudenti.item(i).attributes[0].nodeValue
if (xmlUser == user && xmlPass == pass) {
alert ("Utente riconosciuto")
log = 1
document.cookie = xmlId
document.login.submit()
break
}
}
}
if (log == 0) {
alert("Utente non riconosciuto")
return false
}
}
</script>
</head>
<body>
<form name="login" action="riservata.htm">
<p>Utente:</p>
<input type="text" name="nomeUtente" />
<br />
<p>Password:</p>
<input type="text" name="Pw" />
<br />
<input type="button" value="Accedi" onclick="autentica()" />
</form>
</body>
</html>
<html>
<head>
<title></title>
</head>
<body>
area riservata
</body>
</html>