HTML czy XHTML

Włodzimierz Gajda

W chwili obecnej (kwiecień 2006) w Internecie obowiązują dwa języki: starzejący się już HTML oraz zastępujący go XHTML. Artykuł jest próbą odpowiedzi na dwa pytania: Którego z języków używać? Jak przygotowywać strony WWW zgodne ze standardami?

1 lipca 2006 r.

Spis treści

  1. 1. Język HTML
  2. 2. Język XHTML
  3. 3. XHTML zgodny z HTML
    1. 3.1. Wielkość liter
    2. 3.2. Elementy puste i niepuste
    3. 3.3. Znaczniki opcjonalne
    4. 3.4. Cudzysłowy otaczające wartości atrybutów
    5. 3.5. Minimalizacja atrybutów logicznych
    6. 3.6. Identyfikator fragmentu
    7. 3.7. Style i skrypty
    8. 3.8. Encje
    9. 3.9. Błędy HTML 4.01 strict
  4. 4. Dokumenty HTML/XHTML w sieci WWW
    1. 4.1. Content-type
    2. 4.2. Czy to HTML czy XHTML?
    3. 4.3. Jak przeglądarka traktuje dokument HTML, a jak XHTML?
    4. 4.4. Po czym przeglądarka rozpoznaje język dokumentu?
    5. 4.5. Nagłówek Content-type dokumentu HTML oraz XHTML
    6. 4.6. Problemy z Internet Explorerem
  5. 5. Strona XHTML wysyłana jako application/xhtml+xml
    1. 5.1. Zmiana nagłówków wysyłanych przez serwer Apache
    2. 5.2. Wysyłanie nagłówka HTTP w PHP
    3. 5.3. Style CSS
  6. 6. Warunkowa modyfikacja typu dokumentu
    1. 6.1. Negocjacja zawartości
    2. 6.2. Parsing nagłówka HTTP ACCEPT
    3. 6.3. Warunkowe wysyłanie typów text/html application/xhtml+xml
  7. 7. Wymiana zawartości
    1. 7.1. Kłopot z deklaracją XML
    2. 7.2. Kłopot z kodowaniem znaków
  8. 8. Cztery proste zasady
  9. 9. HTML czy XHTML
    1. 9.1. Rozwiązanie 1
    2. 9.2. Rozwiązanie 2
    3. 9.3. Rozwiązanie 3
    4. 9.4. Rozwiązanie 4
    5. 9.5. Rozwiązanie 5

1. Język HTML

Rozwój języka HTML został wstrzymany w roku 1999. Wtedy to ukazała się ostatnia specyfikacja języka, zatytułowana HTML 4.01 Specification, opisująca język HTML w wersji 4.01.

Dokument ten sygnalizował w wielu miejscach trendy, jakie zaczynały obowiązywać w dziedzinie publikacji internetowych. Głównie chodzi o oddzielenie prezentacyjnych cech witryny od jej struktury (poprzez stosowanie stylów).

Specyfikacja definiuje trzy dialekty języka: strict, transitional oraz frameset. Wprawdzie w żadnym miejscu dokumentu nie jest to jasno powiedziane, ale moim zdaniem należy się skupić na języku HTML 4.01 w wersji strict. Jest to szczególnie ważne, gdy myślisz przyszłościowo o tworzeniu witryn WWW i planujesz publikowanie stron zgodnych ze standardami. Treść dokumentów HTML 4.01 strict oraz XHTML 1.0 strict różni się siedmioma drobnymi szczegółami.

Wcześniejsze wersje języka HTML, poprzedzające HTML 4.01, odeszły do lamusa i nie należy ich stosować.

2. Język XHTML

Specyfikacja języka XHTML 1.0 jest datowana na 26 stycznia 2000 roku. Dokument ten w podtytule jest określony jako A Reformulation of HTML 4 in XML 1.0. Z tego wynika pewien dość oczywisty wniosek: język XHTML nie jest nowym językiem a jedynie modyfikacją języka HTML. Ponadto we wstępie specyfikacji XHTML (strona 1, akapit Abstract, drugie zdanie) zawarto stwierdzenie:

„The semantics of the elements and their attributes are defined in the W3C Recommendation for HTML 4. ”

Konsekwencje powyższego stwierdzenia są istotne. Oznacza ono bowiem, że w specyfikacji języka XHTML nie opisano żadnego ze znaczników. Szukając opisu elementów, ich atrybutów oraz zdarzeń musimy zajrzeć do specyfikacji języka HTML.

Specyfikacja XHTML 1.0 definiuje jedynie zmiany, jakie należy wprowadzić w dokumencie HTML by stał się on dokumentem XHTML.

Podobnie jak HTML 4.01, również język XHTML 1.0 posiada trzy dialekty strict, transitional oraz frameset. Tak jak w przypadku HTML najlepiej stosować wersję strict.

W chwili obecnej dostępne są wersje języka XHTML: 1.0, 1.1 oraz 2.0. Z racji na swoje surowe wymagania (każdy dokument XHTML 1.1 musi być wysyłany jako application/xhtml+xml, XHTML 2.0 nie jest zgodny w dół z poprzednimi językami) powszechnie stosowana jest wyłącznie wersja 1.0 języka XHTML.

3. XHTML zgodny z HTML

Powszechnie stosowanym rozwiązaniem (zalecanym również przez W3C) jest przygotowywanie dokumentów w języku XHTML w taki sposób, by były one — na ile to możliwe — poprawnymi dokumentami HTML. Wprawdzie pełna zgodność nie jest możliwa, jednak w zasadniczej swojej części (czyli pomiędzy znacznikami <body> oraz </body>) dokumenty w języku XHTML 1.0 strict różnią się od dokumentów HTML 4.01 strict tylko siedmioma szczegółami.

Oto siedem różnic, jakie należy mieć na uwadze. Podane rozwiązania możemy stosować zarówno w językach XHTML jak i HTML.

3.1. Wielkość liter

W języku HTML nazwy znaczników oraz atrybutów mogły być zapisywane dowolnymi literami. Wszystkie poniższe przykłady są poprawne w języku HTML:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<strong>white</strong>
<STRONG>black</STRONG>
<strong>gray</STRONG>
<stRONG>silver</STrong>

Wprawdzie specyfikacja HTML stosuje konsekwentnie do zapisu nazw znaczników duże litery, a do atrybutów — małe. Nie jest to jednak wymóg; decydują o tym jedynie względy estetyczne i upodobanie autorów specyfikacji (konsekwencja autorów zawodzi w odniesieniu do atrybutów wyliczeniowych, które są czasami pisane dużymi, a czasami — małymi literami).

W języku XHTML nazwy znaczników oraz atrybutów muszą być zapisywane małymi literami.

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<strong>white</strong>
<em id="op">black</em>
<a href="index.html">Indeks</a>
<strong onmouseover="fun1();">nothing</strong>
<a id="STR" href="MENU.HTML">Menu</a>

Wartości atrybutów takich jak id czy href, mogą być zapisywane literami dowolnej wielkości. Pamiętaj jednak, że powyższe ograniczenie dotyczy również wartości atrybutów wyliczeniowych. Na przykład typ elementu input należy koniecznie zapisywać małymi literami:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<input type="text" name="IMIE" />
<form action="index.php" method="post">

Poniższy zapis jest poprawny wyłącznie w HTML:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<input type="TEXT" name="IMIE" />
<form action="index.php" method="POST">
lp. Element Atrybut Wartości
lp. Element Atrybut Wartości
1. button type button, submit, reset
2. col, colgroup, tbody, td, tfoot, th, thead, tr valign top, middle, bottom, baseline
3. col, colgroup, tbody, td, tfoot, th, thead, tr align left, center, right, justify, char
4. form method get, post
5. input type text, password, checkbox, radio, submit, reset, file, hidden, image, button
6. param valuetype data, ref, object
7. table frame void, above, below, hsides, lhs, rhs, vsides, box, border
8. table rules none, groups, rows, cols, all
9. td, th scope row, col, rowgroup, colgroup
10. dir ltr, rtl

Tabela 1. Atrybuty o wartościach wyliczeniowych

Uważaj także na wielkość liter w encjach heksadecymalnych. Zapis:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
&#X41;

jest niepoprawny w XHTML. Należy stosować małą literę x:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
&#x41;

Jako ciekawostkę warto zapamiętać, że jednym z niewielu miejsc, gdzie wielkość liter odgrywa rolę są — w języku HTML — właśnie encje. Znak &Aring; jest różny od &aring;!

3.2. Elementy puste i niepuste

W języku HTML pojawiło się pojęcie elementu pustego. Elementami pustymi są między innymi img, br, hr, link oraz meta. Przykłady elementów niepustych to p, em, span czy table.

Elementy puste należy w języku XHTML kończyć dwoma znakami /> zamiast pojedynczego >. Zatem należy pisać:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<img src="" alt="" />
<br />
<hr />
<link rel="stylesheet" type="text/css" href="style.css" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2" />

zamiast:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<img src="" alt="">
<br>
<hr>
<link rel="stylesheet" type="text/css" href="style.css">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">

Zwróćmy uwagę na spację występującą przed znakami />. W XHTML, który ma być za razem poprawnym HTML jest ona konieczna (część przeglądarek HTML-owych nie zrozumie zapisu <br/>). Natomiast pomiędzy końcowymi znakami / oraz > spacja nie może wystąpić.

Znacznik <br /> nie jest poprawny w myśl specyfikacji HTML. Jednakże współczesne oprogramowanie (włącznie z walidatorami W3C) traktuje element <br /> zawarty w dokumencie HTML tak jak poprawny element <BR>. To samo dotyczy pozostałych elementów pustych kończonych znakami />.

Elementy niepuste nie mogą być pisane w taki sposób. Nawet jeśli ich zawartość jest pusta. Zatem zapisem poprawnym jest:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<p></p>
<strong></strong>
<div></div>

Zapisami niepoprawnymi są:

HTML 4.01 strict — niepoprawny
XHTML 1.0 strict — niepoprawny
<p />
<strong />
<div />

Element pusty nie może być zapisywany jako:

HTML 4.01 strict — niepoprawny
XHTML 1.0 strict — niepoprawny
<br></br>
<hr></hr>

3.3. Znaczniki opcjonalne

W języku HTML niektóre znaczniki, na przykład </p> oraz </li>, były opcjonalne. W języku XHTML nie ma znaczników opcjonalnych. Wszystkie znaczniki są obowiązkowe.

Zatem przykład:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<li>Red
<li>Green
<li>Blue

jest niepoprawny w języku XHTML. Należy dodać znaczniki zamykające </li>:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<li>Red</li>
<li>Green</li>
<li>Blue</li>

3.4. Cudzysłowy otaczające wartości atrybutów

Wartości atrybutów w języku HTML możemy pisać otaczając je znakami cudzysłowu lub apostrofami:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<a href="index.html">Indeks</a>
<a href='nowa.html'>Nowa</a>

W języku HTML W niektórych sytuacjach cudzysłowy i apostrofy są zbędne. Poniższy przykład jest poprawny w języku HTML:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<a href=index.html>Indeks</a>
<a href=nowa.html>Nowa</a>
<td rowspan=4 colspan=5 id=opis>

Specyfikacja HTML 4.01 wyraźnie zalecała stosowanie cudzysłowów, nie był to jednak wymóg, a jedynie zalecenie.

W języku XHTML cudzysłowy lub apostrofy są zawsze konieczne (w odniesieniu do każdego atrybutu!):

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<a id="ind" href="index.html">Indeks</a>
<a href='nowa.html'>Nowa</a>
<td rowspan="4" colspan="5" id="opis">

3.5. Minimalizacja atrybutów logicznych

Niektóre atrybuty są nazywane atrybutami logicznymi. Należy do nich na przykład atrybut selected elementu option.

lp. Element Atrybuty logiczne
lp. Element Atrybuty logiczne
1. area nohref
2. button disabled
3. img ismap
4. input checked, disabled, readonly, ismap
5. object declare
6. optgroup disabled
7. option selected, disabled
8. script defer
9. select multiple, disabled
10. textarea disabled, readonly

Tabela 2. Atrybuty o wartościach logicznych

W języku HTML atrybuty logiczne mogą być zapisywane w zminimalizowanej postaci:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<option selected value="pink">Pink colour</option>

Z racji na zgodność ze starszymi przeglądarkami, specyfikacja HTML 4.01 zalecała stosowanie zminimalizowanej postaci atrybutów logicznych.

W języku XHTML atrybuty logiczne należy zawsze zapisywać w pełnej postaci, tzn. jako parę atrybut="wartosc":

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<option selected="selected" value="pink">Pink colour</option>

3.6. Identyfikator fragmentu

W języku HTML możemy stosować dwa rodzaje atrybutów do identyfikacji fragmentu dokumentu. Atrybutami tymi są id oraz name:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
<a name="info" href="info.html">...</a>
<a id="i2" href="info.html">...</a>

W języku XHTML atrybut name jest niepoprawny. Stosuj wyłącznie atrybut id:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
<a id="i2" href="info.html">...</a>

3.7. Style i skrypty

Style CSS oraz skrypty JavaScript, zawierające jedną z czterech poniższych kombinacji znaków:

należy w języku XHTML zapisywać w zewnętrznych plikach .css, .js lub stosować CDATA:

<style type="text/css">
<![CDATA[
div {
    color      : yellow;
    background : red;
}
]]>
</style>

Pamiętaj jednak, że CDATA nie może się pojawić w dokumencie HTML (ani w XHTML wysyłanym jako text/html).

Jeżeli zastosujesz CDATA w statycznym dokumencie .html, to bez względu na to czy go przygotujesz w języku HTML czy XHTML, takie style nie będą działały (pierwsza reguła będzie ignorowana przez MSIE). Jedynym rozwiązaniem, jakie zadziała zarówno w HTML jak i XHTML są zewnętrzne pliki .css oraz .js.

3.8. Encje

Znaki wykorzystywane do zapisu kodu HTML, czyli <, > oraz &, należy zapisywać wyłącznie w postaci encji &lt;, &gt; oraz &amp;.

W języku HTML również było to wymagane, jednak przeglądarki w wielu różnych sytuacjach potrafiły poprawnie zinterpretować znaki <, > oraz &.

W XHTML możemy stosować wyłącznie encje. Pamiętaj o adresach definiujących zmienne w PHP!

HTML 4.01 strict — poprawny
XHTML 1.0 strict — niepoprawny
index.php?imie=Jan&nazwisko=Nowak

Powyższy przykład należy zapisać jako:

HTML 4.01 strict — poprawny
XHTML 1.0 strict — poprawny
index.php?imie=Jan&amp;nazwisko=Nowak

Pamiętaj również, że encje nazwane mogą w XHTML przysporzyć wielu kłopotów. Zawsze poprawnymi znakami są jedynie &lt;, &gt;, &amp; oraz &quot;. Zamiast pozostałych najlepiej stosować unikod lub encje numeryczne.

3.9. Błędy HTML 4.01 strict

Już w języku HTML 4.01 strict wprowadzono liczne obostrzenia, które przybrały formę nakazu. Są nimi:

Ponadto w formie zaleceń pojawiły się wymogi:

lp. Błąd Przykład Firefox Walidator W3C
lp. Błąd Przykład Firefox Walidator W3C
1-1 Wielkość liter w nazwie znacznika <SPAN>A</SPAN> Brak błędu Błąd
1-2 Wielkość liter w nazwie atrybutu <span ID="nic">A</span> Brak błędu Błąd
1-3 Wielkość liter w wartości atrybutu wyliczeniowego method="GET" Brak błędu Błąd
1-4 Wielkość litery x w encji heksadecymalnej &#x41; Błąd Błąd
2-1 Element pusty bez kończącego slasha <br> Błąd Błąd
2-2 Element niepusty z kończącym slashem <p /> Brak błędu Brak błędu
2-3 Element pusty ze znacznikiem zamykającym <br></br> Brak błędu Brak błędu
3-1 Pominięty znacznik opcjonalny <li>kot Błąd Błąd
4-1 Wartość atrybutu otoczona apostrofami <span id='a'> Brak błędu Brak błędu
4-2 Wartość atrybutu bez cudzysłowów i apostrofów <span id=a> Błąd Błąd
5-1 Atrybut logiczny w zminimalizowanej postaci <input checked ... /> Błąd Błąd
6-1 Identyfikator fragmentu: name <span name="a"> Brak błędu Błąd
7-1 Znaki <, & użyte w stylach bez CDATA - Błąd Ostrzeżenie
7-2 Znaki <, & użyte w stylach z CDATA - Brak błędu Brak błędu
7-3 Dokument XHTML 1.0 strict wysyłany jako text/html zawierający CDATA nie jest poprawnie wyświetlany! - Brak błędu Brak błędu
7-4 Dokument HTML 4.01 strict wysyłany jako text/html, znaki <, & użyte w stylach nie stanowią problemu - Brak błędu Brak błędu
8-1 Znak & Hello & Goodbye Błąd Ostrzeżenie
9-1 Nieznany znacznik <ala>KOT</ala> Brak błędu Błąd
9-2 Nieznany atrybut <span ala="ola">KOT</span> Brak błędu Błąd
9-3 Błędne zagnieżdżenie (zachodzące znaczniki) <em><span></em></span> Błąd Błąd
9-4 Niedopuszczalne zagnieżdżenie <pre><hr /></pre> Brak błędu Błąd
9-5 Użycie kontrowersyjnych elementów <b> oraz <i> (specyfikacja HTML odradza ich użycie) <b>A</b>, <i>B</i> Brak błędu Brak błędu
9-6 Użycie przestarzałych elementów <center>C</center> Brak błędu Błąd

Tabela 3. Błędy w kodzie XHTML

4. Dokumenty HTML/XHTML w sieci WWW

Zawartość pliku .html to tylko jeden z etapów przygotowania strony XHTML zgodnej ze standardami. Strony WWW wysyłane przez serwer do przeglądarki są opatrzone dodatkowymi informacjami nazywanymi nagłówkiem HTTP. Nagłówek ten, w normalnych okolicznościach, nie jest widoczny. Możemy go podejrzeć za pomocą opcji Narzędzia → Informacje o stronie w Firefoxie lub skorzystać z wtyczek LiveHTTPHeaders (dla Firefoxa) lub ieHTTPHeaders (dla Internet Explorera).

Szczegóły zapytania HTTP wyświetlane w Firefoxie opcją Narzędzia → Informacje o stronie (zakładka Headers)

Rysunek 1. Szczegóły zapytania HTTP wyświetlane w Firefoxie opcją Narzędzia → Informacje o stronie (zakładka Headers)

Zapytania i odpowiedzi HTTP wyświetlane przez wtyczkę LiveHTTPHeaders Firefoxa

Rysunek 2. Zapytania i odpowiedzi HTTP wyświetlane przez wtyczkę LiveHTTPHeaders Firefoxa

4.1. Content-type

Typ plików na dysku oznaczamy rozszerzeniem. Na podstawie końcówki .txt system wie, że plik dane.txt jest plikiem tekstowym. Natomiast plik o nazwie piosenka.html jest traktowany (na podstawie rozszerzenia) jako dokument w języku HTML.

Podobną rolę w odniesieniu do dokumentów dostępnych w sieci WWW (dokładniej: dokumentów przekazywanych protokołem HTTP) pełni nagłówek Content-type. Nagłówek ten jest wysyłany wraz z każdym plikiem pobieranym z serwera WWW. Jeśli odwiedzamy stronę http://www.example.com/piosenka.html, to serwer wyśle, wraz z kodem HTML strony, nagłówek, który może być następujący:

Content-type: text/html;charset=iso-8859-2

Nagłówek ten oznacza, że dane powinny być traktowane jako dokument HTML (mówi o tym napis text/html), w którym znaki zakodowano w standardzie iso-8859-2.

Obrazy PNG są oznaczane jako:

Content-type: image/png

zaś style CSS:

Content-type: text/css

I tak dalej. To na podstawie takiego właśnie nagłówka przeglądarka wie, z jakim rodzajem danych ma do czynienia.

I tutaj docieramy do zasadniczej sprawy na temat języka XHTML. Dokumenty przygotowywane w języku XHTML należy oznaczyć jednym z trzech typów przeznaczonych dla języka XML:

application/xhtml+xml
application/xhtml
application/xml

Zalecany jest pierwszy z nich: application/xhtml+xml.

Dokumenty w języku HTML wysyłamy zawsze wyłącznie jako:

text/html

4.2. Czy to HTML czy XHTML?

Po czym rozpoznajemy język, w jakim przygotowano dokument? Do tego służy deklaracja DOCTYPE. Zawartość dokumentu powinna być zgodna z podanym typem.

Jeżeli ograniczymy się do wersji strict języków (X)HTML, to pozostają trzy dostępne typy dokumentów:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

Najlepiej wykorzystywać deklaracje DOCTYPE w identycznej postaci, gdyż niekiedy odstępstwa mogą powodować przejście przeglądarki w tryb pracy określany terminem quirks mode. W przypadku, gdy brakuje deklaracji DOCTYPE, wówczas dokument jest zazwyczaj traktowany jako HTML 4.01 transitional.

4.3. Jak przeglądarka traktuje dokument HTML, a jak XHTML?

Znana od zarania internetu zasada interpretacji HTML-a za wszelką cenę przestaje obowiązywać. Do niedawna przeglądarka, po pobraniu dokumentu, starała się za wszelką cenę wyświetlić wszystko, co potrafi, a ignorowała nieznane jej znaczniki.

Niepoprawny kod HTML, testowany jedynie pod względem wyglądu w przeglądarce, bywa określany w angielskich dokumentach jako html sup — zupa HTML-owa. Najtrafniejszym polskim określeniem wydaje mi się — użyty na stronie http://pornel.net/xhtml — termin po<b>a<br>any HTML.

Strony zgodne ze standardami stosują zupełnie odmienne reguły. Kod (X)HTML nowoczesnej strony WWW powinien być w pełni zgodny ze stosowanym językiem. Nie tylko nie wolno używać znaczników, które nie występują w definicji języka, ale trzeba je poprawnie zagnieżdżać.

Czy jest to ważne dla przeglądarki? Tak. Współczesne przeglądarki inaczej traktują strony przygotowane w języku HTML, a inaczej strony XHTML.

Dokumenty HTML są przez przeglądarki traktowane — tak jak na początku — z przymrużeniem oka. Przeglądarka stara się poprawnie wyświetlić stronę nawet, jeśli jest ona pełna błędów i nieznanych znaczników.

Natomiast dokument XHTML musi być poprawny, w przeciwnym razie nie zostanie w ogóle wyświetlony. Przypomina to proces kompilacji programu komputerowego: najmniejszy błąd składniowy (np. użycie znaku & zamiast encji &amp;, czy brak zamykającego znacznika </li>) spowoduje, że przeglądarka wyświetli wyłącznie komunikat o błędzie!

<!DOCTYPE ...>
<html xmlns= ...>
  <head>
    <title>Wierszyk</title>
  </head>
<body>

<p>Hello & Goodbye!</p>

</body>
</html>

Listing 1. Błąd w kodzie XHTML: użycie znaku & zamiast encji &amp;

Komunikat wyświetlany przez Firefoxa przy przetwarzaniu strony z listingu 1

Rysunek 3. Komunikat wyświetlany przez Firefoxa przy przetwarzaniu strony z listingu 1

4.4. Po czym przeglądarka rozpoznaje język dokumentu?

Język, w jakim przygotowano dokument możemy rozpoznać po deklaracji DOCTYPE. Jednak dla przeglądarki najważniejszy jest nagłówek odpowiedzi HTTP.

Jeżeli w nagłówku tym znajduje się typ:

Content-type: text/html

to strona taka jest traktowana jako HTML bez względu na deklarację DOCTYPE.

Dokumenty, które mają być traktowane jako XHTML muszą być oznaczone typem:

Content-type: application/xhtml+xml

4.5. Nagłówek Content-type dokumentu HTML oraz XHTML

Specyfikacje dostępne na stronach konsorcjum W3C jasno określają, jakimi nagłówkami należy opatrzyć strony WWW.

Jeżeli strona jest wykonana w języku HTML to jedynym poprawnym typem jest text/html.

W przypadku języka XHTML 1.0 zalecanym typem jest application/xhtml+xml. Jednakże dopuszczalne jest (w niektórych sytuacjach) wysyłanie takiego dokumentu jako text/html. Tak wysyłany dokument powinien być maksymalnie zgodny z HTML-em. W Internecie można znaleźć wypowiedzi mówiące, że wysyłanie dokumentu XHTML 1.0 wyłącznie jako text/html (por. artykuł pt. Sending XHTML as text/html Considered Harmful) jest szkodliwe.

Natomiast dokumenty XHTML w wersji od 1.1 wzwyż należy wysyłać wyłącznie jako application/xhtml+xml.

4.6. Problemy z Internet Explorerem

Głównym argumentem przeciwko całkowitemu przejściu na język XHTML jest fakt, że Internet Explorer, nie interpretuje poprawnie dokumentów wysyłanych jako application/xhtml+xml. Jeśli w nagłówku HTTP wystąpi typ:

Content-type: application/xhtml+xml

to na taki dokument Internet Explorer zareaguje wyświetlając okno dialogowe przedstawione na rysunku 3.

Reakcja Internet Explorera na typ application/xhtml+xml

Rysunek 4. Reakcja Internet Explorera na typ application/xhtml+xml

Jeżeli nie chcesz utracić wizyt internautów korzystających z MSIE, musisz — przynajmniej w odniesieniu do wizyt z MSIE — stosować nagłówek text/html. A to oznacza, że w myśl standardów, nie możesz stosować XHTML 1.1 (XHTML 1.1 ma być bezwarunkowo wysyłany jako application/xhtml+xml, bez względu na przeglądarkę).

5. Strona XHTML wysyłana jako application/xhtml+xml

5.1. Zmiana nagłówków wysyłanych przez serwer Apache

Do bezwarunkowej zmiany typu dokumentów o rozszerzeniu .html wysyłanych przez serwer Apache możesz wykorzystać plik .htaccess. Umieść w nim wpis:

AddType application/xhtml+xml;charset=utf-8 .html

5.2. Wysyłanie nagłówka HTTP w PHP

Nagłówek transakcji HTTP możemy w języku PHP ustalić wywołując funkcję header():

header('Content-Type: application/xhtml+xml; charset=utf-8');

5.3. Style CSS

Style dokumentu XHTML wysyłanego jako application/xhtml+xml ustalamy deklaracją XML:

<?xml-stylesheet href="style.css" type="text/css"?>

W przypadku stylów wewnętrznych należy użyć deklarację XML oraz element style:

<?xml-stylesheet href="#internalStyle" type="text/css"?>
<!DOCTYPE ...>
<html xmlns= ...>
  <head>
    <title>Strona...</title>
    <style type="text/css" id="internalStyle">
    div {
        ...
    }
    </style>
  </head>

6. Warunkowa modyfikacja typu dokumentu

Jeśli chcesz stosować język XHTML 1.0 zgodnie z zaleceniami W3C, to powinieneś wysyłać do przeglądarek interpretujących XML (czyli np. do Firefoxa) nagłówek:

Content-type: application/xhtml+xml

zaś do Internet Explorera:

Content-type: text/html

Jest to możliwe dzięki tzw. negocjowaniu zawartości. Weź jednak pod uwagę, że nie da się tego zrobić w gołym (X)HTML (tj. bez PHP, ASP czy innych sztuczek po stronie serwera).

Jeśli zatem robisz strony wyłącznie w języku (X)HTML, nie stosując skryptów działających na serwerze (czyli PHP czy ASP) czy innych technik warunkowej zmiany nagłówka HTTP, to tak przygotowywane dokumenty opatrzone deklaracją DOCTYPE języka XHTML nie będą zgodne z zaleceniami W3C. Otrzymasz w ten sposób dokument XHTML, który jest zawsze wysyłany jako text/html (naruszenie zaleceń podanych w dokumencie XHTML Media Types), lub zawsze wysyłany jako application/xhtml+xml, a zatem, niedostępny dla osób korzystających z Internet Explorera.

6.1. Negocjacja zawartości

Protokół HTTP pozwala przeglądarce na tak zwaną negocjację zawartości. Polega to na tym, iż przeglądarka przekazując zapytanie do serwera zaznacza, jaki rodzaj danych chce otrzymać.

Na przykład Firefox wysyła następujący nagłówek HTTP ACCEPT (odczytany w skrypcie PHP ze zmiennej $_SERVER['HTTP_ACCEPT']):

text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

W nagłówku tym przecinek pełni rolę separatora, zaś poszczególne wpisy mają postać:

typ

lub

typ;q=0.3

Ogólnie, nagłówek ten ma więc postać:

typ,typ;q=x.y,typ,typ,typ;q=x.y,typ;q=x.y,typ,...

Liczba podana po znaku równości jest z zakresu od 0 do 1 i określa preferencje przeglądarki. Brak liczby jest równoważny maksymalnej wartości 1.

Nagłówek wysyłany przez Firefoxa oznacza, że przeglądarka preferuje typy:

text/xml               domyślnie: q=1
application/xml        domyślnie: q=1
application/xhtml+xml  domyślnie: q=1

(brak części q=x.y oznacza, że q wynosi 1) przed:

text/html;q=0.9

W ten sposób Firefox, stosując technikę negocjacji zawartości, zaznacza, że preferuje dokumenty XHTML (typ application/xhtml+xml posiada domyślną wagę q=1) przed dokumentami HTML (typ text/html posiada mniejszą wagę q=0.9).

6.2. Parsing nagłówka HTTP ACCEPT

Do analizy nagłówka HTTP ACCEPT możemy użyć funkcji explode() oraz wyrażeń regularnych. W pliku httpaccept.inc.php znajdziesz funkcję httpaccept_parse(), która jest odpowiedzialna za przetworzenie nagłówka HTTP ACCEPT w tablicę asocjacyjną.

6.3. Warunkowe wysyłanie typów text/html application/xhtml+xml

Jeśli w skrypcie PHP umieścisz kod:

<?php
require_once 'httpaccept.inc.php';
$czy_xhtml = httpaccept_send_header('utf-8');
?>
<!DOCTYPE ...>

to w zależności od przeglądarki, wysłany zostanie nagłówek text/html lub application/xhtml+xml. Informacja o rodzaju wysłanego nagłówka zostaje zapisana w zmiennej $czy_xhtml.

Parametr funkcji httpaccept_send_header() służy do ustalenia kodowania znaków zawartego w nagłówku HTTP.

7. Wymiana zawartości

7.1. Kłopot z deklaracją XML

Deklaracja XML występująca na początku dokumentów XHTML:

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

przysporzy dwóch kłopotów. Po pierwsze koliduje z krótkimi znacznikami PHP, po drugie przełącza Internet Explorera w quirks mode.

Kolizję z krótkimi znacznikami PHP rozwiążesz zmieniając konfigurację PHP. W pliku PHP zmodyfikuj wartość parametru short_open_tag:

short_open_tag = Off

i stosuj wyłącznie pełne znaczniki PHP:

<?php

?>

Problem z Internet Explorerem jest trudniejszy. Chcąc uniknąć trybu quirks mode należałoby zrezygnować z nagłówka XML. Ponieważ nagłówek ten jest opcjonalny, nie stanowi to problemu. Niestety, rozwiązanie nie jest takie proste. Dołączając style do dokumentu XHTML musimy przed deklaracją DOCTYPE umieścić deklarację XML:

<?xml-stylesheet href="style.css" type="text/css"?>
<!DOCTYPE ...>

Ta deklaracja również przestawia Internet Explorera z trybu standardów w tryb quirks mode.

Mamy dwa rozwiązania powyższego problemu: możemy zrezygnować ze stylów lub warunkowo zmienić nagłówek dokumentu:

if ($czy_xhtml) {
    echo '<?xml version="1.0" encoding="utf-8"?>';
    echo '<?xml-stylesheet href="style.css" type="text/css"?>';
}

Niestety warunkowa zmiana zawartości dokumentu, określana mianem cloakingu, pomimo, że działa poprawnie, może być źle widziana przez wyszukiwarki.

7.2. Kłopot z kodowaniem znaków

Kodowanie znaków, podobnie jak i style, wymagają wymiany zawartości.

Dokument XHTML nie wymaga elementu meta. Kodowanie znaków jest ustalone w nagłówku HTTP. Element meta ustalający kodowanie znaków dokumentu HTML nie może być zawarty w dokumencie wysyłanym jako application/xhtml+xml, gdyż pozwala on na przetwarzanie dokumentu jako text/html:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Z drugiej strony, jeśli taki element usuniemy, wówczas dokument traktowany jako text/html nie będzie zawierał poprawnego kodowania (pomimo nagłówka HTTP!).

Jedynym wyjściem, z tego zamkniętego koła, jest podmiana zawartości dokumentu, na podstawie negocjacji zawartości. Zatem kodowanie znaków należy wysyłać warunkowo, w zależności od wysłanego nagłówka:

if (!$czy_xhtml) {
    echo ' <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
}

Kłopot z deklaracją stylów w XHTML jest ściśle praktyczny, gdyż wymusza na przeglądarce MSIE tryb quirks. Element meta dotyczący kodowania znaków nie stwarza realnych trudności. Wprawdzie zezwala on aplikacjom na traktowanie dokumentu jako text/xhtml, jednak nie są mi znane przypadki, kiedy tak by się działo z dokumentem wysyłanym jako application/xhtml+xml.

8. Cztery proste zasady

Myśląc przyszłościowo o tworzeniu witryn WWW warto przestrzegać czterech prostych reguł.

Po pierwsze sprawdzaj poprawność każdego projektu. Możesz do tego wykorzystać na przykład narzędzia dostępne na witrynie W3C. Jeśli do witryny, widocznej w internecie dodasz kod:

<p>
  <a href="http://validator.w3.org/check?uri=referer">HTML</a>
  <a href="http://jigsaw.w3.org/css-validator/check/referer">CSS</a>
</p>

to wystarczy, że klikniesz podane hiperłącza HTML czy CSS, a poprawność kodu zostanie zbadana. Jeszcze prościej poprawność dowolnej strony WWW sprawdzisz wykorzystując Developer Toolbar Firefoxa. Walidację ułatwiają narzędzia zawarte w zakładce Tools.

Możesz też wykorzystać wtyczkę Firefoxa o nazwie HTML Validator. Narzędzie to działa off-line.

Wynik sprawdzenia strony WWW wtyczką Firefoxa HTML Validator

Rysunek 5. Wynik sprawdzenia strony WWW wtyczką Firefoxa HTML Validator

Pamiętaj, że walidatory nie wychwycą wszystkich możliwych błędów, nie należy ich zatem traktować jako ostatecznej wyroczni. Pomogą ci jednak poznać błędy, jakie popełniasz. Nawet, jeżeli nie zdołasz poprawić ich w bieżącym projekcie, to i tak gra jest warta świeczki: kolejne projekty rozpoczniesz dysponując większym doświadczeniem dotyczącym poprawności kodu HTML i CSS.

Wpadki walidatora W3C:

Analiza verbose wykonana przez walidator W3C informuje o typie text/html

Rysunek 6. Analiza verbose wykonana przez walidator W3C informuje o typie text/html

Po drugie należy pracować w trybie standardów, a nie w trybie quirks mode. Tryb pracy Firefoxa jest podany w oknie dialogowym Narzędzia → Informacje o stronie w zakładce Ogólne.

Tryb pracy Firefoxa

Rysunek 7. Tryb pracy Firefoxa

Po trzecie stosuj wersję strict. Każda kolejna wersja HTML czy XHTML była coraz bardziej restrykcyjna. Pracując w wersji strict nie tylko przestrzegasz najsurowszych obowiązujących zasad, ale przygotowujesz się także na niespodzianki, jakie mogą się pojawić w kolejnych wersjach XHTML.

Wreszcie jako ostatnią zasadę, staraj się przygotowywać witryny, których zawartość (pomiędzy znacznikami <body> oraz </body>) będzie zgodna zarówno z HTML jak i XHTML. Wtedy, ewentualna zmiana języka, w jakiej przygotowana jest witryna, sprowadzi się do modyfikacji deklaracji DOCTYPE (lub ewentualnie całego nagłówka strony, czyli wszystkiego powyżej <body>) oraz zmiany nagłówka Content-type protokołu HTTP.

Przygotowując witryny WWW przestrzegam jeszcze jednej, moim zdaniem ważnej, zasady. Każdy kolejny projekt, ma stanowić przynajmniej mały krok w kierunku przestrzegania standardów. Staram się wyciągać wnioski z popełnianych błędów i unikać ich w kolejnych projektach.

9. HTML czy XHTML

Jak już powiedziałem, treść strony, zawarta pomiędzy znacznikami <body> oraz </body>, powinna być zgodna (przynajmniej w sensie walidatorów W3C) zarówno z HTML 4.01 strict jak i z XHTML 1.0 strict.

Niechlujne zamykanie znaczników, stosowanie znaków & zamiast encji, używanie liter dużych i małych w nazwach znaczników czy korzystanie z przestarzałych elementów to już internetowe średniowiecze. Wprawdzie ogromna większość witryn zawiera niepoprawny kod HTML, jednakże były one przygotowywane w czasach, gdy standardy nie obowiązywały, a przynajmniej nie były tak popularne.

Nikt nie poprawi osiemdziesięciu miliardów witryn WWW dostępnych w internecie. Należy zadbać o to, by nowo powstające witryny były coraz bardziej zgodne ze standardami, a starsze poprawiać w miarę możliwości.

Gdy zgodzisz się ze mną, że treść witryny zawarta pomiędzy <body> oraz </body> powinna być zgodna zarówno z HTML 4.01 strict jak i XHTML 1.0 strict, to decyzja dotycząca języka, w jakim przygotowujesz stronę WWW, dotyczy wyłącznie nagłówka witryny oraz nagłówków protokołu HTTP.

9.1. Rozwiązanie 1

Język, nagłówek HTTP:

ZALETY:

WADY:

9.2. Rozwiązanie 2

Język, nagłówek HTTP:

ZALETY:

WADY:

9.3. Rozwiązanie 3

Język, nagłówek HTTP:

W czasie tworzenia witryny (witryna niedostępna publicznie) stosujemy nagłówki XHTML, deklarację XML i Content-type application/xhtml+xml. Wymaga to wymiany wyłącznie nagłówka strony WWW i protokołu HTTP.

ZALETY:

WADY:

9.4. Rozwiązanie 4

Język, nagłówek HTTP:

Stosujemy drobny cloaking: podmieniamy nagłówek strony, chodzi głównie o usunięcie deklaracji XML. Ma to na celu wymuszenie trybu standardów w przeglądarce MSIE.

ZALETY:

WADY:

9.5. Rozwiązanie 5

Język, nagłówek HTTP:

ZALETY:

WADY:

lp. Zawartość Plik
lp. Zawartość Plik
1. Specyfikacja języka HTML 4.01 .pdf
2. XHTML Basic .pdf
3. Specyfikacja języka XHTML 1.0 .pdf
4. Specyfikacja języka XHTML 1.1 .pdf
5. Associating Style Sheets with XML Documents .pdf
6. HTML FAQ .pdf
7. XHTML Media Types .pdf
8. RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1 .txt
.pdf
9. RFC 2854: The 'text/html' Media Type .txt
10. RFC 3023: XML Media Types .txt
11. RFC 3226: The 'application/xhtml+xml' Media Type .txt

Tabela 4. Specyfikacje

lp. Tytuł Adres
lp. Tytuł Adres
1-1 HTML and XHTML Frequently Answered Questions http://www.w3.org/MarkUp/2004/xhtml-faq
1-2 XHTML 1.0 The Extensible HyperText Markup Language (Second Edition) http://www.w3.org/TR/xhtml1/
1-3 XHTML Media Types http://www.w3.org/TR/xhtml-media-types/xhtml-media-types.html
1-4 XHTML Basic http://www.w3.org/TR/2000/REC-xhtml-basic-20001219/
1-5 XHTML 1.1 - Module-based XHTML http://www.w3.org/TR/2001/REC-xhtml11-20010531/
1-6 Associating Style Sheets with XML documents http://www.w3.org/1999/06/REC-xml-stylesheet-19990629/
1-7 HTML 4.01 Specification http://www.w3.org/TR/1999/REC-html401-19991224/
1-8 XHTML 2.0 http://www.w3.org/TR/xhtml2/
2-1 Hypertext Transfer Protocol - HTTP/1.1 http://www.rfc-editor.org/rfc/rfc2616.txt
2-2 The 'text/html' Media Type http://www.rfc-editor.org/rfc/rfc2854.txt
2-3 The 'application/xhtml+xml' Media Type http://www.rfc-editor.org/rfc/rfc3236.txt
2-4 XML Media Types http://www.rfc-editor.org/rfc/rfc3023.txt
3-1 Henri Sivonen's pages http://hsivonen.iki.fi/
3-2 XHTML: What's the Point? http://hsivonen.iki.fi/xhtml-the-point/
3-3 Things to Take into Account When Moving to Standards-Compliant HTML and CSS Authoring http://hsivonen.iki.fi/standards/
3-4 HOWTO Spot a Wannabe Web Standards Advocate http://hsivonen.iki.fi/wannabe/
4-1 Po czym rozpoznać "standardowego" łebmajstra? http://3cc.pl/archive/2006/01/jtz-po-czym-rozpoznac-standardowego-lebmajstra/
5-1 Sending XHTML as text/html Considered Harmful http://hixie.ch/advocacy/xhtml
6-1 Content Negotiation - raz a dobrze http://www.doktorno.boo.pl/index.php?q=art008
7-1 Kurs tworzenia stron WWW http://kurs.browsehappy.pl/
8-1 Irracjonalne uwielbienie dla XHTML http://pornel.net/xhtml
9-1 XML on the Web Has Failed http://www.xml.com/pub/a/2004/07/21/dive.html
9-2 The Road to XHTML 2.0: MIME Types http://www.xml.com/pub/a/2003/03/19/dive-into-xml.html
10-1 Beware of XHTML http://www.webdevout.net/articles/beware_of_xhtml.php
11-1 Better Living Through XHTML http://www.alistapart.com/articles/betterliving/
11-2 Fix Your Site With the Right DOCTYPE! http://www.alistapart.com/stories/doctype/
12-1 Walidator HTML/XHTML W3C http://validator.w3.org
12-2 Walidator CSS W3C http://jigsaw.w3.org/css-validator
12-3 XML schema validator http://schneegans.de/sv/
13-1 Behind the Scenes with XHTML http://www.webreference.com/authoring/xhtml/coding/
13-2 Why Switch to XHTML? http://www.webreference.com/authoring/xhtml/
14-1 The perils of using XHTML properly http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/
15-1 Serving up XHTML with the correct MIME type http://keystonewebsites.com/articles/mime_type.php

Tabela 5. Dokumenty w internecie

lp. Nazwa Adres Pobierz
lp. Nazwa Adres Pobierz
1. LiveHTTPHeaders (wtyczka Firefoxa) http://livehttpheaders.mozdev.org/installation.html livehttpheaders-0.12.xpi
2. ieHTTPHeaders (wtyczka Internet Explorera) http://www.blunck.info/iehttpheaders.html ieHTTPHeadersSetup.exe
3. HTML Validator https://addons.mozilla.org/extensions/moreinfo.php?id=249&application=firefox html_validator-0.7.9-fx+mz-windows.xpi

Tabela 6. Oprogramowanie

lp. Opis Pobierz
lp. Opis Pobierz
1-1 Wysyłanie dokumentu jako application/xhtml+xml, iso-8859-2, zmiana typu w pliku .htaccess .zip
1-2 Wysyłanie dokumentu jako application/xhtml+xml, utf-8, zmiana typu w pliku .htaccess .zip
2-1 Wysyłanie dokumentu jako application/xhtml+xml, iso-8859-2, funkcja header() w PHP .zip
2-2 Wysyłanie dokumentu jako application/xhtml+xml, utf-8, funkcja header() w PHP .zip
3-1 Błędy w XHTML wysyłanym jako application/xhtml+xml .zip
4-1 Style zewnętrzne w XHTML wysyłanym jako application/xhtml+xml .zip
4-2 Style wewnętrzne w XHTML wysyłanym jako application/xhtml+xml .zip
5-1 Negocjacja zawartości: badanie nagłówka HTTP ACCEPT .zip
5-2 Negocjacja zawartości: warunkowe wysyłanie dokumentu XHTML jako text/html (do IE) oraz jako application/xhtml+xml (do FF)
6-1 Witryna pt. Step one wykonana w XHTML bezwarunkowo wysyłana jako application/xhtml+xml .zip
6-2 Witryna pt. Rzeżucha wykonana w XHTML bezwarunkowo wysyłana jako application/xhtml+xml .zip
7-1 Witryna pt. Step one wykonana w XHTML wysyłana jako text/html do IE oraz jako application/xhtml+xml do FF .zip
7-2 Witryna pt. Rzeżucha wykonana w XHTML wysyłana jako text/html do IE oraz jako application/xhtml+xml do FF .zip

Tabela 7. Przykłady omówione w artykule

Artykuł pochodzi ze strony http://www.gajdaw.pl