XHTML SVG CSS PHP

Dr. O. Hoffmann

PHP-Labor

Mit Eifer hab ich mich der Studien beflissen;
Zwar weiß ich viel, doch möcht ich alles Wissen.
Wagner im Faust von Johann Wolfgang Goethe

XML und PHP

Da es sich bei XML um ein Klartextformat handelt, können mit PHP beliebige XML-Formate sehr einfach dynamisch erzeugt werden. Um aber sicherzustellen, daß wirklich beim Nutzer der passende parser verwendet wird, ist jedoch mit der header-Funktion der korrekte header zu senden. Bei statischen Dateien sollte das ein aktuell und korrekt konfigurierter server selbst erledigen. Ist dies nicht der Fall, der Autor hat aber auf die Konfiguration des servers keinen Einfluß, so kann er immer noch statische Dokument durch ein PHP-Skript per readfile durchschleusen, welches zuvor den korrekten header sendet.

Dabei ist zu bedenken, daß es meist nicht sinnvoll ist, dem Nutzer selbst erfundene Formate anzubieten, die also nicht als Standard spezifiziert sind.

XHTML

XHTML als XML-Dokument ist hingegen als Standard spezifiziert, man bekommt allerdings Probleme mit alten Darstellungsprogrammen wie netscape4 oder msie.
Wenn wir zum Beispiel XHTML-Dokumente nehmen, zwingt auch erst der korrekte header das Darstellungsprogramm des Nutzers dazu, einen XML-parser zu verwenden und nicht etwa den gewöhnlichen SGML/HTML-parser. Dazu ist anzumerken, daß bisherige Darststellungsprogramme für HTML nie in der Lage waren, HTML im Sinne von SGML zu interpretieren, sie haben immer nur Teilbereiche von HTML interpretiert und die Spezifikationen im Sinne einer SGML nie komplett umgesezt. Das ist etwas anders bei Programmen, die in der Lage sind, eine spezifizierte und standardisierte XML zu interpretieren, aufgrund der einfacheren Sprachkonstruktion ist dies viel einfacher möglich als eine Interpretation von HTML, welches zudem historisch schwer belastet ist durch das Problem, daß weltweit über 90% der HTML-Dokument technisch grob fehlerhaft sind und trotzdem der Anspruch besteht, daß grob fehlerhafte Dokument sinnvoll dargestellt werden sollen. Dies ist bei XML deutlich einfacher - bei groben Syntax- oder Strukturfehlern ist eine Anzeige nicht erforderlich, stattdessen erscheint eine Fehlermeldung, die dem Autor hilft, brauchbare Dokumente zu erstellen.

Nun kann HTML an sich ähnlich konsequent und gut strukturiert geschrieben werden wie ein XML-Dokument, weil ein Darstellungsprogramm aber immer auch fehlerhafte Dokumente darstellen wird, entfällt bei HTML selbst eine grobe Qualitätskontrolle durch das Darstellungsprogramm komplett, was bei XML nicht der Fall ist. Somit ist an sich XHTML eine sinnvolle Wahl für qualitativ hochwertige Inhalte, stößt aber auch noch einige Jahre nach der Spezifikation auf das Problem, daß es von einem bekannteren Anbieter von Darstellungsprogrammen boykottiert wird (microsoft heißt die Firma) und bei einer anderen zumindest der Verdacht besteht, daß diese in ihren Suchergebnissen Dokumente benachteiligt, die im Format XHTML vorliegen (Google heißt diese Firma), weswegen es meist sinnvoll ist, zu analysieren, welches Programm solch ein Dokument anfordert und dann per Skript entschieden wird, ob das Dokument korrekt als XHTML gesendet wird oder an solche Programme gezielt fehlerhaft als HTML, obwohl es sich eigentlich um XHTML handelt.

Eine weitere wichtige Anwendung liegt vor, wenn nicht nur ein Namensraum verwendet werden kann, weil eine Kombination von W3C-Standards in einem Dokument notwendig oder sinnvoll erscheint.

Hier ist das Beispiel für ein XHTML-Dokument:
XHTML mit XML per PHP
Funktionieren sollte es mit neueren browsern (kompatibel zu mozilla5, zum Beispiel auch Konqueror3, Netscape6/7, Opera6/7/8/9).
Wegen fehlender CSS-Dekoration mag das Beispiel etwas trostlos wirken, für einige andere Effekte, die in XHTML noch funktionieren, müßte man vielleicht auch noch andere Namensräume hinzufügen. Das Ganze soll ja aber auch nur das Prinzip vermitteln und keinen Schönheitspreis gewinnen...
Generell ist die Lage so, daß sich die Darstellungsprogramme nach dem header als nach der Notation in der Datei richten, formal korrekte header für XHTML sind also etwa:
application/xhtml+xml
application/xml
text/xml
Dazu gibt es auch eine W3C-Notiz.

application/xhtml+xml ist der eigentlich für XHTML vorgesehene MIME-Typ! Das Darstellungsprogramm sollte so wissen, daß er kein (x)-beliebiges XML bekommt, sondern eben XHTML. Nun kennen aber einige Darstellungsprogramme diesen MIME-Typ noch nicht. Aktuell sende ich bei XHTML zunehmend soweit sinnvoll den richtigen header:
Üblicher Weise geben Darstellungsprogramme in der Variable HTTP_ACCEPT an, welche Formate sie verstehen, man kann also vorsichtig formulieren:

<?php
# header fuer xhtml senden?
# Die Idee ist, wenn der browser ueberhaupt XML kennt, 
# bekommt er einen richtigen content-type, kennt er 
# immerhin HTML, bekommt er den, sonst wird geraten, 
# ob es Netscape4 oder MSIE ist, die bekommen dann 
# auch text/html, sonst gibt es xhtml.
$xhtml=TRUE;
$httpheader="Content-type: application/xhtml+xml";
$alterbrowser=0;
if(isset($_SERVER['HTTP_ACCEPT'])) {
if ( strpos($_SERVER["HTTP_ACCEPT"],"application/xhtml+xml") ) {
   # nichts zu tun...
} else if(strpos($_SERVER["HTTP_ACCEPT"],"application/xml")) {  
  $httpheader="Content-type: application/xml";
  $xhtml=TRUE;
} else if(strpos($_SERVER["HTTP_ACCEPT"],"text/xml")) {  
  $httpheader="Content-type: text/xml";
  $xhtml=TRUE;  
} else if(strpos($_SERVER["HTTP_ACCEPT"],"text/html")) {  
  $httpheader="Content-type: text/html";
  $xhtml=FALSE;   
} else {
   # nur wenn gar nichts angegeben ist, raten, ob es
   # netscape4 oder MSIE ist:
   $alterbrowser=substr_count(substr($agent, 0, 11), "Mozilla/4.");
   if ($alterbrowser != "0") {
      $httpheader="Content-type: text/html";
      $xhtml=FALSE; 
   }
}
header($httpheader);
}

?>

Ganz darauf verlassen kann man sich aber auch nicht. Konqueror 3.2/3.3 etwa, kommt mit dem ersten XHTML-header zurecht, zeigt das aber nicht unter HTTP_ACCEPT an. Der bekommt dann aber nach wie vor text/html vorgesetzt und soll sich nicht beschweren, wenn der nicht behauptet, XHTML anzeigen zu können, obwohl er es kann. Beim Umrüsten von HTML auf XHTML sollte aber unbedingt geprüft werden, ob noch Fehler im Dokument sind, die der XML-parser nicht verzeihen wird. Auch CSS-Stilvorlagen muß man gegebenenfalls etwas anpassen, oft ist es da sinnvoll, Hintergrund-Angaben vom body-Element ins html-Element zu verlagern.
Obiges Beispiel mit dem automatisch generierten header: XHTML-header mit Fallunterscheidung
oder zum Testen mit eigener Auswahl:
XHTML1.1 als application/xhtml+xml
XHTML1.1 als application/xml
XHTML1.1 als text/xml
XHTML1.1 als text/html
XHTML1.1 als text/plain
Spätestens das letzte sollte als XHTML-Quelltext angezeigt werden, sonst arbeitet das Programm fehlerhaft. Der msie scheint generell Probleme mit XML zu haben, obgleich das eigentlich einer der ersten war, der überhaupt etwas mit XML anfangen kann, scheint da aber keine großen Fortschritte gemacht zu haben. Bei meinem Test hat er teilweise groben Unfug angestellt oder offensichtlich unsinnige Fehlermeldungen ausgespuckt (angeblich hat er in einer Zeile in der XHTML1.1 DTD des W3C einen Fehler gefunden. Inzwischen wurde mir recht überzeugend dargelegt, daß der Fehler nicht in der DTD ist, sondern beim msie liegt).

SVG

Hier ist das Beispiel für eine SVG:
SVG mit PHP
Funktionieren sollte das mit Programmen, die einen entsprechenden parser eingebaut haben (Amaya5 ff, Opera8 ff, Geckos1.8 ff, Konqueror mit KSVG zum Beispiel) oder wenn ein plugin im Darstellungsprogramm vorhanden ist, der das anzeigt.
Weitere Erläuterungen und Beispiele, bei denen wirklich SVG mit PHP kombiniert wird, gibt es unter dem Menüpunkt Vektorgraphik.

MathML

Hier ist das Beispiel für eine Datei im Format MathML:
MathML mit PHP
Das Format wird hier einfach verwendet, um eine Formel für die Weglänge eines Pfades anzugeben. Mal abgesehen davon, daß Amaya die Zeilenumbrüche ignoriert, zeigt dieses Programm das Dokument inhaltlich sinnvoll dar. Opera 9.50 (alpha/beta) stellen Teile richtig dar, besonders sinnvoll sieht das Ergebnis allerdings nicht aus. Obgleich die Geckos angeblich MathML anzeigen können, ist mir selbst bei diesem einfachen Beispiel keine Anzeige gelungen; die Geckos versuchen allesamt den Nutzer dazu zu veranlassen, ein anderes Programm zur Anzeige zu verwenden. Konqueror stellt den Inhalt als Text ohne sinnvolle Formatierung dar. Wie bereits der Spezifikation zu entnehmen ist, ist es als nicht einfach anzusehen, dies Format mit einem einfachen Texteditor zu nutzen. In der Regel werden dafür spezielle Programme verwendet oder etwa LaTex-Dokument in MathML konvertiert. In Planung befindet sich eine Spezifikation für eine reduzierte Version, welche eine Darstellung des Formates mittels Stilvorlagen im Format CSS ermöglicht.

SMIL

Hier ist das Beispiel für eine Datei im Format SMIL:
SMIL mit PHP
Das Format wird hier einfach verwendet, um drei Bilder hintereinander darzustellen, die mit PHP dynamisch erzeugt werden. Das Problem von SMIL scheint zu sein, daß zwar diverse Module davon in anderen Formaten verwendet werden, es aber kaum ein Programm gibt, welches das Format selbst komplett interpretiert. Eine Anzeige etwa mit dem Real-Player ist mir nicht gelungen. Diese simple Anwendung läßt sich jedenfalls auch mit SVG umsetzen, wobei das darin integrierte SMIL-Modul zur deklarativen Animation verwendet wird, was dann etwa in Opera und dem adobe-plugin nachvollziehbar ist. Die Dokumentstruktur sieht dann allerdings anders aus.

WML

Hier ist das Beispiel für eine WML-Ausgabe:
WML mit PHP
Funktionieren sollte das mit browsern, die einen entsprechenden parser eingebaut haben (Opera4ff zum Beispiel) oder natürlich mit einem dafür geeigneten Telephon.
Ein Telephon mit solch einer Funktion habe ich nicht, daher ist mein persönliches Interesse an dem Format sehr mäßig. Bei W3C werden ohnehin XHTML-Module für Mobiltelephone angeboten, mag also sein, daß WML über kurz oder lang auch schon wieder uninteressant zu werden droht.

XML-Dokumente können nun in andere XML-Dokumente konvertiert werden, etwa in die genannten XHTML, SVG, WML oder auch mathML. Eine solche Konversion vor der Darstellung ist dringend zu empfehlen bei privaten XML-Dokumenttypen oder bei firmenspezifischen, die allesamt nicht standardisiert sind und somit von keinem oder bestenfalls einem firmenspezifischen Darstellungsprogramm eine sinnvolle Anzeige zu erwarten ist.
Diese Konversion findet mit dem XML-Format XSL statt. Die Konversion oder Transformation (XSLT) kann nun theoretisch vom Darstellungsprogramm selbst vorgenommen werden, zum anderen, was derzeit (Januar 2008) aber vorteilhafter ist, auch auf dem server. Sowohl für den Apachen (HTTP-server) als auch für PHP gibt es Module, mit denen dieses erledigt werden kann. Diese enthalten Funktionen, mit denen für das eigene Format ein Transformationsskript entwickelt werden kann.
Für Näheres möchte ich hier allerdings die jeweilige Anleitung empfehlen. Die phpinfo sollte in jedem Falle aufführen, ob solche Module vorhanden sind oder nicht.

Quelltexte

Schauen wir uns den Quelltext der PHP-Datei für XHTML an:

<?php
  $content="Content-type: application/xhtml+xml";
  header($content);
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?> \n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Beispiel xhtml mit xml-parser</title>
</head>
<body>
<h1>Hallo Welt</h1>
<h2>Beispiel XHTML mit XML-parser</h2>

<p>
Das ist also der Text <br />
Mal gucken.
</p>

<p>
   <a href="http://validator.w3.org/check/referer">
   <img src="http://www.w3.org/Icons/valid-xhtml10" 
   alt="Valid XHTML 1.0!" height="31" width="88" /></a>
</p>
</body>
</html>

Schauen wir uns den Quelltext der PHP-Datei für SVG an:

<?php
  $content="Content-type: image/svg+xml";
  header($content);
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?> \n";
?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 5 4"
     version="1.1"
     xmlns="http://www.w3.org/2000/svg" xml:lang="de"
     stroke-width="0.1">
  <desc>Vier Rechtecke</desc>
    <rect x="0.5" y="0.5" width="2" height="1" 
     fill="none" stroke="blue"/>
    <rect x="0.5" y="2" width="1" height="1.5"
     fill="none" stroke="red"/>
    <rect x="3" y="0.5" width="1.5" height="2"
     fill="none" stroke="green"/>
    <rect x="2" y="3" width="2.5" height="0.5"
     fill="none" stroke="yellow"/>
  <rect x=".01" y=".01" width="4.98" height="3.98"
     fill="none" stroke="orange" stroke-width=".01" />
</svg>

Schauen wir uns den Quelltext der PHP-Datei für MathML an:

<?php
  $content="Content-type: application/mathml+xml";
  header($content);
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?> \n";
?>
<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN"
       "http://www.w3.org/TR/MathML2/dtd/mathml2.dtd">
<math xmlns="http://www.w3.org/1998/Math/MathML">

  <mtext>
  Sei 
 </mtext>
<mspace linebreak="newline" /> 
<mrow>
<mo> ( </mo>
  <mi> x </mi>
  <mo> &ApplyFunction; </mo>
  <mrow>
    <mo> ( </mo>
      <mi> t </mi>
    <mo> ) </mo>
  </mrow> 
  <mo> , </mo>
  <mi> y </mi>
  <mo> &ApplyFunction; </mo>
  <mrow>
    <mo> ( </mo>
      <mi> t </mi>
    <mo> ) </mo>
  </mrow>  
<mo> ) </mo>
</mrow>
<mspace linebreak="newline" /> 
<mtext>
  ein Pfad in einer Ebene 
  mit einer Parametrisierung mit 
  <mi> t </mi> von <mn>0</mn> bis
  </mtext>

<mspace linebreak="newline" /> 

<mrow>
  <mi>L</mi>
  <mo>=</mo>
  <msubsup>
    <mo>&int;</mo>
    <mn>0</mn>
    <mn>1</mn>
  </msubsup>
  <msqrt>
    <msup>
      <mrow>
        <mo>(</mo>
        <mfrac>
          <mi>dx</mi>
          <mi>dt</mi>
        </mfrac>
        <mo>)</mo>
      </mrow>
      <mn>2</mn>
    </msup>
    <mo>+</mo>
    <msup>
      <mrow>
        <mo>(</mo>
        <mfrac>
          <mi>dy</mi>
          <mi>dt</mi>
        </mfrac>
        <mo>)</mo>
      </mrow>
      <mn>2</mn>
    </msup>
  </msqrt>
  <mi>dt</mi>
</mrow>
</math>

Schauen wir uns den Quelltext der PHP-Datei für SMIL an:

<?php
  $content="Content-type: application/smil+xml";
  header($content);
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?> \n";
?>
<!DOCTYPE smil PUBLIC "-//W3C//DTD SMIL 3.0 Language//EN"
"http://www.w3.org/2008/SMIL30/SMIL30Language.dtd">
<smil xmlns="http://www.w3.org/ns/SMIL" version="3.0" baseProfile="Language">
  <body>
    <seq begin="3s">
      <img src="../labor/erstesbild.php?x=600&amp;y=400&amp;z=1"
             alt="Bild 1" dur="10s" end="click" />
      <img src="../labor/erstesbild.php?x=600&amp;y=400&amp;z=2"
             alt="Bild 2" dur="10s" end="click" />
      <img src="../labor/erstesbild.php?x=600&amp;y=400&amp;z=3"
             alt="Bild 3" dur="10s" end="click" />
    </seq>
  </body>
</smil>


Schauen wir uns den Quelltext der PHP-Datei für WML an:

<?php
  $content="Content-type: text/vnd.wap.wml";
  header($content);
echo "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?> \n";
?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN" 
 "http://www.wapforum.org/DTD/wml_1.1.xml">
<wml>
  <card id="eins">
    <p>
  	wml mit php.
    </p>
   <p>    
      <a href="#zwei">gehe zur zweiten Card</a>
    </p>    
  </card>
  
  <card id="zwei">
    <p>
  	sollte funzen...
    </p>
   <p>    
      <a href="#eins">gehe zur ersten Card</a>
    </p>    
  </card>
</wml>