Polyglot aneb webovým kodérem pod obojí

HTML 5

Když se občas na přednáškách ptám, jakou verzi HTML posluchači používají, jsem vždy překvapen tím, že naprostá většina se hlásí k XHTML. Při bližším ohledání stránek tvůrců v XHTML však vyjde najevo, že káží víno a pijí špinavou vodu. Svůj validní XHTML kód podsouvají prohlížeči se špatným MIME typem text/html a nutí jej používat parser HTML. HTML5 přináší některé změny syntaxe, které konečně umožňují tuto praktiku dělat tak, abychom se za ni nemuseli stydět.

Pro začátek si zase připomeneme pár historických faktů. Od počátku webu měly všechny prohlížeče k dispozici parser, který uměl načítat kód HTML a uměl se vypořádat i s běžnými syntaktickými chybami jako byly neukončené či překřížené elementy, neukončené hodnoty atributů atd. Dále v článku mu budeme říkat parser HTML.

S nástupem XHTML se do prohlížečů přidal ještě parser XML. Jakým parserem se stránka bude načítat, řídil MIME typ zasílaný do prohlížeče. Stránky označené pomocí text/html se zpracovávaly pomocí parseru HTML a stránky označené pomocí jednoho z MIME typů application/xhtml+xml, application/xml nebo text/xml se pak načítaly pomocí parseru XML.

Pro zájemce o XHTML vše vypadá jednoduše – napíší kód v XHTML, zajistí jeho odeslání se správným MIME typem a mohou být spokojení. Bohužel to není pravda – dosud stále majoritní prohlížeč Internet Explorer je schopný takovou stránku zobrazit až od 14. března 2011 (ano dva tisíce jedenáct, není to překlep) – data uvedení IE verze 9. Starší verze Internetu Exploreru místo zobrazení stránky zaslané jako application/xhtml+xml nabídly její uložení na disk. Věru nic praktického pro brouzdání po webu.

Jak se tento závažný nedostatek Internet Exploreru v posledních deseti letech řešil? Pragmatici nepřešli na XHTML, ale používali stále dál osvědčené HTML. Konec konců XHTML nepřineslo žádnou novou zajímavou funkcionalitu, kvůli které by stálo za to opustit HTML. Nicméně příchod XHTML byl spojen s několika nereálnými očekáváními a používání XHTML se stalo jistou módou. O praktické fungování XHTML v Internetu Exploreru (a v dalších starších prohlížečích, které nebyly aktualizovány o podporu XHTML) se zasloužila podobnost syntaxí HTML a XHTML.

XHTML dokument je totiž možné načíst pomocí parseru HTML. Spoléhá se přitom na to, že parser HTML umí sám opravit mnohé chyby v kódu. Když například v XHTML dokumentu použijeme <br/>, parser HTML lomítko vyhodnotí jako neznámý atribut a ignoruje jej. Je to poměrně brutální řešení, protože stránka zapsaná XHTML neodpovídá syntaxi HTML a není tak jisté, že všechny prohlížeče pochopí kód stejně a navíc tak, jak jsme chtěli.

Stalo se proto běžnou praxí, že XHTML stránky se odesílají do prohlížeče se špatným MIME typem text/html, aby fungovaly ve všech prohlížečích. V době, kdy to vypadalo, že IE přijde s podporou XHTML dříve než v roce 2011, některé weby dokonce posílaly různým prohlížečům různé MIME typy – alternativní prohlížeče podporující XHTML dostaly správný typ application/xhtml+xml; IE a neznámé prohlížeče pak dostaly zcela stejný dokument označený jako text/html. Dnes se tento přístup již moc nepoužívá – je to práce navíc a občas to zlobí s proxy servery – skoro všichni tak lžou a posílají XHTML jako  text/html.

Zasílání XHTML se špatným MIME typem je v zásadě funkční, ale je potřeba dávat si pozor na některé detaily. Některé syntaktické konstrukce vedou k vytvoření rozdílného objektového modelu (DOM) v prohlížeči, pokud se čtou HTML respektive XML parserem. V praxi se to může projevit lehce odlišným zobrazením nebo chybami při běhu skriptu. Jeden jednoduchý příklad za všechny. Prázdný element <br/> lze v XHTML zapsat i jako:

<br></br>
ukázat DOM

Při načítání pomocí parseru XML se vytvoří jeden element br . Při načítání pomocí parseru HTML se však vytvoří dva elementy br . Součástí specifikace XHTML je příloha C, která na podobné problémy upozorňuje.

Posílání XHTML s MIME typem text/html při dodržení několika pravidel funguje, nicméně bychom z takového přístupu neměli mít dobrý pocit. Prohlížeč nutíme načítat nevalidní HTML a nemáme 100% jistotu, že prohlížeč bude správně interpretovat náš kód.

Východiskem z této nemilé situace je HTML5. Jak jsme si již řekli v minulém článku, HTML5 velice precizně definuje chování parseru HTML, takže se předchází rozdílné interpretaci chybného kódu různými prohlížeči. Navíc byla syntaxe HTML rozšířena tak, aby více odpovídala XML. Jednou z nejviditelnějších změn je povolení lomítka na konci prázdného elementu. Následující kód je tak nyní zcela validní i při použití HTML syntaxe (všimněte si zejména elementů meta a br):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Pokusná stránka</title>
  </head>
  <body>
    <h1>Test<br/>1</h1>
  </body>
</html>
ukázat DOM
Jakou verzi (X)HTML používáte nejvíc?

Navíc vzniká separátní specifikace Polyglot Markup: HTML-Compatible XHTML Documents, jejímž cílem je definovat společnou podmnožinu syntaxe HTML a XML, která zajistí vytvoření stejného DOM při čtení parserem HTML i XML. Díky změnám v syntaxi HTML5 tak polyglot dokument může být zároveň validní HTML dokument a well-formed XML dokument. Konečně tak máme k dispozici postup, jak XHTML5 publikovat s MIME typem text/html a přitom mít výsledek funkční i formálně korektní.

V následují části textu se podíváme na jednotlivá pravidla, která je potřeba dodržet, aby náš dokument byl ten správný polyglot.

Na první pohled je samozřejmě polyglot dokument bližší XHTML5, protože to má striktnější syntaxi než HTML. Pravidla pro polyglot dokumenty tak v podstatě definují podmnožinu syntaktických konstruktů XHTML5 (resp. XML), které lze používat.

Prolog a kódování

Polyglot dokument nesmí obsahovat deklaraci XML:

<?xml version="1.0" encoding="utf-8"?>

Je to dáno tím, že parsery HTML tento konstrukt neznají. Dokument XML bez této deklarace však může používat jen kódování UTF-8 nebo UTF-16. V prostředí internetové komunikace má UTF-16 svoje problémy, takže polyglot dokument musí být vždy uložen v kódování UTF-8. Použité kódování musíme pro parser HTML identifikovat pomocí odpovídajícího elementu meta :

<meta charset="utf-8"/>

V ideálním případě bychom měli kódování indikovat navíc ještě zapsáním speciálního znaku BOM (Byte Order Mark) na začátek souboru.

Nastavení kódování UTF-8+BOM v oblíbeném editoru PSPad

Samotný výběr kódování je jednoduchý, stačí v menu vybrat FormátUTF-8. Aby PSPad zapisoval na začátek souborů v kódování UTF-8 i BOM, musíme aktivovat speciální parametr. Otevřeme dialog pro nastavení programu pomocí NastaveníNastavení programu… a v sekci Program 2 zaškrtneme volbu Ident. byty v kódování UTF-8.

Poznámka

Pokud PSPad používáte i pro editování skriptů PHP v kódování UTF-8, dejte si pozor na to, abyste volbu před prací s PHP zase vypnuli. PHP si bez speciální konfigurace se znakem BOM moc nerozumí.

Na začátku dokumentu musíme uvést deklaraci typu dokumentu ve tvaru:

<!DOCTYPE html>

Deklarace slouží k tomu, aby se při použití parseru HTML přepnul prohlížeč do striktního zobrazovacího režimu, kdy interpretuje kaskádové styly v souladu s doporučeními W3C. Důležité je zachovat správnou velikost písmen u řetězců DOCTYPE a html  – XML na rozdíl od HTML je na tomto místě citlivé na velikost písmen.

Naše dosavadní znalosti můžeme shrnout do jednoduché kostry polyglot dokumentu:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta charset="utf-8"/>
    <title>Pokusná „polyglot“ stránka</title>
  </head>
  <body>
    <p>Příliš žluťoučký kůň úpěl ďábelské ódy</p>
  </body>
</html>
ukázat DOM

Jmenné prostory

Polyglot dokument na rozdíl od plnokrevného XHTML může používat pouze jmenný prostor pro HTML, SVG a MathML. Ten navíc musí být deklarován vždy pouze na elementu html (resp. svg či math) jako výchozí jmenný prostor. V praxi tak musíme deklaraci jmenného prostoru uvádět pouze na elementu html .

<html xmlns="http://www.w3.org/1999/xhtml">

Zápis elementů a atributů

Zatímco v HTML lze názvy elementů a atributů zapisovat libovolně malými i velkými písmeny, případně jejich kombinací, v polyglot dokumentu je nutné vždy používat pouze malá písmena. Takže zatímco v HTML je možné psát následující kód

<P claSS=note>Text</p>
ukázat DOM

V polyglot dokumentu se musíme držet více při zemi

<p class="note">Text</p>
ukázat DOM

Zároveň vidíme, že hodnotu atributů je vždy nutné uzavírat do uvozovek (případně apostrofů).

Syntaxe pro zápis prázdných elementů ( <element/>) musí být používána výhradně pro následující prázdné elementy: area , base , br , col , command , embed , hr , img , input , keygen , link , meta , param , source . Tyto elementy zároveň nesmí být nikdy zapsány jako dvojice počátečního a koncového tagu. Nepřípustné jsou tak například zápisy

<br></br>
<hr></hr>
ukázat DOM

Korektní zápis je

<br/>
<hr/>
ukázat DOM

Pokud máme v dokumentu prázdný jakýkoliv jiný element, musí se naopak zapisovat pomocí počátečního i koncového tagu, tedy místo <p/> musíme vždy použít  <p></p>.

Při použití parseru HTML se do DOMu automaticky doplňující chybějící elementytbody a colgroup . Proto je potřeba vždy řádky tabulkytr obalit odpovídajícím elementem tbody .

U atributů obsahujících logickou hodnotu, se neuvádí jen jméno atributu jako v HTML, ale jako hodnota atributu se uvede jeho jméno. Takže například místo

<input type=checkbox checked>
ukázat DOM

Bude polyglot dokument obsahovat

<input type="checkbox" checked="checked"/>
ukázat DOM

Určení jazyka

Jazyk dokumentu musíme vždy určovat pomocí obou dvou atributů lang a xml:lang najednou, navíc musí vždy obsahovat shodnou hodnotu.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="cs" xml:lang="cs">
  <head>
    <meta charset="utf-8"/>
    <title>Pokusná „polyglot“ stránka</title>
  </head>
  <body>
    <p>Příliš žluťoučký kůň úpěl ďábelské ódy</p>
  </body>
</html>
ukázat DOM

Entity

Polyglot dokument může používat jen pět předdefinovaných entit XML – &lt;, &amp;, &gt;, &apos; a &quot;. Další desítky entit známé z HTML nejsou k dispozici. Speciální znaky tak musíme zapisovat buď přímo, pomocí „chytré“ klávesnice nebo aplikace typu „Mapa znaků“, případně se na znak odvolat jeho číselným kódem Unicode. Tak například znak © dostupný v HTML pomocí entity &copy; můžeme zapsat následujícími třemi způsoby

©
©
©

Bílé znaky

Mezi jazyky HTML a XML existují drobné odlišnosti v chápaní bílých znaků (mezery, tabelátory, konce řádků) a to je potřeba v polyglot dokumentu zohlednit. Obsah elementů textarea a pre musí začínat hned za počátečním tagem bez vloženého konce řádky, jinak se na výstupu objeví prázdný řádek navíc.

Špatný zápis Správný zápis Alternativní správný zápis
<pre>
var x = 10;
window.alert(x);
</pre>
<pre>var x = 10;
window.alert(x);
</pre>
<pre>var x = 10;
window.alert(x);</pre>

Pokud z nějakého důvodu potřebujeme do atributu zapsat znak tabelátoru nebo konce řádku, nemůžeme jej zapsat přímo, ale musíme jej zapsat pomocí odkazu na číselnou entitu.

Skripty a styly

V XHTML a tím pádem ani v polyglot dokumentech se nesmí používat javascriptové volání document.write(). Lze to obejít použitím vlastnosti innerHTML. Pozor však na to, že obsah elementuscript nesmí obsahovat znaky <&.

Důsledkem toho všeho je, že některé „javascriptové kousky“ si musíme v polyglot dokumentech odpustit. Nelze používat  document.write():

<script>
  // nelze použít v polyglot dokumentu
  document.write("<p style='color: blue'>Ahoj</p>");
</script>

Tento skript však nelze obejít ani pomocí innerHTML, protože uvnitř elementu script se nesmí používat <&:

<div id="kontejner"></div>
<script>
  // nelze použít v polyglot dokumentu
  document.getElementById('kontejner').innerHTML = "<p style='color: blue'>Ahoj</p>";
</script>

Podobné případy můžeme obejít pouze ruční konstrukcí DOMu z jednotlivých uzlů, například:

<div id="kontejner"></div>
<script>
  var p = document.createElementNS("http://www.w3.org/1999/xhtml", "p");
  p.setAttribute("style", "color: blue");
  var t = document.createTextNode("Ahoj");
  p.appendChild(t);
  document.getElementById('kontejner').appendChild(p);
</script>

Abychom se všem výše uvedeným problémům vyhnuli, je nejlepší veškeré skripty umístit externě do samostatných souborů a do stránky je načítat pomocí

<script src="URL skriptu">
</script>

Ze stejných důvodů je jistější i kaskádové styly připojovat jako externí pomocí element link .

Pokud používáte XHTML, posílá ho server jako…

Má cenu vytvářet polyglot dokumenty?

Asi vás zklamu, ale většinou ne. Jediný případ je ten, kdy stránky musí jít zpracovat pomocí existujících nástrojů založených na XML. Máte třeba přísný firemní CMS vyžadující použití XHTML, ale zároveň chcete jít s dobou HTML5, pak může mít polyglot dokument své opodstatnění.

Argumentem pro polyglot dokument bývá, že jej lze snadno načítat jako XML a dále zpracovávat. To je pravda, ale upřímně neděje se to tak často. Pokud někdo takové věci potřebuje dělat, může využít některou z existujících implementací parseru HTML5, které dokument HTML vrací jako kdyby to byl XHTML dokument a lze ji předřadit před další řetězec automatického zpracování založeného na XML.

Parsery HTML5 vracející výstup jako XML

Největším uživatelem polyglot dokumentů tak budou patrně ti webmasteři, kteří stále věří XHTML nebo po nich XHTML vyžaduje zákazník. S pravidly pro polyglot dokumenty lze konečně vytvářet stránky, které fungují v prohlížečích a zároveň vyhovují aktuálním specifikacím.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 40

Přehled komentářů

joy BOM je smetí
Jiří Kosek Re: BOM je smetí
Marax Re: BOM je smetí
Pavel Šimerda Re: BOM je smetí
Tomáš Herceg Re: BOM je smetí
František Kučera Re: BOM je smetí
Pavel Šimerda Re: BOM je smetí
Pavel Šimerda Re: BOM je smetí
Franta Meta – charset
Jiří Kosek Re: Meta – charset
Franta Re: Meta – charset
Pavel Šimerda Re: Meta – charset
František Kučera Re: Meta – charset
Pavel Šimerda Re: Meta – charset
Marek Knápek Pořádný standard
Pavel Šimerda Re: Pořádný standard
bauglir Re: Pořádný standard
juraj Re: Pořádný standard
maryo Re: Polyglot aneb webovým kodérem pod obojí
noname takže to shrňme
Pavel Šimerda Re: takže to shrňme
Jiří Kosek Re: takže to shrňme
František Kučera Re: takže to shrňme
Jiří Kosek Re: takže to shrňme
František Kučera Re: takže to shrňme
Pavel Šimerda Re: takže to shrňme
Jiří Kosek Re: takže to shrňme
xerno Re: takže to shrňme
Jiří Kosek Re: takže to shrňme
xerno Re: takže to shrňme
Bedňa Re: Polyglot aneb webovým kodérem pod obojí
maryo Re: Polyglot aneb webovým kodérem pod obojí
Jiří Kosek Re: Polyglot aneb webovým kodérem pod obojí
Honza Tabulátor/Tabelátor
Jiří Kosek Re: Tabulátor/Tabelátor
Jan Prachař Zlatá střední cesta
http://zee.cz/ Parser
Jiří Kosek Re: Parser
http://zee.cz/ Re: Parser
Lojza Článek je jen dalším argumentem pro HTML 4
Zdroj: http://www.zdrojak.cz/?p=3563