Linguaggi di markup - SGML, HTML e XML
In questa pagina 10
Questa nota presenta la famiglia dei linguaggi di markup: da dove vengono, come si dice se un documento XML è corretto (ben formato) e conforme a uno schema (valido), e quando conviene XML, HTML o JSON. L'architettura in cui questi formati viaggiano è in Architettura delle applicazioni web - browser, server web e livelliUn'applicazione web è distribuita su più livelli (tier): presentazione (browser: HTML, CSS, JavaScript), logica applicativa (server web e application server) e dati (DBMS). Il client invia richieste HTTP, il server risponde; HTTP è senza stato, quindi lo stato dell'utente viaggia in cookie e sessioni. Il web server serve file statici, l'application server (container, per esempio Tomcat per le servlet Java) esegue codice che genera risposte dinamiche; spesso il web server fa da reverse proxy davanti all'application server. Il browser trasforma i byte della risposta in una pagina: decodifica, tokenizzazione e costruzione del DOM, CSS che diventa CSSOM, render tree, layout (reflow), paint e composizione; un script senza defer o async blocca il parsing, il CSS blocca il rendering. Origine = schema + host + porta; la same-origin policy limita ciò che uno script può leggere da altre origini. Web 1.0: pagine generate dal server, ogni azione ricarica la pagina; Web 2.0: AJAX, contenuti degli utenti, servizi REST; Web 3.0: dati con significato esplicito (RDF, linked data).Architettura delle applicazioni web - browser, server web e livelli →; HTML ha una nota a parte (HTML5 - struttura del documento, elementi semantici e formUn documento HTML5 ha la forma doctype (), html con lang, head (meta charset UTF-8, viewport, title, link, script) e body. Il parser HTML5 non dà mai errore: corregge (aggiunge il tbody, chiude i p). Gli elementi semantici (header, nav, main, section, article, aside, footer, figure, time) descrivono il ruolo del contenuto e danno ai lettori di schermo i punti di riferimento; div e span sono neutri. Link: a href (assoluto, relativo, #frammento, mailto), rel e target; immagini con alt obbligatorio. Tabelle: table, caption, thead, tbody, th con scope, td, colspan e rowspan, solo per dati. Form: action, method (GET mette i campi nella query string, per letture idempotenti e ricercabili; POST li mette nel corpo, per modificare lo stato), enctype (application/x-www-form-urlencoded predefinito, multipart/form-data per i file); si invia solo ciò che ha name; label for collega etichetta e campo; tipi di input (text, email, number, date, time, radio, checkbox, hidden...); validazione nativa con required, minlength, maxlength, min, max, step, pattern e type, aggirabile e quindi da ripetere sul server; novalidate la spegne. Accessibilità: lang, alt, label, gerarchia dei titoli, navigazione da tastiera, ARIA solo quando l'HTML nativo non basta.HTML5 - struttura del documento, elementi semantici e form →). XML e JSON "di base", con SOAP e REST, sono già in Web service, XML, JSON, SOAP e RESTUn web service e' un servizio software accessibile via rete da altri programmi, con messaggi in formato standard su HTTP; i formati di dati sono XML (marcatori annidati, attributi, namespace, validazione con XSD) e JSON (RFC 8259: oggetti, array, stringhe, numeri, true, false, null; piu' compatto e diretto per i linguaggi di programmazione); SOAP e' un protocollo di messaggi XML (Envelope con Header facoltativo e Body, Fault per gli errori) inviati di solito con una POST HTTP e descritti da un file WSDL; REST e' uno stile architetturale (Fielding) in cui il servizio espone risorse identificate da URI e le manipola con i metodi HTTP: GET legge, POST crea, PUT sostituisce, PATCH modifica, DELETE elimina, con codici di stato significativi (200, 201 con Location, 204, 400, 404, 409), senza stato sul server, con cache e interfaccia uniforme.Web service, XML, JSON, SOAP e REST →: qui si aggiungono DTD, XML Schema, namespace e il confronto.
Che cos'è un linguaggio di markup
Il markup è l'insieme dei marcatori che si aggiungono a un testo per dire che cosa è ogni parte. Ci sono due approcci:
- procedurale: si dice come trattare il testo ("metti in grassetto, vai a capo"): TeX, troff;
- descrittivo (o generalizzato): si dice che cosa è il testo ("questo è un titolo, questo è un autore") e il come lo decide un altro programma (un foglio di stile, un'applicazione). SGML, XML e HTML sono di questo tipo. Il vantaggio è separare contenuto e presentazione ed elaborare lo stesso documento in modi diversi.
SGML, XML e HTML: la genealogia
- SGML (Standard Generalized Markup Language, ISO 8879, 1986) è un metalinguaggio: non definisce i tag, ma il modo di definire linguaggi di markup. Ogni linguaggio ("applicazione SGML") si descrive con una DTD (Document Type Definition) che elenca gli elementi ammessi, il loro contenuto e i loro attributi. È potente ma complesso: pochi strumenti lo implementano per intero.
- HTML fino alla 4.01 è un'applicazione SGML: ha una sua DTD. Il vocabolario è fisso (
h1,p,a...) e pensato per le pagine web, e i browser sono molto tolleranti con gli errori. - XML (eXtensible Markup Language, W3C, versione 1.0 del 1998) è un sottoinsieme semplificato di SGML: sintassi rigida, nessuna abbreviazione, analisi semplice. Non fissa nessun vocabolario: ciascuno inventa i propri tag.
- XHTML riscrive HTML come applicazione XML (ogni tag chiuso, minuscole...).
- HTML5 (WHATWG HTML Living Standard) non si basa più su SGML: definisce un algoritmo di parsing che dice che DOM costruire da qualsiasi testo, anche sbagliato, e quindi è tollerante per definizione. Esiste anche una serializzazione XML (XHTML5, servita con
application/xhtml+xml), ma è rara.
SGML (ISO 8879) ──┬── HTML 2.0 ... 4.01 (applicazioni SGML)
└── XML 1.0 (sottoinsieme) ──┬── XHTML, SVG, MathML, XSD, web.xml, pom.xml ...
HTML5 (WHATWG): parser proprio, né SGML né XML (ma con una serializzazione XML)XML: documento ben formato
L'idea base (albero di elementi, esempio del libro, regole principali) è già in Web service, XML, JSON, SOAP e RESTUn web service e' un servizio software accessibile via rete da altri programmi, con messaggi in formato standard su HTTP; i formati di dati sono XML (marcatori annidati, attributi, namespace, validazione con XSD) e JSON (RFC 8259: oggetti, array, stringhe, numeri, true, false, null; piu' compatto e diretto per i linguaggi di programmazione); SOAP e' un protocollo di messaggi XML (Envelope con Header facoltativo e Body, Fault per gli errori) inviati di solito con una POST HTTP e descritti da un file WSDL; REST e' uno stile architetturale (Fielding) in cui il servizio espone risorse identificate da URI e le manipola con i metodi HTTP: GET legge, POST crea, PUT sostituisce, PATCH modifica, DELETE elimina, con codici di stato significativi (200, 201 con Location, 204, 400, 404, 409), senza stato sul server, con cache e interfaccia uniforme.Web service, XML, JSON, SOAP e REST →. Qui sono raccolte le regole complete della buona formazione (well-formedness, XML 1.0): un documento che le viola non è XML e un parser XML deve fermarsi con un errore (a differenza di un parser HTML).
- C'è un solo elemento radice; prima e dopo possono esserci solo commenti, istruzioni di elaborazione e spazi.
- Ogni tag di apertura ha il suo tag di chiusura (o è vuoto:
<br/>), gli elementi sono annidati correttamente (<a><b></b></a>). - I nomi distinguono maiuscole e minuscole:
<Studente>non si chiude con</studente>. Un nome comincia con una lettera, un trattino basso o i due punti, e continua con lettere, cifre,-,_,.. - Un elemento non può avere due attributi con lo stesso nome, e i valori degli attributi stanno fra virgolette (doppie o singole) e non contengono
<. - I caratteri
<e&nel testo si scrivono con le entità predefinite:<>&"'; per un blocco di testo grezzo c'è<![CDATA[ ... ]]>. - La dichiarazione
<?xml version="1.0" encoding="UTF-8"?>, se c'è, è la prima cosa del file (nemmeno uno spazio prima). Le istruzioni di elaborazione hanno la forma<?bersaglio dati?>; i commenti<!-- ... -->non contengono--.
Esempio: il documento del seguito.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE prenotazioni SYSTEM "prenotazioni.dtd">
<prenotazioni>
<aula id="a1" posti="80"><nome>Aula A1</nome></aula>
<aula id="a2" posti="45"><nome>Aula B2</nome></aula>
<aula id="a3" posti="30"><nome>Lab Info</nome></aula>
<prenotazione id="p1" aula="a1">
<giorno>2026-10-19</giorno>
<ora_inizio>09:00</ora_inizio>
<ora_fine>11:00</ora_fine>
<studente>Rossi</studente>
</prenotazione>
<prenotazione id="p2" aula="a1">
<giorno>2026-10-19</giorno>
<ora_inizio>14:00</ora_inizio>
<ora_fine>16:00</ora_fine>
<studente>Bianchi</studente>
</prenotazione>
<prenotazione id="p3" aula="a2">
<giorno>2026-10-20</giorno>
<ora_inizio>10:00</ora_inizio>
<ora_fine>12:00</ora_fine>
<studente>Verdi</studente>
</prenotazione>
<prenotazione id="p4" aula="a3">
<giorno>2026-10-21</giorno>
<ora_inizio>09:00</ora_inizio>
<ora_fine>13:00</ora_fine>
<studente>Rossi</studente>
</prenotazione>
</prenotazioni>- Le chiavi del database (
1,2...) diventano gli identificatoria1,p1: un valore di tipo ID in XML non può cominciare con una cifra ed è unico in tutto il documento, quindi si usa un prefisso diverso per aule e prenotazioni. - Informazioni come
postistanno in un attributo (metadati dell'elemento), altre comestudentein un elemento figlio. Non c'è una regola assoluta: gli attributi sono semplici (una sola stringa, nessun ordine, nessuna struttura), gli elementi possono ripetersi e annidarsi. - La riga
<!DOCTYPE ...>collega il documento alla sua DTD (vedi sotto).
Documento valido: la DTD
Ben formato vuol dire sintassi corretta. Valido (valid) vuol dire che, in più, il documento rispetta le regole di uno schema: quali elementi esistono, in che ordine, con quali attributi. Un documento ben formato non è automaticamente valido; uno valido è sempre ben formato. La validazione è un controllo separato fatto da un parser validante.
Come si dichiara
La DTD si dichiara con <!DOCTYPE radice ...>. Può essere esterna (un file, SYSTEM "prenotazioni.dtd"), interna (dentro il documento, fra parentesi quadre [ ... ]) o entrambe.
<!DOCTYPE prenotazioni [
<!ELEMENT prenotazioni (prenotazione*)>
<!ELEMENT prenotazione (#PCDATA)>
]>Elementi: <!ELEMENT>
<!ELEMENT nome modello-di-contenuto>. I modelli:
| modello | significato |
|---|---|
EMPTY |
nessun contenuto (<br/>) |
ANY |
qualunque contenuto |
(#PCDATA) |
solo testo (parsed character data) |
(a, b, c) |
sequenza: a poi b poi c, nell'ordine |
(a | b) |
scelta: a oppure b |
a? |
zero o una volta |
a* |
zero o più volte |
a+ |
una o più volte |
(#PCDATA | em)* |
contenuto misto: testo con em fra le parole |
Gli operatori si combinano con le parentesi: (a, (b \| c)+).
Attributi: <!ATTLIST>
<!ATTLIST elemento nome tipo valore-predefinito>.
- tipi:
CDATA(testo qualsiasi);ID(identificatore, unico nel documento, nome valido);IDREF(riferimento a unIDche deve esistere;IDREFSper più);NMTOKEN(una parola); un'enumerazione(a \| b \| c); - valori:
#REQUIRED(obbligatorio),#IMPLIED(facoltativo),#FIXED "v"(sempre uguale a v), oppure un valore"v"usato se manca.
La DTD dell'esempio
<!ELEMENT prenotazioni (aula+, prenotazione*)>
<!ELEMENT aula (nome)>
<!ATTLIST aula
id ID #REQUIRED
posti CDATA #REQUIRED>
<!ELEMENT nome (#PCDATA)>
<!ELEMENT prenotazione (giorno, ora_inizio, ora_fine, studente)>
<!ATTLIST prenotazione
id ID #REQUIRED
aula IDREF #REQUIRED>
<!ELEMENT giorno (#PCDATA)>
<!ELEMENT ora_inizio (#PCDATA)>
<!ELEMENT ora_fine (#PCDATA)>
<!ELEMENT studente (#PCDATA)>- La radice
prenotazionicontiene almeno un'aula (aula+) seguita da zero o più prenotazioni (prenotazione*): le aule vanno prima, perché la sequenza è ordinata. aulaha un elementonomee due attributi obbligatori:iddi tipoID(unico),postitesto.prenotazioneha quattro figli in questo ordine;auladi tipoIDREFè una chiave esterna: il parser verifica che esista un elemento con quell'ID. È l'unico controllo di integrità referenziale della DTD, ma è debole: non dice a quale tipo di elemento punta (l'IDREFpuò puntare anche ap1).
Il documento sopra è valido. Questi sei documenti, tutti ben formati, non sono validi (messaggio del parser Java del JDK 21, che valida con la DTD):
| modifica | errore |
|---|---|
manca <ora_fine> |
il contenuto di prenotazione deve corrispondere a (giorno,ora_inizio,ora_fine,studente) |
aula="a9" |
deve esistere un elemento con identificatore a9 |
due id="p1" |
il valore p1 di tipo ID deve essere unico |
manca posti |
l'attributo posti è obbligatorio |
ora_fine prima di ora_inizio |
stesso errore della sequenza |
elemento <note> non dichiarato |
note deve essere dichiarato |
Limiti della DTD
- Niente tipi di dato:
giornoè testo; la DTD accetta<giorno>pippo</giorno>; - non esprime vincoli numerici (
posti > 0) né fra elementi (ora_finedopoora_inizio); - ha una sintassi diversa da XML;
- non conosce i namespace.
Per questo oggi si usa quasi sempre XML Schema.
XML Schema (XSD)
XML Schema (W3C, estensione .xsd) è un linguaggio per descrivere i documenti XML scritto in XML. Ha tipi di dato semplici (xs:string, xs:integer, xs:positiveInteger, xs:date, xs:boolean...), tipi complessi con sequenza, scelta e cardinalità precisa (minOccurs, maxOccurs), restrizioni (lunghezze, intervalli, espressioni regolari) e vincoli di chiave. Lo schema dell'esempio:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="prenotazioni">
<xs:complexType>
<xs:sequence>
<xs:element name="aula" type="TipoAula" maxOccurs="unbounded"/>
<xs:element name="prenotazione" type="TipoPrenotazione"
minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:key name="chiaveAula">
<xs:selector xpath="aula"/>
<xs:field xpath="@id"/>
</xs:key>
<xs:keyref name="refAula" refer="chiaveAula">
<xs:selector xpath="prenotazione"/>
<xs:field xpath="@aula"/>
</xs:keyref>
</xs:element>
<xs:simpleType name="Ora">
<xs:restriction base="xs:string">
<xs:pattern value="([01][0-9]|2[0-3]):[0-5][0-9]"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TipoAula">
<xs:sequence>
<xs:element name="nome" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="posti" type="xs:positiveInteger" use="required"/>
</xs:complexType>
<xs:complexType name="TipoPrenotazione">
<xs:sequence>
<xs:element name="giorno" type="xs:date"/>
<xs:element name="ora_inizio" type="Ora"/>
<xs:element name="ora_fine" type="Ora"/>
<xs:element name="studente" type="xs:string"/>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="aula" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>- Il prefisso
xsè legato al namespace di XML Schema; ogni parolaxs:...è un costrutto dello schema. xs:sequenceè la sequenza ordinata,maxOccurs="unbounded"è il "più volte";aulahaminOccurs1 (valore predefinito) emaxOccurs="unbounded"(come+della DTD),prenotazionehaminOccurs="0"(come*).xs:key/xs:keyrefesprimono chiave e chiave esterna con un tipo preciso:auladi una prenotazione deve valere l'iddi un elementoaula, non di un altro. È la versione corretta del vincolo che la DTD fa conIDREF.xs:positiveIntegerrifiutaposti="0"o"molti";xs:dateaccetta soloAAAA-MM-GG(2026-10-19sì,19/10/2026no).- Perché non
xs:time?xs:timerichiede i secondi (09:00:00): con09:00il documento sarebbe invalido (verificato con il validatore del JDK 21). Si definisce il tipoOracon un pattern (espressione regolareore:minuti); un'ora25:00viene rifiutata. - Lo schema ancora non controlla che
ora_finesia dopoora_inizio: i vincoli fra valori diversi li verifica l'applicazione (o il linguaggio Schematron/XSD 1.1, fuori dal programma).
Confronto:
| DTD | XML Schema | |
|---|---|---|
| sintassi | propria (non XML) | XML |
| tipi di dato | solo testo | molti tipi e restrizioni |
| namespace | no | sì |
| chiavi esterne | ID/IDREF (debole) |
key/keyref |
| complessità | semplice | verboso |
Namespace
Due vocabolari XML possono usare lo stesso nome (<titolo> di un libro, <titolo> di un documento HTML). I namespace (W3C, Namespaces in XML) distinguono i nomi associandoli a un URI che fa da identificatore: non deve essere una pagina esistente, deve solo essere unico.
<pr:prenotazioni xmlns:pr="http://aule.example.org/ns/prenotazioni"
xmlns:h="http://www.w3.org/1999/xhtml">
<pr:prenotazione id="p1" aula="a1">
<pr:studente>Rossi</pr:studente>
<h:p>Portare <h:em>il proprio</h:em> portatile.</h:p>
</pr:prenotazione>
</pr:prenotazioni>xmlns:pr="..."lega il prefissoprall'URI; il nome completo dipr:studenteè la coppia (URI,studente). Il prefisso è solo un'abbreviazione locale: due documenti con prefissi diversi ma lo stesso URI usano lo stesso vocabolario.h:peh:emappartengono al namespace di XHTML: nello stesso documento convivono due vocabolari senza conflitti.- Con
xmlns="URI"senza prefisso si imposta il namespace predefinito per l'elemento e tutti i discendenti non prefissati: lo stesso documento si può scrivere<prenotazioni xmlns="http://aule.example.org/ns/prenotazioni" xmlns:h="...">con tag senza prefisso. Un parser che riconosce i namespace restituisce per entrambe le scritture gli stessi nomi (verificato con Python:{http://aule.example.org/ns/prenotazioni}studente). - Gli attributi senza prefisso non appartengono a nessun namespace (neppure a quello predefinito):
ideaulasono qui nomi semplici. - La visibilità di una dichiarazione è l'elemento in cui compare e i suoi discendenti.
Leggere XML da un programma
Due stili: DOM (si carica tutto in un albero in memoria, si naviga liberamente) e SAX o a eventi (si legge in sequenza, poco consumo di memoria). Nel browser c'è DOMParser, che restituisce un albero DOM interrogabile come una pagina HTML:
const doc = new DOMParser().parseFromString(xml, "application/xml");
const elenco = [...doc.querySelectorAll("prenotazione")]
.map(p => p.getAttribute("id") + "=" + p.querySelector("studente").textContent);
// con le prenotazioni p1 (Rossi) e p2 (Bianchi): ["p1=Rossi", "p2=Bianchi"]
const rotto = new DOMParser().parseFromString("<a><b></a>", "application/xml");
rotto.querySelector("parsererror") !== null; // true: XML non ben formato- Con
"application/xml"il parser è severo: se il documento non è ben formato non lancia un'eccezione ma restituisce un documento che contiene un elementoparsererror; va controllato. getAttributelegge un attributo,textContentil testo dentro l'elemento.
XML, HTML e JSON a confronto
| HTML | XML | JSON | |
|---|---|---|---|
| scopo | pagine per le persone | documenti e dati strutturati | dati |
| vocabolario | fisso (WHATWG) | libero | libero (oggetti e array) |
| errori | tollerato, il parser corregge | fatale, il parser si ferma | fatale |
| maiuscole | tag e attributi indifferenti | distinte | distinte nelle chiavi |
| chiusura | opzionale per alcuni (<li>, <p>), assente per i vuoti (<br>) |
sempre obbligatoria | non applicabile |
| attributi | anche senza valore (required) o senza virgolette |
sempre nome="valore" |
non esistono |
| tipi di dato | no (solo testo) | solo con XML Schema | stringhe, numeri, booleani, null, oggetti, array |
| schema | no | DTD, XSD | no standard in RFC 8259 |
JSON (RFC 8259, descritto in Web service, XML, JSON, SOAP e RESTUn web service e' un servizio software accessibile via rete da altri programmi, con messaggi in formato standard su HTTP; i formati di dati sono XML (marcatori annidati, attributi, namespace, validazione con XSD) e JSON (RFC 8259: oggetti, array, stringhe, numeri, true, false, null; piu' compatto e diretto per i linguaggi di programmazione); SOAP e' un protocollo di messaggi XML (Envelope con Header facoltativo e Body, Fault per gli errori) inviati di solito con una POST HTTP e descritti da un file WSDL; REST e' uno stile architetturale (Fielding) in cui il servizio espone risorse identificate da URI e le manipola con i metodi HTTP: GET legge, POST crea, PUT sostituisce, PATCH modifica, DELETE elimina, con codici di stato significativi (200, 201 con Location, 204, 400, 404, 409), senza stato sul server, con cache e interfaccia uniforme.Web service, XML, JSON, SOAP e REST →) è oggi il formato normale per i dati scambiati fra pagina e server. Una prenotazione dell'esempio:
{"id": "p1", "aula": "a1", "giorno": "2026-10-19", "ora_inizio": "09:00", "ora_fine": "11:00", "studente": "Rossi"}Che cosa si perde o cambia passando da XML a JSON:
- attributi ed elementi figli diventano la stessa cosa, chiavi di un oggetto (qui
id,aulaegiornohanno lo stesso aspetto): la distinzione va decisa per convenzione; - l'ordine dei figli in XML conta, quello delle chiavi di un oggetto JSON no (è un array a conservarlo);
- elementi ripetuti diventano un array, ma un singolo elemento diventa un oggetto, non un array di uno: formati incoerenti se si converte meccanicamente;
- contenuto misto (testo con tag nel mezzo, come
Portare <em>il proprio</em> portatile) non ha un equivalente naturale; - numeri e booleani sono nativi in JSON (
80), testo in XML ("80"); - namespace, commenti, istruzioni di elaborazione non esistono.
Quando si sceglie XML: documenti con testo misto, formati con schema e validazione rigorosa, i file di configurazione dell'ecosistema Java (web.xml delle servlet, pom.xml di Maven), SVG, MathML, SOAP. Quando si sceglie JSON: API tra browser e server, perché JSON.parse lo trasforma in oggetti JavaScript in una riga (JavaScript - linguaggio, DOM ed eventiJavaScript (standard ECMAScript, Ecma-262) è il linguaggio dei browser: tipizzato dinamicamente, con sette tipi primitivi (number, string, boolean, undefined, null, bigint, symbol) e gli oggetti (anche array e funzioni); typeof null vale "object" per un errore storico; == converte i tipi, === no (si usa sempre ===); valori falsy: false, 0, 0n, "", null, undefined, NaN. let e const hanno visibilità di blocco e una zona morta prima della dichiarazione, var visibilità di funzione e hoisting; const impedisce di riassegnare il nome, non di modificare l'oggetto. Funzioni: dichiarazione (hoisted), espressione, arrow function (this lessicale), parametri predefiniti, rest e spread, destructuring. Array: map, filter, reduce, find, some, every, sort (senza comparatore ordina come stringhe). Closure: una funzione ricorda le variabili dell'ambiente in cui è nata. Eventi: addEventListener; propagazione in tre fasi (cattura, target, bolla), stopPropagation, preventDefault, delegazione con event.target e closest. DOM: albero di nodi; querySelector, createElement, append, replaceChildren, textContent (sicuro) contro innerHTML (rischio di XSS), classList, dataset. Moduli ES (type="module", import e export) sono differiti e in modalità strict. Event loop: un solo thread, call stack, coda dei task (setTimeout, eventi) e coda dei microtask (promise, await) svuotata dopo ogni task: l'esecuzione asincrona (fetch, async e await, Promise.all) è alla base di AJAX e il codice lungo blocca la pagina.JavaScript - linguaggio, DOM ed eventi →).
Errori tipici
- Dire che un documento è "valido" quando è solo ben formato (o viceversa).
- Tag di apertura e di chiusura con maiuscole diverse (
<Studente>...</studente>). &non scritto come&(per esempio "Rossi & Bianchi" nel testo).- Due elementi radice, o testo/elementi dopo la radice.
- Valori di
IDche iniziano con una cifra (id="1") o ripetuti. - Dimenticare
#REQUIREDo il tipoIDREFnella DTD, e credere che l'IDREFcontrolli il tipo dell'elemento puntato. - Attesa di un controllo dei tipi dalla DTD:
giornoaccetta qualunque testo. - Pensare che un attributo senza prefisso erediti il namespace predefinito.
- Usare
xs:timecon ore senza secondi. - Aspettarsi dal parser HTML lo stesso rigore di un parser XML (e viceversa).
Domande d'esame
- Che differenza c'è fra documento XML ben formato e valido? Fare un esempio di documento ben formato ma non valido rispetto a una DTD. Ben formato: rispetta la sintassi XML (un'unica radice, annidamento, attributi fra virgolette, entità). Valido: in più rispetta lo schema (DTD o XSD). Esempio: una
prenotazionesenzaora_fine, oppure conaula="a9"che non corrisponde a nessunID. - Scrivere una DTD per un elenco di aule con nome e posti, dove ogni prenotazione fa riferimento a un'aula.
<!ELEMENT prenotazioni (aula+, prenotazione*)>,aulacon attributoid ID #REQUIRED,prenotazioneconaula IDREF #REQUIREDe figli in sequenza (soluzione completa nel testo e in Esercizio - XML ben formato e valido con una DTD per le prenotazioni (applicazione web)). - Perché si usa XML Schema al posto della DTD? A che cosa servono i namespace? Quando si preferisce JSON? XSD ha tipi, restrizioni, key/keyref e namespace ed è in XML. I namespace evitano i conflitti di nomi fra vocabolari diversi, associando i nomi a un URI. JSON è più compatto e si legge direttamente in JavaScript: per i dati scambiati con il server; XML per documenti con contenuto misto e configurazioni.
Versione ripasso
Genealogia. SGML (ISO 8879, 1986) = metalinguaggio con DTD. HTML fino a 4.01 = applicazione SGML. XML 1.0 (W3C, 1998) = sottoinsieme semplificato di SGML. HTML5 = parser proprio, tollerante, né SGML né XML. Markup descrittivo: separa contenuto e presentazione.
Ben formato (errore fatale per il parser XML):
- un'unica radice;
- tag chiusi e annidati;
- maiuscole e minuscole distinte;
- attributi tra virgolette, mai ripetuti, senza
<; - entità
< > & " '(o CDATA); - dichiarazione
<?xml ...?>all'inizio, senza spazi prima.
Valido = ben formato + conforme a uno schema.
DTD.
<!ELEMENT e (a, b)>sequenza;(a | b)scelta;? * +cardinalità;(#PCDATA)testo;EMPTY,ANY;(#PCDATA | em)*contenuto misto.<!ATTLIST e nome tipo default>: tipiCDATA,ID(unico),IDREF, enumerazione; default#REQUIRED,#IMPLIED,#FIXED.- Esempio:
<!ELEMENT prenotazioni (aula+, prenotazione*)>;aula id ID #REQUIRED posti CDATA #REQUIRED;prenotazione id ID #REQUIRED aula IDREF #REQUIRED. - Un
IDnon comincia con una cifra:a1,p1. - Limiti: niente tipi, niente
ora_fine > ora_inizio,IDREFsenza tipo del bersaglio, niente namespace.
XML Schema.
- È scritto in XML. Tipi
xs:date,xs:positiveInteger;minOccurs/maxOccurs;xs:restrictionconxs:pattern. xs:key/xs:keyref= chiave e chiave esterna tipizzata.xs:timevuole i secondi: per09:00serve un pattern.- I vincoli fra valori li controlla l'applicazione.
Namespace. xmlns:pr="URI" lega un prefisso a un URI identificatore; xmlns="URI" è il namespace predefinito; gli attributi senza prefisso non hanno namespace.
XML, HTML, JSON. HTML: vocabolario fisso, tollerante. XML: libero, rigido, per documenti e configurazioni (web.xml, pom.xml). JSON (Web service, XML, JSON, SOAP e RESTUn web service e' un servizio software accessibile via rete da altri programmi, con messaggi in formato standard su HTTP; i formati di dati sono XML (marcatori annidati, attributi, namespace, validazione con XSD) e JSON (RFC 8259: oggetti, array, stringhe, numeri, true, false, null; piu' compatto e diretto per i linguaggi di programmazione); SOAP e' un protocollo di messaggi XML (Envelope con Header facoltativo e Body, Fault per gli errori) inviati di solito con una POST HTTP e descritti da un file WSDL; REST e' uno stile architetturale (Fielding) in cui il servizio espone risorse identificate da URI e le manipola con i metodi HTTP: GET legge, POST crea, PUT sostituisce, PATCH modifica, DELETE elimina, con codici di stato significativi (200, 201 con Location, 204, 400, 404, 409), senza stato sul server, con cache e interfaccia uniforme.Web service, XML, JSON, SOAP e REST →): dati, niente attributi né contenuto misto né ordine delle chiavi. DOMParser con "application/xml" segnala gli errori con un elemento parsererror.
Errori tipici
- Confondere ben formato e valido.
&senza&; tag con maiuscole diverse.IDche comincia con una cifra o ripetuto.- Aspettarsi tipi dalla DTD.
- Attributo che "eredita" il namespace.
Contesto: Architettura delle applicazioni web - browser, server web e livelliUn'applicazione web è distribuita su più livelli (tier): presentazione (browser: HTML, CSS, JavaScript), logica applicativa (server web e application server) e dati (DBMS). Il client invia richieste HTTP, il server risponde; HTTP è senza stato, quindi lo stato dell'utente viaggia in cookie e sessioni. Il web server serve file statici, l'application server (container, per esempio Tomcat per le servlet Java) esegue codice che genera risposte dinamiche; spesso il web server fa da reverse proxy davanti all'application server. Il browser trasforma i byte della risposta in una pagina: decodifica, tokenizzazione e costruzione del DOM, CSS che diventa CSSOM, render tree, layout (reflow), paint e composizione; un script senza defer o async blocca il parsing, il CSS blocca il rendering. Origine = schema + host + porta; la same-origin policy limita ciò che uno script può leggere da altre origini. Web 1.0: pagine generate dal server, ogni azione ricarica la pagina; Web 2.0: AJAX, contenuti degli utenti, servizi REST; Web 3.0: dati con significato esplicito (RDF, linked data).Architettura delle applicazioni web - browser, server web e livelli →, HTML5 - struttura del documento, elementi semantici e formUn documento HTML5 ha la forma doctype (), html con lang, head (meta charset UTF-8, viewport, title, link, script) e body. Il parser HTML5 non dà mai errore: corregge (aggiunge il tbody, chiude i p). Gli elementi semantici (header, nav, main, section, article, aside, footer, figure, time) descrivono il ruolo del contenuto e danno ai lettori di schermo i punti di riferimento; div e span sono neutri. Link: a href (assoluto, relativo, #frammento, mailto), rel e target; immagini con alt obbligatorio. Tabelle: table, caption, thead, tbody, th con scope, td, colspan e rowspan, solo per dati. Form: action, method (GET mette i campi nella query string, per letture idempotenti e ricercabili; POST li mette nel corpo, per modificare lo stato), enctype (application/x-www-form-urlencoded predefinito, multipart/form-data per i file); si invia solo ciò che ha name; label for collega etichetta e campo; tipi di input (text, email, number, date, time, radio, checkbox, hidden...); validazione nativa con required, minlength, maxlength, min, max, step, pattern e type, aggirabile e quindi da ripetere sul server; novalidate la spegne. Accessibilità: lang, alt, label, gerarchia dei titoli, navigazione da tastiera, ARIA solo quando l'HTML nativo non basta.HTML5 - struttura del documento, elementi semantici e form →, JavaScript - linguaggio, DOM ed eventiJavaScript (standard ECMAScript, Ecma-262) è il linguaggio dei browser: tipizzato dinamicamente, con sette tipi primitivi (number, string, boolean, undefined, null, bigint, symbol) e gli oggetti (anche array e funzioni); typeof null vale "object" per un errore storico; == converte i tipi, === no (si usa sempre ===); valori falsy: false, 0, 0n, "", null, undefined, NaN. let e const hanno visibilità di blocco e una zona morta prima della dichiarazione, var visibilità di funzione e hoisting; const impedisce di riassegnare il nome, non di modificare l'oggetto. Funzioni: dichiarazione (hoisted), espressione, arrow function (this lessicale), parametri predefiniti, rest e spread, destructuring. Array: map, filter, reduce, find, some, every, sort (senza comparatore ordina come stringhe). Closure: una funzione ricorda le variabili dell'ambiente in cui è nata. Eventi: addEventListener; propagazione in tre fasi (cattura, target, bolla), stopPropagation, preventDefault, delegazione con event.target e closest. DOM: albero di nodi; querySelector, createElement, append, replaceChildren, textContent (sicuro) contro innerHTML (rischio di XSS), classList, dataset. Moduli ES (type="module", import e export) sono differiti e in modalità strict. Event loop: un solo thread, call stack, coda dei task (setTimeout, eventi) e coda dei microtask (promise, await) svuotata dopo ogni task: l'esecuzione asincrona (fetch, async e await, Promise.all) è alla base di AJAX e il codice lungo blocca la pagina.JavaScript - linguaggio, DOM ed eventi →; esercizio: Esercizio - XML ben formato e valido con una DTD per le prenotazioni (applicazione web). Esempio conduttore in XML. Frammento del documento esportato:
<prenotazioni>
<aula id="a1" posti="80"><nome>Aula A1</nome></aula>
<prenotazione id="p1" aula="a1">
<giorno>2026-10-19</giorno>
<ora_inizio>09:00</ora_inizio>
<ora_fine>11:00</ora_fine>
<studente>Rossi</studente>
</prenotazione>
</prenotazioni>Contenuto della DTD completa.
<!ELEMENT prenotazioni (aula+, prenotazione*)>,<!ELEMENT aula (nome)>,<!ELEMENT prenotazione (giorno, ora_inizio, ora_fine, studente)>.<!ATTLIST aula id ID #REQUIRED posti CDATA #REQUIRED>,<!ATTLIST prenotazione id ID #REQUIRED aula IDREF #REQUIRED>.- Collegamento:
<!DOCTYPE prenotazioni SYSTEM "prenotazioni.dtd">(esterna) oppure[ ... ](interna).
Violazioni che la DTD segnala (ben formato ma non valido): manca un figlio della sequenza, IDREF senza ID (aula="a9"), ID duplicato, attributo #REQUIRED mancante, elemento non dichiarato.
XSD.
<xs:attribute name="posti" type="xs:positiveInteger" use="required"/>
<xs:element name="giorno" type="xs:date"/>
<xs:key name="chiaveAula"> <xs:selector xpath="aula"/> <xs:field xpath="@id"/> </xs:key>
<xs:keyref name="refAula" refer="chiaveAula"> <xs:selector xpath="prenotazione"/> <xs:field xpath="@aula"/> </xs:keyref>Il tipo Ora con xs:pattern ([01][0-9]|2[0-3]):[0-5][0-9] rifiuta 25:00. xs:time richiede i secondi. Né DTD né XSD controllano ora_fine dopo ora_inizio.
Namespace.
<pr:prenotazioni xmlns:pr="http://aule.example.org/ns/prenotazioni"
xmlns:h="http://www.w3.org/1999/xhtml">
<pr:studente>Rossi</pr:studente>
<h:p>Portare <h:em>il proprio</h:em> portatile.</h:p>
</pr:prenotazioni>Il nome completo è la coppia (URI, nome locale); il prefisso è locale. Gli attributi senza prefisso restano senza namespace.
XML contro HTML contro JSON.
| HTML | XML | JSON | |
|---|---|---|---|
| errori | corretti dal parser | fatali | fatali |
| vocabolario | fisso | libero | libero |
| attributi | sì | sì | no |
| tipi | no | con XSD | numeri, booleani, null |
Passando da XML a JSON si perdono: distinzione attributo/elemento, ordine dei figli, contenuto misto, namespace.
Domande d'esame, tracce.
- Ben formato contro valido, con esempio di documento ben formato ma non valido.
- DTD per aule e prenotazioni (Esercizio - XML ben formato e valido con una DTD per le prenotazioni (applicazione web)).
- Perché XSD invece di DTD, a che servono i namespace, quando JSON. Regole della buona formazione, in sintesi.
- Una sola radice.
- Tag chiusi e annidati.
- Nomi con maiuscole e minuscole distinte.
- Attributi tra virgolette, mai ripetuti, senza
<. <e&come entità.- Dichiarazione
<?xml ...?>per prima.
Modelli di contenuto della DTD.
| modello | significato |
|---|---|
EMPTY, ANY |
nessun contenuto, qualunque contenuto |
(#PCDATA) |
solo testo |
(a, b) |
sequenza ordinata |
(a | b) |
scelta |
a?, a*, a+ |
zero o uno, zero o più, uno o più |
(#PCDATA | em)* |
contenuto misto |
Attributi: tipi CDATA, ID, IDREF, enumerazione; default #REQUIRED, #IMPLIED, #FIXED.