Salta al contenuto
Note per Studenti Linguaggi di markup - SGML, HTML e XML

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).

  1. C'è un solo elemento radice; prima e dopo possono esserci solo commenti, istruzioni di elaborazione e spazi.
  2. Ogni tag di apertura ha il suo tag di chiusura (o è vuoto: <br/>), gli elementi sono annidati correttamente (<a><b></b></a>).
  3. 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, -, _, ..
  4. 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 <.
  5. I caratteri < e & nel testo si scrivono con le entità predefinite: &lt; &gt; &amp; &quot; &apos;; per un blocco di testo grezzo c'è <![CDATA[ ... ]]>.
  6. 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
<?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 identificatori a1, 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 posti stanno in un attributo (metadati dell'elemento), altre come studente in 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.

xml
<!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 un ID che deve esistere; IDREFS per 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

dtd
<!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 prenotazioni contiene almeno un'aula (aula+) seguita da zero o più prenotazioni (prenotazione*): le aule vanno prima, perché la sequenza è ordinata.
  • aula ha un elemento nome e due attributi obbligatori: id di tipo ID (unico), posti testo.
  • prenotazione ha quattro figli in questo ordine; aula di tipo IDREF è 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'IDREF può puntare anche a p1).

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_fine dopo ora_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
<?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 parola xs:... è un costrutto dello schema.
  • xs:sequence è la sequenza ordinata, maxOccurs="unbounded" è il "più volte"; aula ha minOccurs 1 (valore predefinito) e maxOccurs="unbounded" (come + della DTD), prenotazione ha minOccurs="0" (come *).
  • xs:key / xs:keyref esprimono chiave e chiave esterna con un tipo preciso: aula di una prenotazione deve valere l'id di un elemento aula, non di un altro. È la versione corretta del vincolo che la DTD fa con IDREF.
  • xs:positiveInteger rifiuta posti="0" o "molti"; xs:date accetta solo AAAA-MM-GG (2026-10-19 sì, 19/10/2026 no).
  • Perché non xs:time? xs:time richiede i secondi (09:00:00): con 09:00 il documento sarebbe invalido (verificato con il validatore del JDK 21). Si definisce il tipo Ora con un pattern (espressione regolare ore:minuti); un'ora 25:00 viene rifiutata.
  • Lo schema ancora non controlla che ora_fine sia dopo ora_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.

xml
<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 prefisso pr all'URI; il nome completo di pr: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:p e h:em appartengono 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): id e aula sono 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:

javascript
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 elemento parsererror; va controllato.
  • getAttribute legge un attributo, textContent il 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:

json
{"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, aula e giorno hanno 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 &amp; (per esempio "Rossi & Bianchi" nel testo).
  • Due elementi radice, o testo/elementi dopo la radice.
  • Valori di ID che iniziano con una cifra (id="1") o ripetuti.
  • Dimenticare #REQUIRED o il tipo IDREF nella DTD, e credere che l'IDREF controlli il tipo dell'elemento puntato.
  • Attesa di un controllo dei tipi dalla DTD: giorno accetta qualunque testo.
  • Pensare che un attributo senza prefisso erediti il namespace predefinito.
  • Usare xs:time con ore senza secondi.
  • Aspettarsi dal parser HTML lo stesso rigore di un parser XML (e viceversa).

Domande d'esame

  1. 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 prenotazione senza ora_fine, oppure con aula="a9" che non corrisponde a nessun ID.
  2. Scrivere una DTD per un elenco di aule con nome e posti, dove ogni prenotazione fa riferimento a un'aula. <!ELEMENT prenotazioni (aula+, prenotazione*)>, aula con attributo id ID #REQUIRED, prenotazione con aula IDREF #REQUIRED e figli in sequenza (soluzione completa nel testo e in Esercizio - XML ben formato e valido con una DTD per le prenotazioni (applicazione web)).
  3. 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à &lt; &gt; &amp; &quot; &apos; (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>: tipi CDATA, 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 ID non comincia con una cifra: a1, p1.
  • Limiti: niente tipi, niente ora_fine > ora_inizio, IDREF senza tipo del bersaglio, niente namespace.

XML Schema.

  • È scritto in XML. Tipi xs:date, xs:positiveInteger; minOccurs/maxOccurs; xs:restriction con xs:pattern.
  • xs:key/xs:keyref = chiave e chiave esterna tipizzata.
  • xs:time vuole i secondi: per 09:00 serve 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 &amp;; tag con maiuscole diverse.
  • ID che 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:

xml
<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.

xml
<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.

xml
<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.

  1. Una sola radice.
  2. Tag chiusi e annidati.
  3. Nomi con maiuscole e minuscole distinte.
  4. Attributi tra virgolette, mai ripetuti, senza <.
  5. < e & come entità.
  6. 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.

Esercizi su questo argomento

Teoria collegata