﻿<?xml version='1.0' encoding='utf-8' standalone='no' ?>
<!DOCTYPE mydoc SYSTEM 'scriptum.xml.dtd'>
<mydoc>
<docinfo>
<info>Fachhochschule Giessen</info>
<info>Vorlesung im Sommersemester 2003</info>
<info>Programmierung von Multimediasystemen</info>
<info>Dynamische Webseiten mit XML, PHP und XSLT</info>
<info>Scriptum zur Vorlesung</info>
<info>Status: 25.06.2003</info>
<info>(c) C. van der Kruijs, ( http://www.vanderkruijs.net )</info>
<info>Hinweise, Anmerkungen und Fehler bitte an: scriptum@vanderkruijs.net</info>
</docinfo>
<section>
<section-header>Teil: XML</section-header>
<section>
<section-header>Einführung und Überblick</section-header>
<para>XML ist die Abkürzung für eXtensible Markup Language, also für erweiterbare Auszeichnungssprache. Um vorneweg den Begriff etwas ein zu schränken: XML ist nicht - wie oft fälschlicherweise angenommen - der Nachfolger von HTML, auch wenn Ähnlichkeiten nicht von der Hand zu weisen sind, sondern:</para>
<ul><para><li>
eine Dokumenten-Beschreibungssprache</li>
</para>
<para><li>
eine Vereinfachung bzw. ein Anwendungsprofil von SGML (Standard Generalized Markup Language) - genau wie es HTML auch ist, allerdings ohne dessen einschränkende Festlegung auf Dokumentformatierung</li>
</para>
<para><li>
eine Beschreibungsvorschrift für eine Metasprache</li>
</para>
<para><li>
offen für jegliche semantische Interpretation</li>
</para>
<para><li>
objektorientiert einsetzbar</li>
</para>
</ul><para>Dies bedeutet: XML beschreibt einerseits eine Klasse von Datenobjekten (=XML-Dokumente), andererseits aber auch (teilweise) das Verhalten von Computerprogrammen, die solche Dokumente Verarbeiten.</para>
<section>
<section-header>Geschichtliche Entwicklung</section-header>
<para>1969 SGML entwickelt bei IBM ( C. Goldfarb, E. Mosher, R. Lorie ) zur Integration von Informationssystemen für Anwaltskanzleien</para>
<para>Nachfolgend internationale Standardisierungsbewegung der Standard GML (SGML), XML wird zur Metasprache; Abkopplung von problem-spezifischen Sprachumfängen</para>
<para>1978 ANSI engagiert sich, GML zu US-Standard zu erheben</para>
<para>1979 Erster ANSI-Entwurf für SGML</para>
<para>1984 SGML-Arbeitsgruppe unter Schirmherrschaft der ISO</para>
<para>1985 Normentwurf SGML</para>
<para>1986 Verabschiedung von SGML durch ISO als ISO 8879:1986</para>
<para>1989 Vorschlag eines SGML basierendes Hypertext-Systems durch T. Berners. Name: Hypertext Markup Language (HTML) und Definition des Uniform Resource Locators (URL) - global eindeutige Adresse für beliebige Inhalte</para>
<para>1990 Start des WWW im CERN (Europäisches Kernforschungszentrum) mit zwei Rechnern</para>
<para>1992 Erster Entwurf zu HTML</para>
<para>1994 Gründung des W3C (World Wide Web Consortium)</para>
<para>1996 Erster XML-Entwurf des W3C</para>
<para>1998 XML 1.0 Recommendation des W3C</para>
<para>2000 XHTML 1.0 (XML-konforme Reformulierung HTML 4.01)</para>
<para>2001 Schema-Standard vom W3C verabschiedet</para>
</section>
<section><section-header>Zielsetzungen des W3C bei der Entwicklung von XML</section-header>
<ul><para><li>
Einfache Nutzung im Internet</li>
</para>
<para><li>
Unterstützung eines breiten Anwendungsspektrums</li>
</para>
<para><li>
SGML-Kompatibilität</li>
</para>
<para><li>
Einfache Applikationsentwicklung</li>
</para>
<para><li>
Minimierung optionaler Sprachmerkmale (idealerweise keine)</li>
</para>
<para><li>
Lesbarkeit und Verständlichkeit für Maschine wie für Mensch</li>
</para>
<para><li>
Kompakte Spezifikation</li>
</para>
<para><li>
Formaler und präziser Sprachentwurf</li>
</para>
<para><li>
Leichte Dokumentenerstellung</li>
</para>
<para><li>
Knappheit von XML-Markup ist von minimaler Bedeutung</li>
</para>
</ul></section>
<section><section-header>XML in 10 Punkten nach W3C-Kurzcharakterisierung</section-header>
<ul><para><li>
XML dient der Strukturierung von Daten</li>
</para>
<para><li>
Sie ist keine Programmiersprache sondern Satz von Vorschriften zum Entwurf von Textformaten und strukturierten Daten</li>
</para>
<para><li>
Sie wendet sich an nicht speziell an Programmierer</li>
</para>
<para><li>
XML erleichtert Programmierung von Datenverarbeitungssystemen</li>
</para>
<para><li>
Sie ist erweiterbar, plattformunabhängig, international und lokalisierbar</li>
</para>
<para><li>
XML sieht ein wenig aus wie HTML</li>
</para>
<para><li>
Beide verwendet Markierungen (Tags) zum Auszeichnen der Inhalte</li>
</para>
<para><li>
HTML verwendet nur vordefinierte Tags zur Formatierung der Darstellung</li>
</para>
<para><li>
XML verwendet frei definierbare Tags zum Beschreiben der Inhalte (Semantik) bzw. deren Struktur - Form der weiteren Verarbeitung (bspw. Darstellung) ist der Anwendung überlassen</li>
</para>
<para><li>
XML ist Text, aber nicht dazu gedacht, gelesen zu werden</li>
</para>
<para><li>
XML-Daten werden in Textdateien gespeichert</li>
</para>
<para><li>
Können entsprechend in beliebigen Texteditoren geladen und angezeigt und bearbeitet werden</li>
</para>
<para><li>
Fehler in der Datei machen sie jedoch ungültig und damit unbrauchbar (im Gegensatz zu HTML) Anwendungen dürfen nicht spekulativ versuchen, Dateifehler zu beheben.</li>
</para>
<para><li>
XML hat aufgrund des Design einen erhöhten Platzbedarf</li>
</para>
<para><li>
Textdateien sind größer als Binärdateien gleichen Informationsgehalts</li>
</para>
<para><li>
Kann auf anderer Ebene kompensiert werden (Kompression im Dateisystem bzw. Übertragungsweg)</li>
</para>
<para><li>
XML ist eine Familie von Techniken</li>
</para>
<para><li>
Auf XML bauen weitere Module auf</li>
</para>
<para><li>
Erweiterung des Funktionsumfangs</li>
</para>
<para><li>
Beispiele:</li>
</para>
<para><li>
DTD/Schema : Techniken zur Typen- und Strukturdeklaration</li>
</para>
<para><li>
DOM/SAX : Manipulationstechniken</li>
</para>
<para><li>
XLink   : Hyperlinks in und zwischen XML-Dokumenten</li>
</para>
<para><li>
XPath  : Adressierung von Elementen eines XML-Dokuments</li>
</para>
<para><li>
CSS   : Formatierungsanweisungen für die Darstellung</li>
</para>
<para><li>
XSL/XSLT : XML-Stylesheet-Language / --Transformations</li>
</para>
<para><li>
XML ist neu, aber so neu auch wieder nicht</li>
</para>
<para><li>
XML-Entwicklung begann 1996, erste Recommendation 1998</li>
</para>
<para><li>
XML basiert auf SGML, mit dem Versuch die besten Eigenschaften zu übernehmen, die Komplexität zu verringern und Erfahrungen mit HTML einfließen zu lassen</li>
</para>
<para><li>
XML überführt HTML in XHTML</li>
</para>
<para><li>
XML-Syntaktische Neuformulierung von HTML</li>
</para>
<para><li>
XML ist modular</li>
</para>
<para><li>
XML ermöglicht Entwicklung eigener Datenformate</li>
</para>
<para><li>
Eindeutigkeit der Formate wird über Namensräume gewährleistet: Kombination von Dokumenten und Dokumenttyp-Definitionen somit möglich</li>
</para>
<para><li>
XML ist die Basis von RDF und dem Semantic Web</li>
</para>
<para><li>
Das Semantic Web ist ein Netz aus Sinn-Zusammenhängen</li>
</para>
<para><li>
Das Resource Description Framework definiert eine XML-Syntax zur Darstellung von beschreibenden Daten</li>
</para>
<para><li>
XML ist lizenzfrei, Plattform- und Herstellerunabhängig und gut unterstützt</li>
</para>
<para><li>
XML wird von einem unabhängigen Gremium entwickelt</li>
</para>
<para><li>
Es sind zwar Firmen vertreten, diese können den Standardisierungsprozess jedoch nicht dominieren</li>
</para>
<para><li>
XML ist weit verbreitet, viele Hersteller bieten (kostenpflichtig/kostenfrei) Werkzeuge an, viele Produkte akzeptieren XML als Datenformat</li>
</para>
</ul><para>XML ist nicht immer die beste Lösung, aber immer Wert, als Alternative in Betracht gezogen zu werden.</para>
</section>
<section><section-header>Die XML-Sprachfamilie</section-header>
</section>
</section>
<section><section-header>Strukturelle Grundlagen</section-header>
<para>Die Syntax eines XML-Dokuments unterliegt strikten Regeln. Gerade in diesem Zusammenhang wird der Unterschied zu HTML sehr deutlich, welches es erlaubt, gegen die Vorschriften zu verstossen. Dies ist prinzipbedingt bei XML nicht möglich, da ansonsten spekulativ auf die Zuordnung und Bedeutung der Inhalte geschlossen werden müsste.</para>
<section>
<section-header>Ein erstes Beispiel</section-header>
<code>
<label>Beispiel 1</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt; </codeline>
<codeline>&lt;Institut Typ=&apos;Fachhochschule&apos;&gt; </codeline>
<codeline>	&lt;Ort&gt;Giessen&lt;/Ort&gt; </codeline>
<codeline>	&lt;Logo src=&quot;fh-giessen.jpg&quot; /&gt; </codeline>
<codeline>&lt;/Institut&gt; </codeline>
</code>
<para>Zeile 1 Prolog mit XML-Deklaration (Document Information Item),</para>
<para>Zeile 2 Öffnende Markierung Institut: Document Element, enthält alle weiteren Elemente des Dokuments, bildet den Rumpf</para>
<para>Zeile 3 Element Ort mit Inhalt &quot;Giessen"</para>
<para>Zeile 4 Leeres Element Logo mit Attribut src</para>
<para>Zeile 5 Schließende Markierung Institut</para>
</section>
<section><section-header>XML-Dokumentenaufbau</section-header>
<para>Ein vollständiges XML-Dokument wird als Document Information Item bezeichnet und enthält:</para>
<para>Prolog Optional; Angaben über das Dokument:</para>
<para>XML-Deklaration,</para>
<para>Processing Instructions,</para>
<para>Dokumenttyp-Deklaration ( &lt;!DOCTYPE...&gt; ),</para>
<para>Entity-Deklarationen</para>
<para>Markup-Deklaration (Element-, Attribut-, oder Notations-Deklaration),</para>
<para>Kommentare</para>
<para>Rumpf Erforderlich; Eigentlicher, strukturierter Inhalt des Dokuments</para>
<para>Besteht aus dem Document Element</para>
<para>Epilog Optional; Von Verwendung wird abgeraten, da Parser nach Abarbeitung des Rumpfs die Verarbeitung evtl. abbrechen.</para>
</section>
<section><section-header>Wohlgeformte Dokumente</section-header>
<para>Als wohlgeformtes Dokument wird ein textartiges Objekt bezeichnet, wenn dessen Inhalt folgenden Anforderungen genügt:</para>
<ul><para><li>
Das XML-Dokument nutzt eine DTD, oder enthält die Deklaration standalone=&quot;yes&quot;.</li>
</para>
<para><li>
Zu jedem Start-Tag existiert genau ein End-Tag (Bei leeren Elementen können diese zu einem speziellen Tag zusammenfallen).</li>
</para>
<para><li>
Die Elemente des Dokuments sind korrekt verschachtelt, d.h. die einzelnen Elemente überlappen einander nicht.</li>
</para>
<para><li>
Das Dokument enthält genau ein Wurzelelement.</li>
</para>
<para><li>
Alle Attributwerte sind in einfachen oder doppelten Anführungszeichen eingeschlossen.</li>
</para>
<para><li>
Kein Start-Tag (oder Tag der eines leeren Elements) enthält zwei oder mehr Attribute desselben Namens.</li>
</para>
<para><li>
Keine Kommentare oder Processing Instructions innerhalb von Tags.</li>
</para>
<para><li>
Kommentare beginnen und enden mit genau zwei Bindestrichen.</li>
</para>
<para><li>
Die Sonderzeichen &lt; und &amp; treten nicht innerhalb von Elementinhalten oder Attributwerten auf.</li>
</para>
</ul><para>Nachfolgend ein Beispieldokument, welches in vielerlei Hinsicht gegen die Anforderungen eines wohlgeformten Dokuments verstößt.</para>
<code>
<label>Beispiel 2: Ein nicht wohlgeformtes Dokument</label>
<codeline>	&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>	&lt;root&gt; </codeline>
<codeline>		&lt;elementA att=a oder b&gt; </codeline>
<codeline>			&lt;elementB&gt; iff a&lt;b ==&gt; ... </codeline>
<codeline>		&lt;/elementA&gt; </codeline>
<codeline>		&lt;elementC att1=&quot;42&quot; att1=&quot;3.14&quot;&gt; </codeline>
<codeline>			&lt;elementD &lt;?do-something?&gt; &gt; </codeline>
<codeline>		&lt;/elementC&gt; </codeline>
<codeline>			&lt;/elementD&gt; </codeline>
<codeline>	&lt;!---- dies ist nicht erlaubt ----&gt; </codeline>
<codeline>&lt;/root&gt; </codeline>
</code>
<para>Im Einzelnen sind die Fehler folgende:</para>
<ul><para><li>
In Zeile 8 findet sich ein nicht in erforderlichen Anführungszeichen eingeschlossener Attributwert.</li>
</para>
<para><li>
Der textuelle Elementinhalte des in Zeile 9 geöffneten Elements elementB enthält ein öffnendes Winkelklammersymbol, welches um Fehler während des Einlesevorgangs zu vermeiden durch die alternative Zeichensequenz &amp;lt; hätte ersetzt werden müssen. Darüber hinaus fehlt das korrekte schließende Tag.</li>
</para>
<para><li>
Innerhalb des Elements elementC der Zeile 11 wird zweifach ein identisch benanntes Attribut definiert.</li>
</para>
<para><li>
Im öffnenden Tag des in Zeile 12 definierten Elements elementD findet sich eine - dort nicht zugelassene - Processing Instruction.</li>
</para>
<para><li>
Die Elementgrenzen der Elemente elementC und elementD überlappen sich.</li>
</para>
<para><li>
Der in Zeile 15 plazierte Kommentar wird nicht durch die erforderlichen genau zwei Bindestriche eingegrenzt.</li>
</para>
</ul></section>
<section><section-header>Syntaktische Konstrukte</section-header>
<para>Innerhalb eines XML-Dokuments können verschiedene Inhalte vorhanden sein, die von einem Parser jeweils unterschiedlich interpretiert werden. Sie dienen u.a. dazu, die eigentlichen Inhalte zu schachteln und Kommentare und Prozessorinstruktionen von einander zu trennen.</para>
<section>
<section-header>Processing Instructions</section-header>
<para>Format:</para>
<code>
<codeline>&lt;?zielanwendung anweisungen ?&gt; </codeline>
</code>
<code>
<label>Beispiel 3: Processing Instructions</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; </codeline>
<codeline>&lt;?mySystem value=&quot;42&quot;?&gt; </codeline>
<codeline>&lt;root&gt; </codeline>
<codeline>	&lt;?System2?&gt; </codeline>
<codeline>	&lt;elementA&gt; </codeline>
<codeline>		&lt;?System3 a=&quot;1&quot; anotherValue?&gt; </codeline>
<codeline>	&lt;/elementA&gt; </codeline>
<codeline>&lt;/root&gt; </codeline>
</code>
<para>Die Zielanwendung gibt an, an welche Anwendung sich die Instruktionen richten. Die angegebenen Anweisungen werden als Zeichenkette an diese Anwendung weitergegeben.</para>
</section>
<section><section-header>XML-Deklaration</section-header>
<para>Format:</para>
<code>
<codeline>&lt;?xml version=&quot;number&quot; [encoding=&quot;encoding&quot;] [standalone=&quot;yes&quot;|&quot;no&quot;] ?&gt; </codeline>
</code>
<code>
<label>Beispiel 4: XML-Deklaration</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt; </codeline>
</code>
<para>Die XML-Deklaration ist optional anzugeben, üblicherweise vorhanden</para>
<para>Attribute:</para>
<para>version  : Erforderlich; zeigt verwendete Version an. Aktuell: Konstante &quot;1.0" oder &quot;1.1&quot;</para>
<para>encoding  : Optional; Kodierungsschema, definiert zugelassene Zeichen</para>
<para>standalone  : Optional: yes|no; besagt, das kein externes Stylesheet oder DTD (Document Type Declaration) vorhanden ist; entsprechende Angaben im Dokument enthalten sein müßten - im Beispiel weggelassen</para>
</section>
<section><section-header>CDATA</section-header>
<para>Format</para>
<code>
<codeline>&lt;![CDATA[beliebiger Inhalt]]&gt; </codeline>
</code>
<code>
<label>Beispiel 5: CDATA</label>
<codeline>&lt;![CDATA[ </codeline>
<codeline>	Dieser Text wird nicht geändert, auch wenn hier &lt;markup&gt; </codeline>
<codeline>	&amp;amp; Entity-Referenzen stehen! </codeline>
<codeline>]]&gt; </codeline>
</code>
<para>CDATA-Abschnitte dürfen dort stehen, wo auch Zeichendaten erlaubt sind, sie schützen Textinhalte, die als Markup interpretiert werden könnten.</para>
</section>
<section><section-header>Dokument Typ Definitionen</section-header>
<para>Format:</para>
<code>
<codeline>&lt;!DOCTYPE element ( SYSTEM | PUBLIC ) [name] URI-of-DTD&gt; </codeline>
</code>
<para>Gegenwärtig erlaubte Formen:</para>
<code>
<codeline>&lt;!DOCTYPE element SYSTEM URI-of-DTD&gt; </codeline>
<codeline>&lt;!DOCTYPE element PUBLIC [name] URI-of-DTD&gt; </codeline>
</code>
<para>Erstere ist eine private-Deklaration der DTD, die auf alle Elemente innerhalb des Wurzelelements angewandt wird. Zweites definiert eine öffentlich zugängliche, die als registrierter Name bekannt ist, oder über die URL gesucht wird.</para>
<code>
<label>Beispiel 6: Document Type Definitionen</label>
<codeline>&lt;!DOCTYPE someContent SYSTEM &quot;abc.dtd&quot;&gt;  </codeline>
<codeline>&lt;!DOCTYPE HTML PUBLIC </codeline>
<codeline>	&quot;-//W3C//DTD HTML 4.01//EN&quot; </codeline>
<codeline>	&quot;http://www.w3.org/TR/html4/strict.dtd&quot;&gt; </codeline>
</code>
<para>Die Document Type Definition kann auch teilweise oder vollständig innerhalb des Dokuments angegeben sein (inline). Die DTD-Syntax wird an entsprechender Stelle näher beleuchtet.</para>
<code>
<codeline>Comment Information Item </codeline>
</code>
<para>Format:</para>
<code>
<codeline>&lt;!-- beliebiger Inhalt --&gt; </codeline>
</code>
<code>
<label>Beispiel 7: Comment Information Item</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; </codeline>
<codeline>&lt;root&gt; </codeline>
<codeline>	&lt;!-- this is a comment --&gt; </codeline>
<codeline>	&lt;ElementA&gt;  </codeline>
<codeline>		&lt;ElementB&gt; </codeline>
<codeline>			&lt;!--  </codeline>
<codeline>			&lt;ElementC/&gt;  </codeline>
<codeline>			&lt;ElementD att1=&quot;...&quot;/&gt; </codeline>
<codeline>			--&gt; </codeline>
<codeline>			&lt;/ElementB&gt; </codeline>
<codeline>	&lt;/ElementA&gt;  </codeline>
<codeline>&lt;/root&gt; </codeline>
</code>
<para>An beliebiger Stelle außerhalb des Markups erlaubt, zudem innerhalb von Dokumenttyp-Deklarationen. Innerhalb des Kommentar-Textes ist die Zeichenkette &quot;--&quot; nicht erlaubt.</para>
</section>
</section>
<section><section-header>Logische Struktur</section-header>
<para>Wichtig: XML beachtet generell Groß/Kleinschreibung (Case-Sensitive) Im Element- bzw. Attributinhalt sind gewisse, von XML selbst genutzte Zeichen, nicht erlaubt. An ihrer Stelle müssen Entity-Referenzen verwendet werden. Diese werden vom Parser automatisch ersetzt. Es ist möglich, innerhalb der Dokument Typ Definition weitere Entity Referenzen zu definieren.</para>
<table>
<tr>
<th><para>Entity-Referenz</para>
</th>
<th><para>Ausgedrücktes Zeichen</para>
</th>
</tr>
<tr>
<td><para>&amp;amp;</para>
</td>
<td><para>&amp;</para>
</td>
</tr>
<tr>
<td><para>&amp;lt;</para>
</td>
<td><para>&lt;</para>
</td>
</tr>
<tr>
<td><para>&amp;gt;</para>
</td>
<td><para>&gt;</para>
</td>
</tr>
<tr>
<td><para>&amp;apos;</para>
</td>
<td><para>&apos;</para>
</td>
</tr>
<tr>
<td><para>&amp;quot;</para>
</td>
<td><para>&quot;</para>
</td>
</tr>
<label>Tabelle 1: Vordefinierte Entity-Referenzen</label>
</table>
<para>Allgemein lassen sich Zeichenreferenzen direkt mit hexadezimalem oder ASCII-Code angeben:</para>
<para>Hexadezimal-Zeichenreferenz für &quot;(c)&quot; (Hex-Code: A9)  &amp;#xA9;</para>
<para>ASCII-Zeichenreferenz für &quot;&amp;&quot; (ASCII-Code 38)   &amp;#38;</para>
<section>
<section-header>Elemente</section-header>
<para>Container für beliebige Inhalte, sowohl Daten als auch andere Elemente, Kommentare und Processing Instructions.</para>
<para>Der Name (Generic Identifier, GI) bestimmt den Typ des Elements.</para>
<para>Elemente können, unter Berücksichtigung der Wohlgeformtheitsregeln beliebig verschachtelt werden.</para>
<para>Ihnen kann eine Menge von Attributspezifikationen (‚Name=Wert'-Paare) enthalten.</para>
<para>Im Grunde gibt es zwei Arten von Elementen: solche mit, und solche ohne Inhalt.</para>
<ul><para><li>
Nichtleeres Element:</li>
</para>
</ul><para>Besteht aus: Einleitender Start-Tag und abschließender, gleichnamiger End-Tag.</para>
<para>Beispiel: &lt;tagname&gt; ... &lt;/tagname&gt;</para>
<para>Leeres Element:</para>
<para>Start-Tag ist gleichzeitig End-Tag. Beispiel: &lt;tagname/&gt;</para>
<para>Oder (wenn Inhalte prinzipiell erlaubt sind, dem Ersten vorzuziehen): &lt;tagname&gt;&lt;/tagname&gt;</para>
</section>
<section><section-header>Attribute</section-header>
<para>Attribute dienen der näheren Spezifizierung von Elementen. Ihre Namen, Bedeutung und Anzahl sind frei definierbar.</para>
<para>Die Angabe erfolgt in der Form name=&quot;wert&quot;, wobei der Wert immer in einfachen &apos; oder doppelten &quot; Anführungszeichen stehen muss (auch bei rein numerischen Angaben) und sich das Begrenzungszeichen nicht im Inhalt wiederfindet. Um trotzdem Anführungszeichen verwenden zu können, werden an ihrer Stelle entsprechende Entities gesetzt, die vom Parser gegen die gewünschten Sonderzeichen ausgetauscht werden.</para>
<para>Vordefinierte Attribute in XML:</para>
<code>
<codeline>xml:lang=&quot;iso-639-Identifier&quot; </codeline>
</code>
<para>Bezeichnet die Sprache des Element-Inhalts nach IANA-Code</para>
<code>
<codeline>xml:space=&quot;default|preserve&quot; </codeline>
</code>
<para>Bestimmt ob Whitespaces (Leerzeichen, Zeilenvorschub, Wagenrücklauf, Tabulator) wie angegeben erhalten bleiben müssen.</para>
<code>
<codeline>xml:link=&quot;simple|extended&quot; </codeline>
</code>
<para>Dient der Verknüpfung zwischen XML-Dokument und anderen Ressourcen. Je nach angegebenem Typ werden weitere Attribute benötigt. Dieser Attribut dürfte durch den XLink-Mechanismus ersetzt werden.</para>
</section>
<section><section-header>Element vs. Attribut</section-header>
<para>Der Vergleich der Eigenschaften von Element und Attribut zeigt bereits, dass sich nicht weiter strukturierte Elemente auch durch Attribute darstellen ließen.</para>
<para>Dies wirft innerhalb der Betrachtung der Syntax eines XML-Dokuments bereits die Frage nach der Organisation, und damit dem Entwurf, eines solchen auf.</para>
<para>Die bestehende XML-Spezifikation bleibt jedoch eine Anwendungs- oder Einsatzempfehlung zu dieser Fragestellung schuldig.</para>
<para>Aufgrund der inhärenten Einschränkungen der Attributprimitive bietet sich ihr Einsatz nur in einigen Sonderfällen an. Beispielsweise zur Darstellung descriptiver Information über das enthaltende Element, die nicht Bestandteil der im XML-Dokument dargestellten Information ist. Hierbei kann es sich um Informationen höherer Ordnung (Metainformationen) handeln, die das Element entsprechend näher auszeichnen.</para>
</section>
</section>
<section><section-header>Namensräume</section-header>
<para>Das Konzept der Namensräume ist das Ergebnis der Bestrebungen folgender Problemfälle lösen zu können, die mit XML an sich nicht, oder nur sehr mühselig, zu begegnen wären:</para>
<ul><para><li>
Wiederverwendung bestehender (fremder) XML-Strukturen in eigenen Dokumenten.</li>
</para>
<para><li>
Wunsch nach breiteren Standards.</li>
</para>
<para><li>
Verringerung des Designaufwandes.</li>
</para>
<para><li>
Nutzung bereits gesammelter Designerfahrung.</li>
</para>
<para><li>
Zusammenführung verschiedener XML-kodierter Inhalte (heterogeneous content syndication).</li>
</para>
</ul><para>Im Grunde löst das Konzept vor Allem ein Problem: Durch die Verwendung von Generic Identifier können gleichlautende, unterschiedlich definierte Markups entstehen. Dies führt zu Schwierigkeiten beim Kombinieren von Dokumenten, da nicht eindeutig ist, zu welcher Definition das jeweilige Element gehört. Die Verwendung von Namensräume (Namespaces) überwindet diese Hürde.</para>
<para>Die Zuordnung zu einem Namensraum wird innerhalb des Element-Start-Tags als Attribut angegeben und gilt für dieses Element als auch für seine Kinder, die diese nicht überschreiben.</para>
<para>Namespace-Deklarationen haben folgende Form:</para>
<code>
<codeline>xmls:namensraumbezeichner=&quot;URI&quot; </codeline>
</code>
<para>Der Universal Resource Identifier (URI) dient der eindeutigen Identifizierung des Namens und muss weltweit eindeutig sein. Realisierbar ist dies über eine URL oder aber auch eine Emailadresse. Empfehlenswert sind jedoch URL&apos;s da tendenziell die Möglichkeit gewährt werden sollte, an der angegebenen Stelle weitere Informationen verfügbar zu machen.</para>
<para>Es können mehrere Namespaces parallel angewendet werden. Über den Namensraumbezeichner können sie selektiv eingesetzt werden. Wird bei der Deklaration kein solcher Namensraumbezeichner angegeben, gilt dieser Namensraum als Default-Namespace und kommt immer zur Anwendung. Der Default-Namespace wirkt sich allerdings nicht auf Attribute aus, für sie gilt weiterhin die dem Dokument zugehörige Typdefinition.</para>
<code>
<label>Beispiel 8: Default Namespace, benannter Namespace:</label>
<codeline>&lt;bspw xmlns:meinNS=&quot;namespace@example.com&quot;  </codeline>
<codeline>				xmlns=&quot;http://www.example2.com&quot;&gt; </codeline>
<codeline>	&lt;meinNS:kind1&gt;Kind 1 in Namespace meinNS&lt;/kind1&gt; </codeline>
<codeline>	&lt;kind2&gt;Kind 2 im Default-Namespace&lt;/kind2&gt; </codeline>
<codeline>&lt;/bspw&gt; </codeline>
</code>
<para>Dass auch die Namensräume das Problem nicht vollständig beseitigen können zeigt folgende Fragenstellung: Was passiert, wenn Dokument mit gleichen Namespace-Bezeichnern (und vielleicht sogar gleichen Tag-Namen) gemischt werden?</para>
<para>Namensräume - sowohl durch explizite Präfixangabe als auch durch überschreiben des Vorgabenamensraumes - wirken sich ausschließlich auf Elemente und deren direkte oder transitive Kindelemente aus!</para>
<para>Namensräume für Attribute werden ausnahmslos durch explizite Präfixangabe festgelegt!</para>
<code>
<label>Beispiel 9: Namensräume</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; </codeline>
<codeline>&lt;Wurzelelement&gt; </codeline>
<codeline>	&lt;ElementA xmlns:NS1=&quot;http://www.example.com/NS1&quot; </codeline>
<codeline>					xmlns:NS2=&quot;http://www.example.com/NS2&quot;&gt; </codeline>
<codeline>		&lt;ns2:ElementB att1=&quot;...&quot;&gt; </codeline>
<codeline>			&lt;ElementD att1=&quot;...&quot; </codeline>
<codeline>					xmlns=&quot;http://www.example.com/NS3&quot;&gt; </codeline>
<codeline>				&lt;ElementC att2=&quot;ABC&quot; NS2:att2=&quot;XYZ&quot;/&gt; </codeline>
<codeline>			&lt;/ElementD&gt; </codeline>
<codeline>		&lt;/ns2:ElementB&gt; </codeline>
<codeline>	&lt;/ElementA&gt; </codeline>
<codeline>&lt;/Wurzelelement&gt; </codeline>
</code>
</section>
<section><section-header>Document Type Definitions</section-header>
<para>Die Document Type Definition (DTD) bildet die textuelle Notation der Struktur eines XML-Dokuments. Sie wurde mit SGML eingeführt, wird aber kurz- bis mittelfristig durch XML-Schema ersetzt sein.</para>
<para>DTD dienen der Definition von Elementen, Attributen, Entitäten, Notationen und Processing Instructions. Üblicherweise wird die Definition in einer separaten Datei gespeichert, auf die referenziert wird. Eine vollständige, oder aber auch teilweise, interne Typ Definition ist möglich.</para>
<para>Eine externe Definition wird als external subset bezeichnet; die interne entsprechend als inernal subset. Die interne Definition hat höhere Priorität und überschreibt ggf. die externe.</para>
<section>
<section-header>Element Definitionen</section-header>
<para>Format:</para>
<code>
<codeline>&lt;!ELEMENT name inhaltsdeklaration &gt; </codeline>
</code>
<para>Die Inhaltsdeklaration kann folgende Werte annehmen:</para>
<code>
<codeline>EMPTY | ANY | mixed | children </codeline>
</code>
<para>EMPTY  : leeres Element</para>
<para>ANY : keine Einschränkungen; sowohl Zeichendaten als Kindelemente in beliebiger Reihenfolge und Häufigkeit möglich</para>
<para>mixed : darf Zeichendaten enthalten, optional gemischt mit Kindelementen, wobei die Typen der Kindelementen beschränkt werden kann, nicht jedoch Reihenfolge und Anzahl. Definition in der Form: ( #PCDATA | name ) * | ( #PCDATA ) *</para>
<para>children : Namentliche Aufzählung der Kindelemente in der erwarteten Reihenfolge</para>
<para>Zur Steuerung stehen verschiedene Operatoren zur Verfügung: Das | (or) Zeichen deutet an, dass eines der genannten optionen enthalten sein muss. Durch Verwendung des Komma (,) wird eine Liste gebildetet, dessen Elemente jeweils vorhanden sein müssen (in der angegebenen Reihenfolge). Das Fragezeichen (?) kennzeichnet den betreffenden Eintrag als optional, das Pluszeichen (+) als mindestens einfach, und das Sternchen (*) als beliebig häufig verhanden. Diese Operatoren dürften bereits aus anderen Bereichen der Informatik bekannt sein, und werden auch innerhalb der XML-Sprachfamilie häufig benutzt.</para>
<code>
<label>Beispiel 10: Element-Definitionen</label>
<codeline>&lt;!ELEMENT br EMPTY&gt; </codeline>
<codeline>&lt;!ELEMENT p ( #PCDATA | emph ) * &gt; </codeline>
<codeline>&lt;!ELEMENT %name.para; %content.para; &gt; </codeline>
<codeline>&lt;!ELEMENT container ANY &gt; </codeline>
<codeline>&lt;!ELEMENT spec ( front, body back? )  &gt; </codeline>
<codeline>&lt;!ELEMENT div1 ( head, ( p | list | note ) *, div2 * ) &gt; </codeline>
<codeline>&lt;!ELEMENT dictionary-body ( %div.mix; | %dict.mix; ) &gt; </codeline>
<codeline>&lt;!ELEMENT p ( #PCDATA | a | ul | b | i | em ) * &gt; </codeline>
<codeline>&lt;!ELEMENT p ( #PCDATA | %font; | %phrase; | %special; | %form: ) * &gt; </codeline>
<codeline>&lt;!ELEMENT b ( #PCDATA ) &gt; </codeline>
</code>
</section>
<section><section-header>Attribut Definitionen</section-header>
<para>Format:</para>
<code>
<codeline>&lt;!ATTLIST elementname (attributname, attributtyp, default-deklaration?)* &gt; </codeline>
</code>
<para>Mit Attributen lassen sich Name-Wert-Paare mit Elementen verknüpfen. Sie dürfen ausschließlich in Start- und Leeres-Element-Tags erscheinen.</para>
<para>Attributdefinitionen für einen Elementtypen werden vereinigt in einer Attributlist-Definition. Werden mehrere Definitionen für einen Elementtypen angegeben werden, gilt zwingend die erste Deklaration. (kein Fehler, Prozessor kann benutzeroptional eine Warnung ausgeben)</para>
<para>Elementname ist der Name eines Elementtyps für welches das Attribut definiert wird; Dieser Elementtyp selbst muss nicht definiert sein. kein Fehler, Prozessor kann benutzeroptional eine Warnung ausgeben)</para>
<para>Attributname ist der Name des Attributs.</para>
<para>Mögliche Typen sind StringType, EnumeratedType und TokenizedType.</para>
<section>
<section-header>StringType</section-header>
<para>Kann lediglich CDATA aufnehmen; als String, der nicht geparst wird, somit werden Entity-Referenzen in diesem Text nicht aufgelöst</para>
</section>
<section><section-header>EnumeratedType</section-header>
<para>Aufzählungstypen können einen Wert aus einer deklarierten Liste von Werten annehmen. Es können zwei unterschiedliche Typen (Enumeration und NotationType) verwendet werden. Die Enumeration stellt eine Liste von Vorgabewerten dar, von denen ein einzelner auszuwählen ist.</para>
<para>Der NotationType Bindet das Element an eine Notation, die mit System- und/oder Public-Identifier deklariert ist. Die Notation dient dazu, das Element mit diesem Attribut zu interpretieren.</para>
</section>
<section><section-header>TokenizedType</section-header>
<para>Bei diesem Typ wird das Attribut mit einem der folgenden Token deklariert:</para>
<table>
<tr>
<th><para>Token</para>
</th>
<th><para>Bedeutung</para>
</th>
</tr>
<tr>
<td><para>ID</para>
</td>
<td><para>Eindeutiger Schlüssel (es ist nur ein solches Attribut pro Element erlaubt, und muss einen deklarierten Vorgabewert haben; entweder #IMPLIED oder #REQUIRED)</para>
</td>
</tr>
<tr>
<td><para>IDREF</para>
</td>
<td><para>Das Attribut muss den Wert des ID-Attributs eines anderen Elements annehmen.</para>
</td>
</tr>
<tr>
<td><para>IDREFS</para>
</td>
<td><para>Liste von IDREF (getrennt mit Whitespaces).</para>
</td>
</tr>
<tr>
<td><para>ENTITY</para>
</td>
<td><para>Referenziert ein in der DTD angegebenes Entity</para>
</td>
</tr>
<tr>
<td><para>ENTITIES</para>
</td>
<td><para>Liste von ENTITY</para>
</td>
</tr>
<tr>
<td><para>NMTOKEN</para>
</td>
<td><para>Namenstoken</para>
</td>
</tr>
<tr>
<td><para>NMTOKENS</para>
</td>
<td><para>Liste von Token (vergl. Enumeration)</para>
</td>
</tr>
<label>Tabelle 2: TokenizedType-Varianten</label>
</table>
<para>Um die Verwendung des Attributs zu steuern, lässt es sich als erforderlich (required), unbestimmt, bzw. ohne Vorgabewert (implied) und als konstant (fixed) bzgl. des Vorgabewert definieren.</para>
<code>
<label>Beispiel 11: Attribut-Listen-Definitionen</label>
<codeline>&lt;!ATTLIST termdef </codeline>
<codeline>          id     ID     #REQUIRED </codeline>
<codeline>          name   CDATA  #IMPLIED&gt; </codeline>
<codeline>&lt;!ATTLIST list </codeline>
<codeline>          type   (bullets|ordered|glossary) &quot;ordered&quot;&gt; </codeline>
<codeline>&lt;!ATTLIST form </codeline>
<codeline>          method CDATA  #FIXED &quot;POST&quot;&gt; </codeline>
</code>
</section>
</section>
<section><section-header>Entities und Notationen</section-header>
<section>
<section-header>Notationen</section-header>
<para>Format:</para>
<code>
<codeline>&lt;!NOTATION name ( externalID | PublicID ) &gt; </codeline>
</code>
<para>Durch Notationen können Dateninhalte externen Quellen zugeordnet werden.</para>
<para>Als solche typisierte Daten werden nicht vom Parser interpretiert sondern an die Anwendung weitergegeben, welche anhand der Notation weitere Informationen zu den Daten erhält oder heranziehen kann.</para>
<code>
<label>Beispiel 12: Notationen</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt; </codeline>
<codeline>&lt;!DOCTYPE someContent [ </codeline>
<codeline>&lt;!NOTATION isoDate SYSTEM &quot;http://www.iso.ch/markete/8601.pdf&quot;&gt; </codeline>
<codeline>&lt;!NOTATION gif PUBLIC             </codeline>
<codeline>&quot;-//Compuserve Information Services//NOTATION Graphics  </codeline>
<codeline>Interchange Format//EN&quot;&gt; </codeline>
<codeline>&lt;!NOTATION hex SYSTEM &quot;hexEditor.exe&quot;&gt; </codeline>
<codeline>&lt;!ELEMENT someContent (#PCDATA)&gt; </codeline>
<codeline>&lt;!ATTLIST someContent format NOTATION (hex) #IMPLIED&gt; ]&gt; </codeline>
<codeline>&lt;someContent format=&quot;hex&quot;&gt;4C 65 74 20 61 6C 6C 20 68 6F 70 65 20 61  </codeline>
<codeline>62 61 6E 64 6F 6E 2C 20 79 65 20 77 68 6F 20 6D 61 79 20 65 6E 74  </codeline>
<codeline>65 72 20 68 65 72 65 21&lt;/someContent&gt; </codeline>
</code>
</section>
<section><section-header>Zeichenreferenzen / Entity-Referenzen (Interne Entities)</section-header>
<para>Zeichenreferenzen verweisen auf spezifische Zeichen im ISO/IEC 10646, als Hex- oder als Dezimalzahl.</para>
<para>Entity-Referenzen verweisen auf den Inhalt eines benannten Entity. Man unterscheidet allgemeine Entity und Parameterentity. Parameterentity werden nur innerhalb der DTD verwendet.</para>
<para>Format:</para>
<code>
<codeline>Allgemein: 	&lt;!ENTITY name &quot;wert&quot;&gt; </codeline>
<codeline>Parameter: 	&lt;!ENTITY % name &quot;wert&quot;&gt; </codeline>
</code>
<code>
<label>Beispiel 13: Entity</label>
<codeline>&lt;!ENTITY copyright &quot;&amp;#xA9&quot;&gt; </codeline>
<codeline>&lt;legalnotes&gt;&amp;copyright; 2002&lt;/legalnotes&gt; </codeline>
<codeline>&lt;!ENTITY % pcdata &quot;(#PCDATA)&quot;&gt; </codeline>
<codeline>&lt;!ELEMENT authortitle %pcdata; &gt; </codeline>
</code>
</section>
<section><section-header>Externe Entities und Unparsed Entities</section-header>
<para>Format:</para>
<code>
<codeline>&lt;!ENTITY name ( SYSTEM | PUBLIC ) quelle ( NDATA notationsreferenz )? &gt; </codeline>
</code>
<para>Mittels externen Entities lassen sich Daten von einer angegebenen URI dynamisch in das Dokument laden.</para>
<code>
<label>Beispiel 14: Externer Entity</label>
<codeline>&lt;!ENTITY fremd SYSTEM &quot;fremd.xml&quot;&gt; </codeline>
</code>
<para>Mittels Unparsed Entities lassen sich Daten, die kein XML sind, in XML-Dokumente dynamisch einbinden.</para>
<code>
<label>Beispiel 15: Unparsed Entity</label>
<codeline>&lt;!ENTITY tollesfoto SYSTEM &quot;mein_tolles_foto.jpg&quot; NDATA jpg&gt; </codeline>
</code>
<para>Hierbei wird eine Notationsdeklaration für jpg vorausgesetzt, damit bekannt ist, wie mit diesen Daten verfahren werden muss.</para>
</section>
</section>
<section><section-header>Kritikpunkte an DTD</section-header>
<ul><para><li>
Unzureichende Datentypen-Unterstützung (eigentlich nur String)</li>
</para>
<para><li>
Unzureichende Strukturunterstützung</li>
</para>
<para><li>
Prinzipiell beliebige Kardinalität möglich, durch Operatoren zur Steuerung von Auftrittshäufigkeiten. Doch: umständlich, fehleranfällig, unübersichtlich.</li>
</para>
<para><li>
Keine Wiederverwertbarkeit vorgesehen</li>
</para>
<para><li>
Nicht erweiterbar</li>
</para>
<para><li>
Keine Unterstützung von Namensräume</li>
</para>
<para><li>
Nur rudimentärer Referenzierungsmechanismus ( ID, IDREF, IDREFS )</li>
</para>
<para><li>
DTD ist kein XML</li>
</para>
</ul></section>
</section>
</section>
<section><section-header>XML-Schema</section-header>
<para>Dieses Kapitel richtet sich nach dem Dokument &quot;XML Schema Part 0: Primer&quot; des W3C (http://www.w3c.org/TR/2001/REC-xmlschema-0-20010502/). Es soll eine nicht-normative Einführung in XML-Schema darstellen. Für weitere Informationen bzgl. spezifischer Fragestellungen wird auf die Teilen 1 (Structures) und 2 (Datatypes) der Schema-Definition verwiesen.</para>
<section>
<section-header>Grundlagen</section-header>
<para>Der Zweck von XML-Schema besteht darin, eine Klasse von XML-Dokumenten zu definieren. Daher wird ein XML-Dokument, das einem solchen Schema entspricht häufig als Instanz-Dokument Bezeichnet.</para>
<section>
<section-header>Das Instanzdokument purchase order</section-header>
<para>Wir beginnen mit einem Beispiel welches einen Bestellauftrag enthält, generiert von einer Bestelloberfläche bspw. in einem Internetshop.</para>
<code>
<label>Beispiel 16: Instanzdokument Purchase Order</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;purchaseOrder orderDate=&quot;1999-10-20&quot;&gt; </codeline>
<codeline>	&lt;shipTo country=&quot;US&quot;&gt; </codeline>
<codeline>		&lt;name&gt;Alice Smith&lt;/name&gt; </codeline>
<codeline>		&lt;street&gt;123 Maple Street&lt;/street&gt; </codeline>
<codeline>		&lt;city&gt;Mill Valley&lt;/city&gt; </codeline>
<codeline>		&lt;state&gt;CA&lt;/state&gt;&lt;zip&gt;90952&lt;/zip&gt; </codeline>
<codeline>	&lt;/shipTo&gt; </codeline>
<codeline>	&lt;billTo country=&quot;US&quot;&gt; </codeline>
<codeline>		&lt;name&gt;Robert Smith&lt;/name&gt; </codeline>
<codeline>		&lt;street&gt;8 Oak Avenue&lt;/street&gt; </codeline>
<codeline>		&lt;city&gt;Old Town&lt;/city&gt; </codeline>
<codeline>		&lt;state&gt;PA&lt;/state&gt;&lt;zip&gt;95819&lt;/zip&gt; </codeline>
<codeline>	&lt;/billTo&gt; </codeline>
<codeline>	&lt;comment&gt;Hurry, my lawn is going wild!&lt;/comment&gt; </codeline>
<codeline>	&lt;items&gt; </codeline>
<codeline>		&lt;item partNum=&quot;872-AA&quot;&gt; </codeline>
<codeline>			&lt;productName&gt;Lawnmower&lt;/productName&gt; </codeline>
<codeline>			&lt;quantity&gt;1&lt;/quantity&gt; </codeline>
<codeline>			&lt;USPrice&gt;148.95&lt;/USPrice&gt; </codeline>
<codeline>			&lt;comment&gt;Confirm this is electric&lt;/comment&gt; </codeline>
<codeline>		&lt;/item&gt; </codeline>
<codeline>		&lt;item partNum=&quot;926-AA&quot;&gt; </codeline>
<codeline>			&lt;productName&gt;Baby Monitor&lt;/productName&gt; </codeline>
<codeline>			&lt;quantity&gt;1&lt;/quantity&gt; </codeline>
<codeline>			&lt;USPrice&gt;39.98&lt;/USPrice&gt; </codeline>
<codeline>			&lt;shipDate&gt;1999-05-21&lt;/shipDate&gt; </codeline>
<codeline>		&lt;/item&gt; </codeline>
<codeline>	&lt;/items&gt; </codeline>
<codeline>&lt;/purchaseOrder&gt; </codeline>
</code>
<para>Die Bestellung besteht aus einem Hauptelement (purchaseOrder) und dessen Kindelementen shipTo, billTo, comment und items. Die Kindelemente enthalten wiederum Subelemente (comment ausgenommen) usw. bishin zu einem Element wie USPrice, welches eine Zahl anstelle weiterer Elemente enthält.</para>
<para>Elemente mit Kindelementen oder Attributen werden als komplexe Typen bezeichnet (complexType). Solche, die Zahlen, Text o.ä., aber keine Kindelemente enthalten oder Attribute besitzen, werden als simple Typen bezeichnet (simpleType). Attribute selbst sind immer simple Typen.</para>
<para>Die komplexen Typen (und einige der simplen) in diesem Instanzdokument, sind im Schema für das Dokument definiert. Die anderen, dort nicht definierten, gehören zur Sammlung der von XML-Schema vordefinierten Typen (primitive Typen).</para>
<para>Im Übrigen muss die Referenz auf das Schema nicht zwangsläufig in einem Instanzdokument eingetragen sein; vorausgesetzt, der Prozessor weiß um das Schema, bzw. wo es erreichbar ist.</para>
</section>
<section><section-header>Das Schema zum purchase order</section-header>
<code>
<label>Beispiel 17: Das Schema für das purchase order Dokument</label>
<codeline>&lt;xsd:schema xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;&gt; </codeline>
<codeline>&lt;xsd:annotation&gt; </codeline>
<codeline>	&lt;xsd:documentation xml:lang=&quot;en&quot;&gt; </codeline>
<codeline>		Purchase order schema for Example.com. </codeline>
<codeline>		Copyright 2000 Example.com. All rights reserved. </codeline>
<codeline>	&lt;/xsd:documentation&gt; </codeline>
<codeline>&lt;/xsd:annotation&gt; </codeline>
<codeline>&lt;xsd:element name=&quot;purchaseOrder&quot; type=&quot;PurchaseOrderType&quot;/&gt; </codeline>
<codeline>&lt;xsd:element name=&quot;comment&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>&lt;xsd:complexType name=&quot;PurchaseOrderType&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;shipTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;billTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;items&quot;  type=&quot;Items&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;orderDate&quot; type=&quot;xsd:date&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;xsd:complexType name=&quot;USAddress&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;name&quot;   type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;street&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;city&quot;   type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;state&quot;  type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;zip&quot;    type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;country&quot; type=&quot;xsd:NMTOKEN&quot; fixed=&quot;US&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;xsd:complexType name=&quot;Items&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;item&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;&gt; </codeline>
<codeline>			&lt;xsd:complexType&gt; </codeline>
<codeline>				&lt;xsd:sequence&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;productName&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;quantity&quot;&gt; </codeline>
<codeline>						&lt;xsd:simpleType&gt; </codeline>
<codeline>							&lt;xsd:restriction base=&quot;xsd:positiveInteger&quot;&gt; </codeline>
<codeline>								&lt;xsd:maxExclusive value=&quot;100&quot;/&gt; </codeline>
<codeline>							&lt;/xsd:restriction&gt; </codeline>
<codeline>						&lt;/xsd:simpleType&gt; </codeline>
<codeline>					&lt;/xsd:element&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;USPrice&quot;  type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element ref=&quot;comment&quot;   minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; </codeline>
<codeline>														minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>				&lt;/xsd:sequence&gt; </codeline>
<codeline>				&lt;xsd:attribute name=&quot;partNum&quot; type=&quot;SKU&quot; </codeline>
<codeline>												use=&quot;required&quot;/&gt; </codeline>
<codeline>			&lt;/xsd:complexType&gt; </codeline>
<codeline>		&lt;/xsd:element&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;!-- Stock Keeping Unit, a code for identifying products --&gt; </codeline>
<codeline>&lt;xsd:simpleType name=&quot;SKU&quot;&gt; </codeline>
<codeline>	&lt;xsd:restriction base=&quot;xsd:string&quot;&gt; </codeline>
<codeline>		&lt;xsd:pattern value=&quot;\d{3}-[A-Z]{2}&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:restriction&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt; </codeline>
<codeline>&lt;/xsd:schema&gt; </codeline>
</code>
<para>Das Schema enthält ein schema-Element mit verschiedenen Kindelementen. Die wesentlichen davon sind: element, complexType und simpleType, die das Aussehen von Elementen und deren Inhalt im Instanzdokument festlegen.</para>
<para>Jedes der Elemente trägt das Präfix xsd, welches mit dem XML-Schema-Namensraum assoziert wurde durch die Deklaration im schema-Element. Das Präfix xsd wird per Konvention mit dem XML-Schema-Namensraum verknüpft; andere Präfixe sind prinzipiell möglich.</para>
<para>Die gleiche Bindung an diesen Namensraum findet sich wieder bei den Angaben zu den vordefinierten simplen Typen (bspw.: xsd:string). Damit wird die Zugehörigkeit zum Standardrepertoir verdeutlicht.</para>
</section>
</section>
<section><section-header>Definition komplexer Typen, Elementen- und Attributdeklaration</section-header>
<para>XML-Schema unterscheidet grundsätzlich zwischen complexType&apos;s, mit möglichen Kindelementen und Attributen, und simpleType&apos;s (die weder über das eine noch das andere verfügen können).</para>
<para>Außerdem wird unterscheidet man zwischen Definition von Typen und der Deklaration. Die Definition beschreibt einen Typen; mit der Deklaration wendet man sie an und beschreibt Elemente, die mit einem spezifischen Namen und Typen im Dokument auftreten dürfen.</para>
<para>Neue komplexe Typen werden mit dem complexType-Element definiert, das typischerweise eine Reihe weiterer Element-, Referenzen und Attributdeklarationen enthält. Die Deklarationen sind für sich genommen keine Typen, sie bilden allerdings die Assoziation zwischen einem Namen und den Vorschriften, die das Erscheinungsbild des Elements bestimmen. Elemente werden mit dem element-Element deklariert. Attribute mit dem attribute-Element.</para>
<code>
<label>Beispiel 18: Definition vom USAddress Typ</label>
<codeline>&lt;xsd:complexType name=&quot;USAddress&quot; &gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;name&quot;   type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;street&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;city&quot;   type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;state&quot;  type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;zip&quot;    type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;country&quot; type=&quot;xsd:NMTOKEN&quot; fixed=&quot;US&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
</code>
<para>Aus dieser Definition geht hervor, das alle Elemente im Instanzdokument, dessen Typ als USAddress deklariert wurde, aus fünf Elementen und einem Attribut bestehen muss. Diese Elemente müssen die mittels der name-Attribute vorgeschriebenen Namen tragen, und in der deklarierten Reihenfolge auftreten. Die ersten vier müssen einen string-Wert enthalten, das fünfte eine Zahl. Ein USAddress-Element darf ein Attribut namens country enthalten, dessen Wert &quot;US&quot; vorgegeben ist.</para>
<para>Diese Definition verwendet lediglich simpleType-Deklarationen (string, decimal, NMTOKEN). Die PurchaseOrderType-Definition enthält dagegen auch komplexe Typen bspw. USAddress. Beide verwendet das type-Attribut um den Typen zu identifizieren, unabhängig davon, ob es sich dabei um einen komplexen oder simplen Typen handelt.</para>
<code>
<label>Beispiel 19: Definition PurchaseOrderType</label>
<codeline>&lt;xsd:complexType name=&quot;PurchaseOrderType&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;shipTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;billTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;items&quot;  type=&quot;Items&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;orderDate&quot; type=&quot;xsd:date&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
</code>
<para>In dieser Definition assoziieren zwei Element-Deklarationen Elementnamen mit dem USAddress-Typ. Daraus folgt, das jedes Element im Instanzdokument, welches vom Typ PurchaseOrderType ist, zwei Kindelemente vom Typ USAddress enthalten muss (shipTo und billTo), die die fünf Subelemente von USAddress enthalten müssen. Diese dürfen wiederum jeweils das Attribut country tragen. Die PurchaseOrderType-Definition enthält ein orderDate-Attribut als simplen Typen date.</para>
<para>Die bis hierhin beschriebenen Deklarationen haben jeweils einen Namen mit einer Typ-Definition verbunden. Manchmal ist es jedoch von Vorteil, ein bereits existierendes Element zu verwenden.</para>
<code>
<label>Beispiel 20: Existierendes Element wiederverwenden</label>
<codeline>&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
</code>
<para>Diese Deklaration referenziert ein bestehendes Element comment, das an anderer Stelle im Schema deklariert wurde. Generell muss der Wert des ref-Attributes auf ein globales Element verweisen, also eines, das direkt unter dem schema-Element deklariert wurde, und nicht als Teil eines complexType-Elements. Die Folgerung aus dieser Deklaration ist, das ein comment-Element in einem Instanzdokument verwendet werden kann, und dessen Inhalt übereinstimmen muss mit dem Element-Typen, in diesem Fall string.</para>
<section>
<section-header>Auftrittssteuerung</section-header>
<section>
<section-header>Elemente: minOccurs, maxOccurs</section-header>
<para>Das comment-Element ist optional im PurchaseOrderType, da der Wert des minOccurs-Attributs in seiner Deklaration 0 ist. Im Allgemeinen gilt, das ein Element auftreten muss, wenn der Wert von minOccurs 1 oder höher ist. Das maximale Vorkommen eines Elements wird über das Attribut maxOccurs in der Deklaration gesteuert. Als gültige Werte beider Attribute werden ganzzahlige, positive Werte akzeptiert, im Falle von maxOccurs zusätzlich &quot;unbounded&quot; um anzugeben, das kein Maximum festgelegt wird. Werden diese Attribute nicht angegeben, wird in beiden Fällen von 1 ausgegangen. Werden dementsprechend beide nicht angegeben, gilt, dass das Element genau einmal auftreten muss. Es ist im Übrigen darauf zu achten, das der Wert für maxOccurs größer oder gleich minOccurs ist.</para>
</section>
<section><section-header>Attribute: use</section-header>
<para>Attribute dürfen einmal oder keinmal auftreten. Mehrfach ist nicht erlaubt. Daher ist die Syntax etwas anders, als die für Elemente. Es wird hierfür das use-Attribut verwendet, welches festlegt, ob ein Attribut angegeben werden muss (required), optional angegeben werden kann (optional) oder nicht verwendet werden darf (prohibited). Wird use nicht angegeben, gilt optional.</para>
</section>
<section><section-header>Elemente und Attribute: default</section-header>
<para>Die Vorgabewerte werden für Elemente wie für Attribute über das default-Attribut gesteuert, wobei die Auswirkung jeweils eine etwas andere ist. Wird ein Default-Wert für ein Attribut angegeben, wird dieses vom Prozessor verwendet, wenn das Attribut im Instanzdokument nicht angegeben wird. In diesem Fall setzt der Prozessor den default-Wert für das Attribut ein. default-Werte machen nur Sinn bei Attributen, deren Auftreten optional ist. Andere use-Vorgaben in Kombination mit einem default-Wert sind Fehler!</para>
<para>Bei Elementen wird der Vorgabewert etwas anders gehandhabt. Ist ein Element mit einem Vorgabewert deklariert worden und das Element im Instanzdokument keinen Inhalt hat, setzt der Prozessor den default-Wert ein. Wenn allerdings das Element im Instanzdokument gar nicht erscheint, wird auch nichts an seiner Stelle durch den Prozessor eingesetzt.</para>
<para>Also: Vorgabewerte von Attributen werden angewendet, wenn das Attribut fehlt (nicht wenn es angegeben wurde mit leerem Inhalt). Vorgabewerte von Elementen werden angewendet, wenn das Element vorhanden aber leer ist (nicht wenn das Element selbst nicht vorhanden ist).</para>
</section>
<section><section-header>Elemente und Attribute: fixed</section-header>
<para>Das fixed-Attribut kann in Attribut- und Elementdeklarationen verwendet werden, um sicher zu stellen, das diese im Instanzdokument bestimmte Werte haben. Im Beispiel ist dies das country-Attribut, das den fixierten Wert &quot;US&quot; enthält. In dieser Deklaration heißt es, dass das country-Attribut optional anzugeben ist, wenn es angegeben wird allerdings den Wert &quot;US&quot; tragen muss, und wenn es nicht angegeben wird, der Prozessor den default-Wert &quot;US&quot; einsetzt. Ein Attribut kann nicht gleichzeitig fixiert sein und einen default-Wert haben.</para>
<table>
<tr>
<th><para>Elemente</para>
</th>
<th><para>Attribute</para>
</th>
<th><para>Erklärung</para>
</th>
</tr>
<tr>
<td><para>minOccurs, maxOccurs, fixed, default</para>
</td>
<td><para>use, fixed, default</para>
</td>
<td></td>
</tr>
<tr>
<td><para>(1, 1) -, -</para>
</td>
<td><para>required, -, -</para>
</td>
<td><para>Element/Attribut muss einmal auftreten und darf beliebigen Wert enthalten.</para>
</td>
</tr>
<tr>
<td><para>(1, 1) 37, -</para>
</td>
<td><para>required, 37, -</para>
</td>
<td><para>Element/Attribut muss einmal auftreten, der Wert muss 37 sein.</para>
</td>
</tr>
<tr>
<td><para>(2, unbounded) 37, -</para>
</td>
<td><para>n/a</para>
</td>
<td><para>Element/Attribut muss mindestens zwei mal auftreten und der Wert muss 37 betragen.</para>
</td>
</tr>
<tr>
<td><para>(0, 1) -, -</para>
</td>
<td><para>optional, -, -</para>
</td>
<td><para>Element/Attribut darf keinmal oder einmal auftreten, der Wert ist beliebig.</para>
</td>
</tr>
<tr>
<td><para>(0, 1) 37, -</para>
</td>
<td><para>optional, 37, -</para>
</td>
<td><para>Element/Attribut darf einmal auftreten. Ist es vorhanden, muss der Wert 37 sein, ist es nicht vorhanden, wird 37 eingesetzt.</para>
</td>
</tr>
<tr>
<td><para>(0, 1) -, 37</para>
</td>
<td><para>optional, -, 37</para>
</td>
<td><para>Element/Attribut darf einmal auftreten. Ist es vorhanden, darf es beliebigen Wert enthalten. Ist es nicht vorhanden, wird 37 eingesetzt.</para>
</td>
</tr>
<tr>
<td><para>(0, 2) -, 37</para>
</td>
<td><para>n/a</para>
</td>
<td><para>Element/Attribut darf kein mal, einmal oder zweimal auftreten. Wenn es nicht vorhanden ist, gilt es als fehlend, ist es vorhanden und leer wird der Wert 37 eingesetzt. Ansonsten ist der Wert, der enthalten ist.</para>
</td>
</tr>
<tr>
<td><para>(0, 0) -, -</para>
</td>
<td><para>prohibited, -, -</para>
</td>
<td><para>Element/Attribut darf nicht auftreten.</para>
</td>
</tr>
<tr>
<td><para>Hinweis:  minOccurs, maxOccurs, und use dürfen nicht in der Deklaration von globalen Elementen oder Attributen verwendet.</para>
</td>
<td></td>
<td></td>
</tr>
<label>Tabelle 3: Zusammenfassung der einzelnen Auftrittssteuerungsangaben für Elemente und Attribute</label>
</table>
</section>
</section>
<section><section-header>Globale Elemente und Attribute</section-header>
<para>Globale Elemente und Attribute werden durch Deklaration als Kind des schema-Elements erzeugt. Einmal deklariert, lassen sich globale Elemente oder Attribute in beliebigen anderen Deklarationen durch Anwendung des ref-Attributs (s.o.) referenzieren.</para>
<para>Durch das Referenzieren von Deklarationen ermöglicht man das Auftreten des referenzierten Elements in einem Instanzdokument im Kontext der referenzierenden Deklaration.</para>
<para>Die Deklaration eines globalen Elements ermöglicht das Auftreten des Elements als Top-Level-Element im Instanzdokument. (Im Beispiel ist also, neben purchaseOrder auch comment als Top-Level-Element möglich.)</para>
<para>Einige Einschränkungen bei der Verwendung von globalen Elementen und Attributen: Eine globale Deklaration selbst kann keine Referenzen enthalten, sondern muss komplexe wie simple Typen direkt einbinden. Das ref-Attribut ist in globalen Elementen also nicht erlaubt. Auch können globale Deklarationen nicht mit den Attributen minOccurs, maxOccurs oder use versehen werden.</para>
</section>
<section><section-header>Namenskonflikte</section-header>
<para>Ein Namenskonflikt tritt auf, wenn zwei Typen mit gleichem Namen definiert wurden. Ist ein Typ mit dem gleichen Namen vorhanden wie ein Element oder ein Attribut, dann ist dies kein Konflikt. Werden Elemente mit dem gleichen Namen innerhalb unterschiedlicher Typen definiert, so ist auch dies kein Konflikt aufgrund der lokalen Deklaration. Auch wenn zwei Typen definiert wurden, die den gleichen Namen tragen, jedoch jeweils zu einem anderen Namensraum gehören, ist dies kein Konflikt.</para>
</section>
</section>
<section><section-header>Simple Typen</section-header>
<para>XML-Schema bringt eine Reihe von vordefinierten, simplen Typen mit. Des Weiteren ist es möglich, neue simple Typen durch Vererbung zu definieren. Beide Arten von simplen Typen können nachfolgend in Element- und Attribut-Deklarationen verwendet werden. Die andere Form definierter Typen, die komplexen Typen, können lediglich auf Elemte angewendet werden,</para>
<table>
<tr>
<th><para>Simpler Typ</para>
</th>
<th><para>Beispiele (Kommata-getrennt)</para>
</th>
<th><para>Hinweise</para>
</th>
</tr>
<tr>
<td><para>String</para>
</td>
<td><para>Confirm this is electric</para>
</td>
<td></td>
</tr>
<tr>
<td><para>NormalizedString</para>
</td>
<td><para>Confirm this is electric</para>
</td>
<td><para>siehe (3)</para>
</td>
</tr>
<tr>
<td><para>token</para>
</td>
<td><para>Confirm this is electric</para>
</td>
<td><para>siehe (4)</para>
</td>
</tr>
<tr>
<td><para>byte</para>
</td>
<td><para>-1, 126</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>UnsignedByte</para>
</td>
<td><para>0, 126</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>base64Binary</para>
</td>
<td><para>GpM7</para>
</td>
<td></td>
</tr>
<tr>
<td><para>HexBinary</para>
</td>
<td><para>0FB7</para>
</td>
<td></td>
</tr>
<tr>
<td><para>Integer</para>
</td>
<td><para>-126789, -1, 0, 1, 126789</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>PositiveInteger</para>
</td>
<td><para>1, 126789</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>NegativeInteger</para>
</td>
<td><para>-126789, -1</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>NonNegativeInteger</para>
</td>
<td><para>0, 1, 126789</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>NonPositiveInteger</para>
</td>
<td><para>-126789, -1, 0</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>int</para>
</td>
<td><para>-1, 126789675</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>UnsignedInt</para>
</td>
<td><para>0, 1267896754</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>long</para>
</td>
<td><para>-1, 12678967543233</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>UnsignedLong</para>
</td>
<td><para>0, 12678967543233</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>short</para>
</td>
<td><para>-1, 12678</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>UnsignedShort</para>
</td>
<td><para>0, 12678</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>decimal</para>
</td>
<td><para>-1.23, 0, 123.4, 1000.00</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>float</para>
</td>
<td><para>-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN</para>
</td>
<td><para>Äquivalent zu einfach-genauem 32-Bit-Fließkomma; NaN bedeutet &quot;not a number&quot;, siehe (2)</para>
</td>
</tr>
<tr>
<td><para>double</para>
</td>
<td><para>-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN</para>
</td>
<td><para>Äquivalent zu einfach doppelt-genauem 64-bit Fließkomma; NaN bedeutet &quot;not a number&quot;, siehe (2)</para>
</td>
</tr>
<tr>
<td><para>boolean</para>
</td>
<td><para>True, false
1, 0</para>
</td>
<td></td>
</tr>
<tr>
<td><para>time</para>
</td>
<td><para>13:20:00.000, 13:20:00.000-05:00</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>dateTime</para>
</td>
<td><para>1999-05-31T13:20:00.000-05:00</para>
</td>
<td><para>31. Mai 1999, 13:20 Uhr Eastern Standard Time (5 Stunden auf Co-Ordinated Universal Time zurück), siehe (2)</para>
</td>
</tr>
<tr>
<td><para>duration</para>
</td>
<td><para>P1Y2M3DT10H30M12.3S</para>
</td>
<td><para>1 Jahr, 2 Monate, 3 Tage, 10 Stunden, 30 Minuten und 12.3 Sekunden</para>
</td>
</tr>
<tr>
<td><para>date</para>
</td>
<td><para>1999-05-31</para>
</td>
<td><para>siehe (2)</para>
</td>
</tr>
<tr>
<td><para>gMonth</para>
</td>
<td><para>--05--</para>
</td>
<td><para>Mai, siehe (2) (5)</para>
</td>
</tr>
<tr>
<td><para>gYear</para>
</td>
<td><para>1999</para>
</td>
<td><para>1999, siehe (2) (5)</para>
</td>
</tr>
<tr>
<td><para>gYearMonth</para>
</td>
<td><para>1999-02</para>
</td>
<td><para>Der Monat Februar 1999, unabhängig der Anzahl von Tagen, siehe (2) (5)</para>
</td>
</tr>
<tr>
<td><para>gDay</para>
</td>
<td><para>---31</para>
</td>
<td><para>der 31. Tag, siehe (2) (5)</para>
</td>
</tr>
<tr>
<td><para>gMonthDay</para>
</td>
<td><para>--05-31</para>
</td>
<td><para>jeder 31. Mai, siehe (2) (5)</para>
</td>
</tr>
<tr>
<td><para>Name</para>
</td>
<td><para>ShipTo</para>
</td>
<td><para>XML 1.0 Name type</para>
</td>
</tr>
<tr>
<td><para>QName</para>
</td>
<td><para>po:USAddress</para>
</td>
<td><para>XML Namespace QName</para>
</td>
</tr>
<tr>
<td><para>NCName</para>
</td>
<td><para>USAddress</para>
</td>
<td><para>XML Namespace NCName, d.h. QName ohne Präfix und Doppelpunkt</para>
</td>
</tr>
<tr>
<td><para>anyURI</para>
</td>
<td><para>Http://www.example.com/, http://www.example.com/doc.html#ID5</para>
</td>
<td></td>
</tr>
<tr>
<td><para>language</para>
</td>
<td><para>en-GB, en-US, fr</para>
</td>
<td><para>Gültige Werte für xml:lang wie in XML 1.0</para>
</td>
</tr>
<tr>
<td><para>ID</para>
</td>
<td></td>
<td><para>XML 1.0 ID Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>IDREF</para>
</td>
<td></td>
<td><para>XML 1.0 IDREF Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>IDREFS</para>
</td>
<td></td>
<td><para>XML 1.0 IDREFS Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>ENTITY</para>
</td>
<td></td>
<td><para>XML 1.0 ENTITY Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>ENTITIES</para>
</td>
<td></td>
<td><para>XML 1.0 ENTITIES Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>NOTATION</para>
</td>
<td></td>
<td><para>XML 1.0 NOTATION Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>NMTOKEN</para>
</td>
<td><para>US,
Brésil</para>
</td>
<td><para>XML 1.0 NMTOKEN Attribut-Typ, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>NMTOKENS</para>
</td>
<td><para>US UK,
Brésil Canada Mexique</para>
</td>
<td><para>XML 1.0 NMTOKENS Attribut-Typ, d.h. eine Whitespace-getrennte List von NMTOKEN&apos;s, siehe (1)</para>
</td>
</tr>
<tr>
<td><para>Hinweise:</para>
<ul><para><li>
Um Kompatibilität zwischen XML-Schema und XML 1.0 DTD zu gewährleisten, sollten die simplen Typen ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN, NMTOKENS nur in Attribute verwendet werden.</li>
</para>
<para><li>
Ein Wert diesen Typs kann in verschiedenen Schreibweisen vorliegen, bspw. sind 100 und 1.0E2 beide gültige Fließkomma-Werte, die &quot;einhundert&quot; darstellen. Allerdings wurden Regeln eingeführt, die ein bestimmtes lexikalisches Format vorschreiben.</li>
</para>
<para><li>
Zeilenvorschub-, Tabulator- und Wagenrücklauf-Zeichen in einem normalizedString werden zu Leerzeichen konvertiert vor dem Verarbeiten des Schemas.</li>
</para>
<para><li>
Wie normalizedString; zusätzlich werden mehrere Leerzeichen zu einem zusammengefaßt, führende und folgende Leerzeichen werden entfernt.</li>
</para>
<para><li>
Das &quot;g&quot;-Präfix signalisiert Zeitangaben nach dem Gregorianischen Kalender.</li>
</para>
</ul></td>
</tr>
<label>Tabelle 4: Simple Typen von XML Schema</label>
</table>
<para>Neue simple Typen werden von bestehenden (eingebauten oder hergeleiteten) abgeleitet. Dazu wird der vorhandene Type in seinem Umfang eingeschränkt, so dass der neu entstehende Typ eine Untermenge des ursprünglichen Typs darstellt.</para>
<para>Das simpleType-Element wird verwendet, um den neuen, simplen Typ zu benennen und zu definieren. In ihm wird das restriction-Element verwendet, um den Basistypen zu spezifizieren, von dem abgeleitet werden soll, und die &quot;facets&quot; (Facetten) zu benennen, die die Einschränkungen darstellen. Mögliche Facetten: length, minLength, maxLength, pattern, enumeration, whiteSpace, maxInclusive, maxExclusive, minInclusive, minExclusive, totalDigits und fractionDigits. Nicht alle Facetten können jedoch auf alle Typen angewendet werden.</para>
<para>Soll ein neuer Integer-Typ gebildet werden, bei dem die Spanne gültiger Werte von 10000 bis zu 99999 (inklusive) reicht, wird vom simplen Typen integer abgeleitet, und entsprechend der minimale und maximale Wert begrenzt.</para>
<code>
<label>Beispiel 21: minInclusive und maxInclusive</label>
<codeline>&lt;xsd:simpleType name=&quot;myInteger&quot;&gt; </codeline>
<codeline>	&lt;xsd:restriction base=&quot;xsd:integer&quot;&gt; </codeline>
<codeline>		&lt;xsd:minInclusive value=&quot;10000&quot;/&gt; </codeline>
<codeline>		&lt;xsd:maxInclusive value=&quot;99999&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:restriction&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt; </codeline>
</code>
<para>Andere Restriktionen führen ggf. ebenfalls zum gewünschten Ergebnis.</para>
<para>Mit pattern&apos;s lassen sich reguläre Ausdrücke zum Beschränken des Gültigkeitsbereichs von string-Typen verwenden.</para>
<code>
<label>Beispiel 22: Regulärer Ausdruck mittels pattern</label>
<codeline>&lt;xsd:simpleType name=&quot;SKU&quot;&gt; </codeline>
<codeline>	&lt;xsd:restriction base=&quot;xsd:string&quot;&gt; </codeline>
<codeline>		&lt;xsd:pattern value=&quot;\d{3}-[A-Z]{2}&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:restriction&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt; </codeline>
</code>
<para>Unter den genannten Facetten ist vor allem enumeration sehr nützlich. Es läßt sich auf alle Typen anwenden (außer boolean). Es beschränkt einen simplen Typen auf eine benannte Liste eindeutiger Werte.</para>
<code>
<label>Beispiel 23: US-Staaten als enumerated-Liste</label>
<codeline>&lt;xsd:simpleType name=&quot;USState&quot;&gt; </codeline>
<codeline>	&lt;xsd:restriction base=&quot;xsd:string&quot;&gt; </codeline>
<codeline>		&lt;xsd:enumeration value=&quot;AK&quot;/&gt; </codeline>
<codeline>		&lt;xsd:enumeration value=&quot;AL&quot;/&gt; </codeline>
<codeline>		&lt;xsd:enumeration value=&quot;AR&quot;/&gt; </codeline>
<codeline>		&lt;!-- u.s.w. --&gt; </codeline>
<codeline>	&lt;/xsd:restriction&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt;  </codeline>
</code>
<section>
<section-header>Aufzählungstypen (List Types)</section-header>
<para>Neben den in &quot;Tabelle 4: Simple Typen von XML Schema&quot; aufgeführten Typen, setzt XML-Schema das Konzept eines Aufzählungstypen um. Aus XML-Sicht müssen Werte in einer Aufzählung atomaren Typs sein, also nicht weiter teilbar. Werte werden, mittels Leerzeichen getrennt, aufgelistet. Vordefinierte, atomaren Typen sind NMTOKEN, IDREFS und ENTITIES. Es lassen sich allerdings auch eigene atomare Typen von anderen, simplen Typen ableiten.</para>
<code>
<label>Beispiel 24: Definition eines Integer-Aufzählungstypen</label>
<codeline>&lt;xsd:simpleType name=&quot;listOfMyIntType&quot;&gt; </codeline>
<codeline>	&lt;xsd:list itemType=&quot;myInteger&quot;/&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt;  </codeline>
</code>
<para>Ein Element diesen Typs im Instanzdokument könnte nun folgendermaßen aussehen:</para>
<code>
<label>Beispiel 25: Anwendung eines Aufzählungstypen</label>
<codeline>&lt;listOfMyInt&gt;20003 15037 95945&lt;/listOfMyInt&gt; </codeline>
</code>
<para>Die Liste kann mit folgenden Facetten eingeschränkt werden: length, minLength, maxLength und enumeration. Als Beispiel wird im Folgenden ein Typ definiert, der eine Liste von genau sechs US-Bundesstaaten enthalten muss.</para>
<code>
<label>Beispiel 26: Längenbeschränkter Aufzählungstyp</label>
<codeline>&lt;xsd:simpleType name=&quot;USStateList&quot;&gt; </codeline>
<codeline>	&lt;xsd:list itemType=&quot;USState&quot;/&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt; </codeline>
<codeline>&lt;xsd:simpleType name=&quot;SixUSStates&quot;&gt; </codeline>
<codeline>	&lt;xsd:restriction base=&quot;USStateList&quot;&gt; </codeline>
<codeline>		&lt;xsd:length value=&quot;6&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:restriction&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt;  </codeline>
</code>
<para>Elemente des Typs müssen im nun sechs Werte beinhalten, und jedes einzelne dieser Werte muss eines der (atomaren) Werte des enumerated Typen USState sein.</para>
<code>
<label>Beispiel 27: Anwendung des längenbeschränkten Aufzählungstyps</label>
<codeline>&lt;sixStates&gt;PA NY CA NY LA AK&lt;/sixStates&gt;  </codeline>
</code>
<para>Hinweis: Es ist möglich einen Aufzählungstypen von string abzuleiten. Allerdings können Zeichenketten auch Leerzeichen beinhalten, die ihrerseits als Trennzeichen Verwendung finden.</para>
</section>
<section><section-header>Vereinigungstypen (Union Types)</section-header>
<para>Im Gegensatz zu Aufzählungstypen, die den Typ der Aufzählungswerte festlegen, gestatten Vereinigungstypen die Auswahl des anzuwendenden Typen aus einer Reihe verschiedener Typen. Diese können sowohl atomare als auch Aufzählungstypen sein.</para>
<code>
<label>Beispiel 28: Vereinigungstypen für Zip-Codes</label>
<codeline>&lt;xsd:simpleType name=&quot;zipUnion&quot;&gt; </codeline>
<codeline>	&lt;xsd:union memberTypes=&quot;USState listOfMyIntType&quot;/&gt; </codeline>
<codeline>&lt;/xsd:simpleType&gt;  </codeline>
</code>
<para>Elemente diesen Typs können nun folgende Inhalte haben:</para>
<code>
<label>Beispiel 29: Anwendung eines Vereinigunstyps</label>
<codeline>&lt;zips&gt;CA&lt;/zips&gt; </codeline>
<codeline>&lt;zips&gt;95630 95977 95945&lt;/zips&gt; </codeline>
<codeline>&lt;zips&gt;AK&lt;/zips&gt;  </codeline>
</code>
<para>Also entweder einen Wert aus der Liste der Kürzel für US-Bundesstaaten oder aber eine Liste von Integerwerten.</para>
<para>Auf Vereinigungstypen lassen sich folgende Facetten anwenden: pattern und enumeration.</para>
</section>
</section>
<section><section-header>Anonyme Typ-Definitionen</section-header>
<para>Schemata können so aufgebaut sein, das zunächst Typen definiert werden, um diese anschliessend mittels dem type-Attribut der Element-Deklaration anzuwenden. In Anbetracht der Wiederverwendbarkeit solcher Typdefinitionen ist dies ein durchaus sinnvoller Ansatz. Allerdings wird das Schema sehr schnell unübersichtlich, wenn Typen auch dann explizit deklariert werden, aber nur einmalig verwendet werden. In solchen Fällen ist es ratsam, diese Typen innerhalb der Elementdeklaration als anonyme Typen zu definieren.</para>
<para>Die Definition von items enthält zwei Elementdeklarationen, die anonyme Typen verwenden (item und quantity). Allgemein lassen sich anonyme Typen am fehlenden name-Attribut, und dem Vorhandensein einer unbenannten (simplen oder komplexen) Typ-Definition, leicht ausmachen.</para>
<code>
<label>Beispiel 30: Anonyme Typ-Definitionen</label>
<codeline>&lt;xsd:complexType name=&quot;Items&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;item&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;&gt; </codeline>
<codeline>			&lt;xsd:complexType&gt; </codeline>
<codeline>				&lt;xsd:sequence&gt;  </codeline>
<codeline>					&lt;xsd:element name=&quot;productName&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;quantity&quot;&gt; </codeline>
<codeline>						&lt;xsd:simpleType&gt; </codeline>
<codeline>							&lt;xsd:restriction base=&quot;xsd:positiveInteger&quot;&gt; </codeline>
<codeline>								&lt;xsd:maxExclusive value=&quot;100&quot;/&gt; </codeline>
<codeline>							&lt;/xsd:restriction&gt; </codeline>
<codeline>						&lt;/xsd:simpleType&gt; </codeline>
<codeline>					&lt;/xsd:element&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;USPrice&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>					&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; </codeline>
<codeline>												minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>				&lt;/xsd:sequence&gt; </codeline>
<codeline>				&lt;xsd:attribute name=&quot;partNum&quot; type=&quot;SKU&quot;  </codeline>
<codeline>												use=&quot;required&quot;/&gt; </codeline>
<codeline>			&lt;/xsd:complexType&gt; </codeline>
<codeline>		&lt;/xsd:element&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt;  </codeline>
</code>
<para>Das item-Element enthält einen anonymen komplexen Typ bestehend aus productName, quantity, USPrice, comment und shipDate sowie einem Attribut namens partNum. Das quantity-Element enthält einen anonymen simplen Typ, der von integer abgeleitet wurde und dessen Wert zwischen 1 und 99 liegen kann.</para>
</section>
<section><section-header>Element-Inhalte</section-header>
<para>Bisher haben wir Elemente gesehen, die andere Elemente enthalten, die Attribute tragen und solche, die Inhalt eines simplen Typs hatten. Weiteres wird im Folgenden behandelt: Elemente mit Attributen aber Inhalt simplen Typs, Elemente mit Kindelementen gemischt mit Zeichendaten, leere Elemente.</para>
<section>
<section-header>Komplexe Typen simplen Typs</section-header>
<para>Die Fragestellung lautet hier: Wie deklariert man ein Element, das zwar Inhalte eines simplen Typs haben soll, jedoch auch über ein Attribut verfügen soll. Ein solches Element wäre etwa das im folgenden Beispiel.</para>
<code>
<label>Beispiel 31: Element simplen Typs mit Attribut</label>
<codeline>&lt;internationalPrice currency=&quot;EUR&quot;&gt;423.46&lt;/internationalPrice&gt; </codeline>
</code>
<para>Simple Typen können, wie erwähnt, nicht über Attribute verfügen. Daher muss ein komplexer Typ definiert werden, der eine Attributdeklaration aufnehmen kann. Aus diesem Grund muss in diesem Fall ein komplexer Typ vom simplen Typ abgeleitet werden.</para>
<code>
<label>Beispiel 32: Ein komplexer Typ abgeleitet von einem simplen Typ</label>
<codeline>&lt;xsd:element name=&quot;internationalPrice&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType&gt; </codeline>
<codeline>		&lt;xsd:simpleContent&gt; </codeline>
<codeline>			&lt;xsd:extension base=&quot;xsd:decimal&quot;&gt; </codeline>
<codeline>				&lt;xsd:attribute name=&quot;currency&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>			&lt;/xsd:extension&gt; </codeline>
<codeline>		&lt;/xsd:simpleContent&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt; </codeline>
</code>
<para>Zunächst wird ein complexType-Element für die Definition eines anonymen Typs verwendet. Um anzuzeigen, das der Inhalt des neuen Typs lediglich Zeichendaten enthalten darf, wird das simpleContent-Element eingesetzt. Schließlich wird vom simplen Typen decimal hergeleitet, welcher um das Attribut currency erweitert wird indem eine normale Attributdeklaration verwendet wird. Ein auf diese Art definierter Typ erfüllt die Anforderungen an ein Element, wie es in &quot;Beispiel 31: Element simplen Typs mit Attribut&quot; angewendet wird.</para>
</section>
<section><section-header>Gemischte Inhalte</section-header>
<para>Folgendes Beispiel illustriert die Verwendung von Kindelementen gemischt mit Zeichendaten.</para>
<code>
<label>Beispiel 33: Gemischte Inhalte eines Elements</label>
<codeline>&lt;letterBody&gt; </codeline>
<codeline>&lt;salutation&gt;Dear Mr.&lt;name&gt;Robert Smith&lt;/name&gt;.&lt;/salutation&gt; </codeline>
<codeline>Your order of &lt;quantity&gt;1&lt;/quantity&gt; &lt;productName&gt;Baby  </codeline>
<codeline>Monitor&lt;/productName&gt; shipped from our warehouse on  </codeline>
<codeline>&lt;shipDate&gt;1999-05-21&lt;/shipDate&gt;. &lt;!-- u.s.w. --&gt;  </codeline>
<codeline>&lt;/letterBody&gt; </codeline>
</code>
<para>Um diesen Auszug eines Instanzdokuments zu ermöglichen, müssen die verwendeten Elemente wie folgt deklariert werden.</para>
<code>
<label>Beispiel 34: Deklaration von Elementen mit gemischtem Inhalt</label>
<codeline>&lt;xsd:element name=&quot;letterBody&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType mixed=&quot;true&quot;&gt; </codeline>
<codeline>		&lt;xsd:sequence&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;salutation&quot;&gt; </codeline>
<codeline>				&lt;xsd:complexType mixed=&quot;true&quot;&gt; </codeline>
<codeline>					&lt;xsd:sequence&gt; </codeline>
<codeline>						&lt;xsd:element name=&quot;name&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>					&lt;/xsd:sequence&gt; </codeline>
<codeline>				&lt;/xsd:complexType&gt; </codeline>
<codeline>			&lt;/xsd:element&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;quantity&quot; type=&quot;xsd:positiveInteger&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;productName&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; </codeline>
<codeline>														minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>			&lt;!-- u.s.w. --&gt; </codeline>
<codeline>		&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt;  </codeline>
</code>
<para>Sämtliche Elemente werden wie gewohnt deklariert. Um nun Zeichendaten innerhalb eines Elements zu ermöglichen, wird das Attribut mixed in der Typdefinition auf &quot;true&quot; gesetzt.</para>
<para>Das mixed-Modell in XML-Schema unterscheidet sich grundlegend vom mixed-Modell in DTD. In XML-Schema müssen die Reihenfolge und die Anzahl der Kindelementen in einem Instanzdokument übereinstimmen mit der entsprechenden Spezifizierung. Im XML 1.0 DTD-Modell jedoch, kann die Reihenfolge und die Anzahl der Kindelemente nicht vorgegeben werden.</para>
</section>
<section><section-header>Leerer Inhalt</section-header>
<para>Angenommen, man möchte im internationalPrice Element sowohl die Währung als auch den Betrag als Attribut angeben, und das Element ansonsten leer belassen.</para>
<code>
<label>Beispiel 35: Ein leeres Element</label>
<codeline>&lt;internationalPrice currency=&quot;EUR&quot; value=&quot;423.46&quot;/&gt;  </codeline>
</code>
<para>Um dies zu erreichen, deklariert man ein Element, welches ausschließlich Kindelemente als Inhalt haben darf, ohne jedoch Kindelemente anzugeben.</para>
<code>
<label>Beispiel 36: Umständliche Definition eines leeren Elements</label>
<codeline>&lt;xsd:element name=&quot;internationalPrice&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType&gt; </codeline>
<codeline>		&lt;xsd:complexContent&gt; </codeline>
<codeline>			&lt;xsd:restriction base=&quot;xsd:anyType&quot;&gt; </codeline>
<codeline>				&lt;xsd:attribute name=&quot;currency&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>				&lt;xsd:attribute name=&quot;value&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>			&lt;/xsd:restriction&gt; </codeline>
<codeline>		&lt;/xsd:complexContent&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt;  </codeline>
</code>
<para>In diesem Beispiel wird ein anonymer Typ mit complexContent (also nur Elemente) definiert, Das complexContent-Element deutet an, dass das Inhaltsmodell anschliessend eingeschränkt oder erweitert werden soll und die Restriktion von anType deklariert zwei Attribute, führt allerdings keine Elemente ein.</para>
<para>Die hier gezeigte Deklaration ist allerdings ziemlich umständlich.</para>
<code>
<label>Beispiel 37: Kompakte Deklaration eines leeren Elements</label>
<codeline>&lt;xsd:element name=&quot;internationalPrice&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType&gt; </codeline>
<codeline>		&lt;xsd:attribute name=&quot;currency&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>		&lt;xsd:attribute name=&quot;value&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt; </codeline>
</code>
<para>Diese kürzere Schreibweise funktioniert ohne simpleContent und complexContent, da sie als Kurzschreibweise interpretiert wird für complexContent mit der Restriktion von anyType.</para>
</section>
<section><section-header>anyType</section-header>
<para>Der Typ anyType ist der Ur-Typ aller Daten- und Elementtypen. Sein Inhalt ist in keiner Weise beschränkt. Wenn kein Typ angegeben wird, wird anyType angenommen, so dass ein solches Element sowohl Zeichendaten als auch Elemente beliebigen Typs in beliebiger Häufigkeit als auch beides gemischt beinhalten kann.</para>
</section>
</section>
<section><section-header>Kommentare (annotations)</section-header>
<para>XML-Schema stellt drei Methoden für das Eintragen von Kommentaren zur Verfügung. Die erste Möglichkeit besteht im Element documentation und ist für Inhalte, die sich an Menschen richten, gedacht. Die Verwendung sollte in Kombination mit dem xml:lang Attribut im documentation- oder, für das ganze Schema, im schema-Element geschehen.</para>
<para>Eine andere Methode, die eher für die maschinelle Verarbeitung vorgesehen ist, ist die Verwendung von appInfo-Elementen.</para>
<para>Sowohl documentation- als auch appInfo-Elemente werden in annotation-Elemente geschachtelt, die häufig am Anfang von Schema-Konstruktionen, bspw. Element-Definitionen, eingefügt werden. Des Weiteren sind sie am Anfang von schema-, simpleType- und attribute-Elementen erlaubt.</para>
</section>
<section><section-header>Aufbau von Inhaltsmodellen</section-header>
<para>Die Definitionen komplexer Typen im purchaseOrder-Schema deklarieren jeweils eine Sequenz von Elementen, die in einem Instanzdokument erscheinen müssen. Das Auftreten kann als optional deklariert werden durch die Verwendung von minOccurs mit einer 0, aber auch anderweitig mittels minOccurs und maxOccurs gesteuert werden. XML-Schema stellt Werkzeuge bereit, die es ermöglichen, das Auftreten von Elementgruppen zu steuern. Diese können allerdings nicht auf Attribute angewendet werden.</para>
<para>XML-Schema ermöglicht das Definieren und Benennen von Elementgruppen, so dass die Elemente für den Aufbau von Inhaltsmodellen komplexer Typen verwendet werden können. Unbenannte Gruppen können ebenso definiert und zusammen mit den benannten Gruppen verwendet werden, und die Reihenfolge des Auftretens kann auf die Reihenfolge der Deklaration begrenzt werden. Alternativ kann das Auftreten der Elemente derart eingeschränkt werden, das lediglich eines der Elemente im Instanzdokument erscheinen darf.</para>
<para>Zur Verdeutlichung werden im PurchaseOrderType zwei Gruppen eingefügt, so dass purchaseOrder-Elemente anschliessend entweder getrennte Elemente für shipTo- und billTo-Adressen enthalten dürfen, oder, falls beide Orte die gleichen sein sollten, eine einzelne Adresse angegeben werden kann.</para>
<code>
<label>Beispiel 38: Nested-Choise- und Sequenz-Gruppen</label>
<codeline>&lt;xsd:complexType name=&quot;PurchaseOrderType&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:choice&gt; </codeline>
<codeline>			&lt;xsd:group ref=&quot;shipAndBill&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;singleUSAddress&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;/xsd:choice&gt; </codeline>
<codeline>		&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;items&quot; type=&quot;Items&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;orderDate&quot; type=&quot;xsd:date&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;xsd:group name=&quot;shipAndBill&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;shipTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;billTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>&lt;/xsd:group&gt;  </codeline>
</code>
<para>Die choise-Gruppe erlaubt das Auftreten eines der Kindelementen im Instanzdokument. Eines seiner Kindelementen ist ein group-Element, welches die benannte Gruppe shipAndBill referenziert, das seinerseits aus den Elementen shipTo und billTo besteht. Das zweite Kind ist das Element singleUSAddress.</para>
<para>Demnach muss ein purchaseOrder-Element im Instanzdokument entweder ein shipTo-Element gefolgt von einem billTo-Element als Kinder besitzen, oder aber ein einzelnes singleUSAddress-Element. Nach der choise-Gruppe werden die Elemente comment und items deklariert, und diese - zusammen mit der choise-Gruppe - sind in einem sequence-Element geschachtelt. Heraus folgt, das nach dem Adress-Element, bzw. den Adress-Elementen, jeweils ein comment- und ein items-Element folgen müssen, und zwar in dieser Reihenfolge.</para>
<para>Neben dieser Methode gibt es noch eine weitere, die das Erscheinen von Elementen in einer Gruppe steuert. Die all-Gruppe ermöglicht es, das die Elementen jeweils optional einmalig in beliebiger Reihenfolge auftreten dürfen. Das all-Element darf nur als Top-Level-Element eines Content-Modells verwendet werden und die Kindelemente ihrerseits dürfen keine Gruppen sein und auch nur einmalig vertreten sein. Mit anderen Worten: Die erlaubten Werte der minOccurs- und maxOccurs-Attribute der Kinder lauten 0 und 1.</para>
<para>Folgendes Beispiel zeigt die Definition von purchaseOrder, so dass die Kinder in beliebiger Reihenfolge auftreten dürfen.</para>
<code>
<label>Beispiel 39: Verwendung einer all-Gruppe</label>
<codeline>&lt;xsd:complexType name=&quot;PurchaseOrderType&quot;&gt; </codeline>
<codeline>	&lt;xsd:all&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;shipTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;billTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;xsd:element name=&quot;items&quot; type=&quot;Items&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:all&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;orderDate&quot; type=&quot;xsd:date&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt;  </codeline>
</code>
<para>Das comment-Element im Beispiel kann demnach optional im Instanzdokument erscheinen, und seine Position könnte vor oder hinter shipTo, billTo und items sein. Das gleiche gilt für die anderen Elemente ebenso.</para>
<para>Nicht erlaubt ist jedoch die Deklaration weiterer Elemente außerhalb der all-Gruppe, um so bspw. ein weiteres comment-Element zu ermöglichen. Das all-Element muss alleiniges Top-Level-Element sein. Folgendes ist also illegal.</para>
<code>
<label>Beispiel 40: Illegale Verwendung einer all-Gruppe</label>
<codeline>&lt;xsd:complexType name=&quot;PurchaseOrderType&quot;&gt; </codeline>
<codeline>	&lt;xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:all&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;shipTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;billTo&quot; type=&quot;USAddress&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;items&quot; type=&quot;Items&quot;/&gt; </codeline>
<codeline>		&lt;/xsd:all&gt; </codeline>
<codeline>		&lt;xsd:sequence&gt; </codeline>
<codeline>			&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot; </codeline>
<codeline>									maxOccurs=&quot;unbounded&quot;/&gt; </codeline>
<codeline>		&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;/xsd:sequence&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;orderDate&quot; type=&quot;xsd:date&quot;/&gt; </codeline>
<codeline>&lt;/xsd:complexType&gt;  </codeline>
</code>
<para>Schlußendlich ist die Verwendung von minOccurs- und maxOccurs-Attributen im Inhaltsmodell (dargestellt mit den Elementen group, choise und all) erlaubt. Durch Kombination und Verschachtelung dieser Elemente und die Auszeichnung mittels dieser Attribute können alle Inhaltsmodelle, die mittels XML 1.0 DTD ausgedrückt werden konnten, umgesetzt werden. Die all-Gruppe erlaubt darüber hinaus noch weitere Möglichkeiten.</para>
</section>
<section><section-header>Attribut-Gruppen</section-header>
<para>Angenommen, es wird erforderlich, weitere Informationen zu den Gegenständen im purchase order zur Verfügung zu stellen. Beispielsweise das Gewicht und der bevorzugten Zustellmethode. Dies kann erreicht werden über die Deklaration der Attribute weichtKg und shipBy in der (anonymen) Typ-Definition des item-Elements.</para>
<code>
<label>Beispiel 41: Zusätzliche Attribute in einer inline-Typ-Definition</label>
<codeline>&lt;xsd:element name=&quot;Item&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType&gt; </codeline>
<codeline>		&lt;xsd:sequence&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;productName&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;quantity&quot;&gt; </codeline>
<codeline>				&lt;xsd:simpleType&gt; </codeline>
<codeline>					&lt;xsd:restriction base=&quot;xsd:positiveInteger&quot;&gt; </codeline>
<codeline>						&lt;xsd:maxExclusive value=&quot;100&quot;/&gt; </codeline>
<codeline>					&lt;/xsd:restriction&gt; </codeline>
<codeline>				&lt;/xsd:simpleType&gt; </codeline>
<codeline>			&lt;/xsd:element&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;USPrice&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; </codeline>
<codeline>													minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;/xsd:sequence&gt; </codeline>
<codeline>		&lt;xsd:attribute name=&quot;partNum&quot; type=&quot;SKU&quot; use=&quot;required&quot;/&gt; </codeline>
<codeline>		&lt;!-- add weightKg and shipBy attributes --&gt; </codeline>
<codeline>		&lt;xsd:attribute name=&quot;weightKg&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>		&lt;xsd:attribute name=&quot;shipBy&quot;&gt; </codeline>
<codeline>			&lt;xsd:simpleType&gt; </codeline>
<codeline>				&lt;xsd:restriction base=&quot;xsd:string&quot;&gt; </codeline>
<codeline>					&lt;xsd:enumeration value=&quot;air&quot;/&gt; </codeline>
<codeline>					&lt;xsd:enumeration value=&quot;land&quot;/&gt; </codeline>
<codeline>					&lt;xsd:enumeration value=&quot;any&quot;/&gt; </codeline>
<codeline>				&lt;/xsd:restriction&gt; </codeline>
<codeline>			&lt;/xsd:simpleType&gt; </codeline>
<codeline>		&lt;/xsd:attribute&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt;  </codeline>
</code>
<para>Alternativ lassen sich die Attribute als benannte Gruppe an anderer Stelle definiert, und in der item-Deklaration referenziert werden.</para>
<code>
<label>Beispiel 42: Attribute mittels einer attribute-Gruppe</label>
<codeline>&lt;xsd:element name=&quot;item&quot; minOccurs=&quot;0&quot; maxOccurs=&quot;unbounded&quot;&gt; </codeline>
<codeline>	&lt;xsd:complexType&gt; </codeline>
<codeline>		&lt;xsd:sequence&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;productName&quot; type=&quot;xsd:string&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;quantity&quot;&gt; </codeline>
<codeline>				&lt;xsd:simpleType&gt; </codeline>
<codeline>					&lt;xsd:restriction base=&quot;xsd:positiveInteger&quot;&gt; </codeline>
<codeline>					&lt;xsd:maxExclusive value=&quot;100&quot;/&gt; </codeline>
<codeline>					&lt;/xsd:restriction&gt; </codeline>
<codeline>				&lt;/xsd:simpleType&gt; </codeline>
<codeline>			&lt;/xsd:element&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;USPrice&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element ref=&quot;comment&quot; minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>			&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; </codeline>
<codeline>													minOccurs=&quot;0&quot;/&gt; </codeline>
<codeline>		&lt;/xsd:sequence&gt; </codeline>
<codeline>		&lt;!-- attributeGroup replaces individual declarations --&gt; </codeline>
<codeline>		&lt;xsd:attributeGroup ref=&quot;ItemDelivery&quot;/&gt; </codeline>
<codeline>	&lt;/xsd:complexType&gt; </codeline>
<codeline>&lt;/xsd:element&gt; </codeline>
<codeline>&lt;xsd:attributeGroup name=&quot;ItemDelivery&quot;&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;partNum&quot; type=&quot;SKU&quot; use=&quot;required&quot;/&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;weightKg&quot; type=&quot;xsd:decimal&quot;/&gt; </codeline>
<codeline>	&lt;xsd:attribute name=&quot;shipBy&quot;&gt; </codeline>
<codeline>		&lt;xsd:simpleType&gt; </codeline>
<codeline>			&lt;xsd:restriction base=&quot;xsd:string&quot;&gt; </codeline>
<codeline>				&lt;xsd:enumeration value=&quot;air&quot;/&gt; </codeline>
<codeline>				&lt;xsd:enumeration value=&quot;land&quot;/&gt; </codeline>
<codeline>				&lt;xsd:enumeration value=&quot;any&quot;/&gt; </codeline>
<codeline>			&lt;/xsd:restriction&gt; </codeline>
<codeline>		&lt;/xsd:simpleType&gt; </codeline>
<codeline>	&lt;/xsd:attribute&gt; </codeline>
<codeline>&lt;/xsd:attributeGroup&gt;  </codeline>
</code>
<para>Das Auslagern ganzer Attributgruppen stellt eine elegante Methode dar, die Lesbarkeit von Schemata zu verbessern und gleichzeitig die Wartung zu erleichtern, da solche Gruppen einmalig definiert beliebig oft verwendet werden können. Eine Attributgruppe kann im Übrigen andere Attributgruppen enthalten. Sowohl die Attributdeklaration als auch die Attributgruppenreferenz müssen am Ende der Definition eines komplexen Typen eingefügt werden.</para>
</section>
<section><section-header>NIL-Werte</section-header>
<para>Eines der im purchase order aufgeführten item-Elemente, der Rasenmäher, besitzt kein shipDate-Element. In unserem Szenario könnte dies vom Schema-Author ein berücksichtigter Zustand sein, der zum Ausdruck bringen soll, das der entsprechende Gegenstand noch nicht versendet wurde. Im Allgemeinen bedeutet das fehlen eines Elements nichts spezifisches. Es könnte bedeuten, das die Information nicht verfügbar oder nicht anwendbar ist. Es kann allerdings auch andere Ursachen haben.</para>
<para>Manchmal ist es erforderlich, oder wünschenswert, explizit zum Ausdruck zu bringen, das die Information nicht verfügbar ist, bspw. wenn Werte aus einer relationalen Datenbank weiterverarbeitet werden, bei denen zwar das Feld vorhanden, der Wert selbst aber nicht gesetzt ist. Solche Fälle können mit dem Schema-NIL-Wert dargestellt werden.</para>
<para>Der NIL-Mechanismus wird über ein Out-Of-The-Band-Signal dargestellt. D.h., es besteht kein NIL-Wert als Inhalt eines Elements, vielmehr wird der Zustand über ein Attribut vermittelt.</para>
<code>
<label>Beispiel 43: Erweiterung der shipData-Deklaration um NIL-Werte</label>
<codeline>&lt;xsd:element name=&quot;shipDate&quot; type=&quot;xsd:date&quot; nillable=&quot;true&quot;/&gt;  </codeline>
</code>
<para>Um im Instanzdokument explizit anzugeben, das der Wert für shipDate NIL ist, wird das Attribut (aus dem XML-Schema-Namespace for instances) auf true gesetzt.</para>
<code>
<label>Beispiel 44: Anwendung des NIL-Wert-Attributs</label>
<codeline>&lt;shipDate xsi:nil=&quot;true&quot;&gt;&lt;/shipDate&gt;  </codeline>
</code>
<para>Das nil-Attribut ist als Teil des XML-Schema Namensraum für Instanzdokumente definiert (http://www.w3.org/2001/XMLSchema-instance)  und als solches muss es im Instanzdokument über einen Präfix (wie xsi: per Konvention) mit diesem assoziiert werden. NIL-Werte können nur auf Elementinhalte angewendet werden, nicht auf Attributwerte. Ein Element mit einem nil-Attribut, welches auf &quot;true&quot; steht, darf keinerlei Inhalte haben, seine Attribute können jedoch weiterhin verwendet werden.</para>
</section>
</section>
<section><section-header>XSL-Transformationen</section-header>
<para>Zum Erstellen von Stylesheets für XML-Daten wurde die XSL (eXtensible Stylesheet Language) entwickelt. Eine XSL-Datei beschreibt, ähnlich wie CSS, wie die Inhalte eines XML-Dokuments dargestellt werden sollen. Das Stylesheet ist ein XML-Dokument mit Elementen, die in einem eigenen Namensraum definiert sind (fo:). XSL ist kompatibel zu CSS, auch wenn die Syntax eine völlig andere ist.</para>
<para>Diese Art der Formattierung wird als XSL-FO (Formatting Objects) bezeichnet und es soll an dieser Stelle zunächst nicht weiter darauf eingegangen werden.</para>
<para>Als ein Teil der XSL wurde XSLT entwickelt; sie ermöglichen die Transformation von XML-Daten in andere Strukturen (unter anderem eben in eine XSL-FO-Struktur). Aber XSLT werden auch häufig dazu verwendet, aus einer XML-Quelle andere, XML-Konforme Ausgabeformate wie HTML zu generieren. Sie eignen sich aber auch für andere Zielformate.</para>
<section>
<section-header>Anwendung von XSLT</section-header>
<para>Für die Anwendung von XSLT wird ein Quell-XML-Dokument vorausgesetzt, auf welches eine XSL-Transformationsvorschrift (Stylesheet) angewendet werden soll.</para>
<para>Als Ausgabedokument wäre ein XML-Dokument mit XSL-FO-Elementen möglich. Aber die Transformation kann auch in XML-Dokumente münden, die die Inhalte des Ursprungsdokuments in abgewandelter Form enthalten. Folgende Beispiele sollen die Anwendung von XSLT veranschaulichen. Die einzelnen Quelltexte wurde der besseren Überschaubarkeit wegen leicht modifiziert bzgl. Einrückung und Zeilenümbrüche.</para>
<code>
<label>Beispiel 45: Dieses Skript in einer XML-Repräsentation</label>
<codeline>&lt;?xml version=&apos;1.0&apos; encoding=&apos;UTF-8&apos; standalone=&apos;no&apos; ?&gt; </codeline>
<codeline>&lt;!DOCTYPE mydoc SYSTEM scriptum.dtd&apos;&gt; </codeline>
<codeline>&lt;mydoc&gt; </codeline>
<codeline>&lt;docinfo&gt; </codeline>
<codeline>&lt;info&gt;Fachhochschule Giessen&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Vorlesung im Sommersemester 2003&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Programmierung von Multimediasystemen&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Dynamische Webseiten mit XML, PHP und XSLT&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Scriptum zur Vorlesung&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Working Draft. Status: 10.06.2003&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;C. van der Kruijs&lt;/info&gt; </codeline>
<codeline>&lt;info&gt;Hinweise, Anmerkungen und Fehler bitte an: 	 </codeline>
<codeline>skriptum@vanderkruijs.net&lt;/info&gt; </codeline>
<codeline>&lt;/docinfo&gt; </codeline>
<codeline>&lt;section&gt; </codeline>
<codeline>&lt;section-header&gt;Teil: XML&lt;/section-header&gt; </codeline>
<codeline>&lt;section&gt; </codeline>
<codeline>&lt;section-header&gt;Einführung und Überblick&lt;/section-header&gt; </codeline>
<codeline>&lt;section&gt; </codeline>
<codeline>&lt;section-header&gt;Abgrenzung des Begriffs XML&lt;/section-header&gt; </codeline>
<codeline>&lt;para&gt; </codeline>
<codeline>	XML ist die Abkürzung für eXtensible Markup Language, also für  </codeline>
<codeline>	erweiterbare Auszeichnungssprache. Um vorneweg den Begriff 	etwas  </codeline>
<codeline>	ein zu schränken: XML ist nicht - wie oft 	fälschlicherweise  </codeline>
<codeline>	angenommen - der Nachfolger von HTML, auch 	wenn Ähnlichkeiten  </codeline>
<codeline>	nicht von der Hand zu weisen sind, sondern: </codeline>
<codeline>&lt;/para&gt; </codeline>
<codeline>&lt;ul&gt; </codeline>
<codeline>	&lt;para&gt;&lt;li&gt;eine Dokumenten-Beschreibungssprache&lt;/li&gt;&lt;/para&gt; </codeline>
<codeline>	&lt;para&gt;&lt;li&gt;eine Vereinfachung bzw. ein Anwendungsprofil von SGML  </codeline>
<codeline>	 	 (Standard Generalized Markup Language) - genau wie es HTML </codeline>
<codeline>		auch ist, allerdings ohne dessen einschränkende Festlegung  </codeline>
<codeline>		auf Dokumentformatierung&lt;/li&gt;&lt;/para&gt; </codeline>
<codeline>	&lt;para&gt;&lt;li&gt;eine Beschreibungsvorschrift für eine  </codeline>
<codeline>		Metasprache&lt;/li&gt;&lt;/para&gt; </codeline>
<codeline>	&lt;para&gt;&lt;li&gt;offen für jegliche semantische  </codeline>
<codeline>		Interpretation&lt;/li&gt;&lt;/para&gt; </codeline>
<codeline>	&lt;para&gt;&lt;li&gt;objektorientiert einsetzbar&lt;/li&gt;&lt;/para&gt; </codeline>
<codeline>&lt;/ul&gt; </codeline>
<codeline>&lt;para&gt; </codeline>
<codeline>	Dies bedeutet: XML beschreibt einerseits eine Klasse von  </codeline>
<codeline>	Datenobjekten (=XML-Dokumente), andererseits aber auch  </codeline>
<codeline>	 (teilweise) das Verhalten von Computerprogrammen, die solche  </codeline>
<codeline>	Dokumente Verarbeiten. </codeline>
<codeline>&lt;/para&gt; </codeline>
<codeline>&lt;/section&gt; </codeline>
<codeline>&lt;!-- ... --&gt; </codeline>
<codeline>&lt;/section&gt; </codeline>
<codeline>&lt;section&gt;&lt;section-header&gt;Strukturelle Grundlagen&lt;/section-header&gt; </codeline>
<codeline>&lt;section&gt; </codeline>
<codeline>&lt;section-header&gt;Ein erstes Beispiel&lt;/section-header&gt; </codeline>
<codeline>&lt;code&gt; </codeline>
<codeline>	&lt;label&gt;Beispiel 1&lt;/label&gt; </codeline>
<codeline>	&lt;codeline&gt; </codeline>
<codeline>		&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;  </codeline>
<codeline>		standalone=&amp;quot;yes&amp;quot;?&amp;gt; </codeline>
<codeline>	&lt;/codeline&gt; </codeline>
<codeline>	&lt;codeline&gt; </codeline>
<codeline>		&amp;lt;Institut Typ=&amp;apos;Fachhochschule&amp;apos;&amp;gt; </codeline>
<codeline>	&lt;/codeline&gt; </codeline>
<codeline>	&lt;codeline&gt;	&amp;lt;Ort&amp;gt;Giessen&amp;lt;/Ort&amp;gt; &lt;/codeline&gt; </codeline>
<codeline>	&lt;codeline&gt;	 </codeline>
<codeline>		&amp;lt;Logo src=&amp;quot;fh-giessen.jpg&amp;quot; /&amp;gt; </codeline>
<codeline>	&lt;/codeline&gt; </codeline>
<codeline>	&lt;codeline&gt;&amp;lt;/Institut&amp;gt; &lt;/codeline&gt; </codeline>
<codeline>&lt;/code&gt; </codeline>
<codeline>&lt;para&gt; </codeline>
<codeline>	Zeile 1 Prolog mit XML-Deklaration (Document Information  </codeline>
<codeline>	Item), </codeline>
<codeline>&lt;/para&gt; </codeline>
<codeline>&lt;para&gt; </codeline>
<codeline>	Zeile 2 Öffnende Markierung Institut: Document Element, enthält  </codeline>
<codeline>	alle weiteren Elemente des Dokuments, bildet den Rumpf </codeline>
<codeline>&lt;/para&gt; </codeline>
<codeline>&lt;para&gt;Zeile 3 Element Ort mit Inhalt &amp;quot;Giessen&quot;&lt;/para&gt; </codeline>
<codeline>&lt;para&gt;Zeile 4 Leeres Element Logo mit Attribut src&lt;/para&gt; </codeline>
<codeline>&lt;para&gt;Zeile 5 Schließende Markierung Institut&lt;/para&gt; </codeline>
<codeline>&lt;/section&gt; </codeline>
<codeline>&lt;!-- ... --&gt; </codeline>
<codeline>&lt;/section&gt; </codeline>
<codeline>&lt;/section&gt; </codeline>
<codeline>&lt;/mydoc&gt; </codeline>
</code>
<para>Wendet man ein auf dieses XML-Dokument ausgerichtetes XSLT-Stylesheet an, so kann der Inhalt beispielsweise als XHTML ausgegeben werden (wie im folgenden Beispiel) oder aber in beliebige andere (Text-) Formate. Denkbar wäre beispielsweise auch TeX, oder eben XSL-FO.</para>
<code>
<label>Beispiel 46: Ausgabe nach Transformation</label>
<codeline>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;&gt; </codeline>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt; </codeline>
<codeline>&lt;META http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt; </codeline>
<codeline>&lt;title&gt;&lt;/title&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;Fachhochschule Giessen&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;Vorlesung im Sommersemester 2003&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;Programmierung von Multimediasystemen&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot;  </codeline>
<codeline>		content=&quot;Dynamische Webseiten mit XML, PHP und XSLT&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;Scriptum zur Vorlesung&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;Working Draft. Status: 10.06.2003&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot; content=&quot;C. van der Kruijs&quot;&gt; </codeline>
<codeline>&lt;meta name=&quot;info&quot;  </codeline>
<codeline>		content=&quot;Hinweise, Anmerkungen und Fehler bitte an:  </codeline>
<codeline>			skriptum@vanderkruijs.net&quot;&gt; </codeline>
<codeline>&lt;link rel=&quot;stylesheet&quot; href=&quot;scriptum.css&quot; type=&quot;text/css&quot;&gt; </codeline>
<codeline>&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>&lt;div class=&quot;docpart&quot;&gt; </codeline>
<codeline>&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>&lt;a name=&quot;1&quot;&gt;&lt;h1&gt;1. Teil: XML&lt;/h1&gt;&lt;/a&gt; </codeline>
<codeline>&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>&lt;a name=&quot;1.1&quot;&gt;&lt;h2&gt;1.1. Einführung und Überblick&lt;/h2&gt;&lt;/a&gt; </codeline>
<codeline>&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>&lt;a name=&quot;1.1.1&quot;&gt;&lt;h3&gt;1.1.1. Abgrenzung des Begriffs XML&lt;/h3&gt;&lt;/a&gt; </codeline>
<codeline>&lt;p&gt; </codeline>
<codeline>	XML ist die Abkürzung für eXtensible Markup Language, also für  </codeline>
<codeline>	erweiterbare Auszeichnungssprache. Um vorneweg den Begriff 	etwas  </codeline>
<codeline>	ein zu schränken: XML ist nicht - wie oft 	fälschlicherweise  </codeline>
<codeline>	angenommen - der Nachfolger von HTML, auch 	wenn Ähnlichkeiten  </codeline>
<codeline>	nicht von der Hand zu weisen sind, sondern: </codeline>
<codeline>&lt;/p&gt; </codeline>
<codeline>&lt;ul&gt; </codeline>
<codeline>&lt;li&gt;&lt;p&gt;eine Dokumenten-Beschreibungssprache&lt;/p&gt;&lt;/li&gt; </codeline>
<codeline>&lt;li&gt;&lt;p&gt;eine Vereinfachung bzw. ein Anwendungsprofil von SGML  </codeline>
<codeline>	 	 (Standard Generalized Markup Language) - genau wie es HTML  </codeline>
<codeline>		auch ist, allerdings ohne dessen einschränkende Festlegung  </codeline>
<codeline>		auf Dokumentformatierung&lt;/p&gt;&lt;/li&gt; </codeline>
<codeline>&lt;li&gt;&lt;p&gt;eine Beschreibungsvorschrift für eine Metasprache&lt;/p&gt;&lt;/li&gt; </codeline>
<codeline>&lt;li&gt;&lt;p&gt;offen für jegliche semantische Interpretation&lt;/p&gt;&lt;/li&gt; </codeline>
<codeline>&lt;li&gt;&lt;p&gt;objektorientiert einsetzbar&lt;/p&gt;&lt;/li&gt; </codeline>
<codeline>&lt;/ul&gt; </codeline>
<codeline>&lt;p&gt; </codeline>
<codeline>	Dies bedeutet: XML beschreibt einerseits eine Klasse von  </codeline>
<codeline>	Datenobjekten (=XML-Dokumente), andererseits aber auch  </codeline>
<codeline>	 (teilweise) das Verhalten von Computerprogrammen, die solche  </codeline>
<codeline>	Dokumente Verarbeiten. </codeline>
<codeline>&lt;/p&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>&lt;a name=&quot;1.2&quot;&gt;&lt;h2&gt;1.2. Strukturelle Grundlagen&lt;/h2&gt;&lt;/a&gt; </codeline>
<codeline>&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>&lt;a name=&quot;1.2.1&quot;&gt;&lt;h3&gt;1.2.1. Ein erstes Beispiel&lt;/h3&gt;&lt;/a&gt; </codeline>
<codeline>&lt;div class=&quot;code&quot;&gt; </codeline>
<codeline>&lt;div class=&quot;label&quot;&gt; </codeline>
<codeline>Beispiel 1&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>&lt;pre&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;  </codeline>
<codeline>		standalone=&quot;yes&quot;?&amp;gt;&lt;/pre&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>&lt;pre&gt;		&amp;lt;Institut Typ=&apos;Fachhochschule&apos;&amp;gt;&lt;/pre&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>&lt;pre&gt;	&amp;lt;Ort&amp;gt;Giessen&amp;lt;/Ort&amp;gt; &lt;/pre&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>&lt;pre&gt;			&amp;lt;Logo src=&quot;fh-giessen.jpg&quot; /&amp;gt;	&lt;/pre&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>&lt;pre&gt;&amp;lt;/Institut&amp;gt; &lt;/pre&gt;&lt;/div&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;p&gt; </codeline>
<codeline>	Zeile 1 Prolog mit XML-Deklaration (Document Information  </codeline>
<codeline>	Item), </codeline>
<codeline>&lt;/p&gt; </codeline>
<codeline>&lt;p&gt; </codeline>
<codeline>	Zeile 2 Öffnende Markierung Institut: Document Element, enthält  </codeline>
<codeline>	alle weiteren Elemente des Dokuments, bildet den Rumpf </codeline>
<codeline>&lt;/p&gt; </codeline>
<codeline>&lt;p&gt;Zeile 3 Element Ort mit Inhalt &quot;Giessen&quot;&lt;/p&gt; </codeline>
<codeline>&lt;p&gt;Zeile 4 Leeres Element Logo mit Attribut src&lt;/p&gt; </codeline>
<codeline>&lt;p&gt;Zeile 5 Schließende Markierung Institut&lt;/p&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;/div&gt; </codeline>
<codeline>&lt;/div&gt;&lt;/div&gt;&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<para>Um diese Ausgabe zu erreichen, wurde folgendes Stylesheet verwendet:</para>
<code>
<label>Beispiel 47: XSLT-Stylesheet</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;xsl:stylesheet version=&quot;2.0&quot;  </codeline>
<codeline>			xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; </codeline>
<codeline>&lt;xsl:output method=&quot;html&quot; encoding=&quot;UTF-8&quot; indent=&quot;no&quot;/&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;mydoc&quot;&gt; </codeline>
<codeline>	&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0 Transitional//EN&quot;&gt; </codeline>
<codeline>	&lt;html&gt; </codeline>
<codeline>	&lt;head&gt; </codeline>
<codeline>	&lt;xsl:apply-templates select=&quot;docinfo&quot;/&gt; </codeline>
<codeline>	&lt;link rel=&quot;stylesheet&quot; href=&quot;scriptum.css&quot; type=&quot;text/css&quot;/&gt; </codeline>
<codeline>	&lt;/head&gt; </codeline>
<codeline>	&lt;body&gt; </codeline>
<codeline>	&lt;div class=&quot;docpart&quot;&gt; </codeline>
<codeline>		&lt;xsl:apply-templates select=&quot;section&quot;/&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>	&lt;/body&gt; </codeline>
<codeline>	&lt;/html&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;docinfo&quot;&gt; </codeline>
<codeline>	&lt;title&gt;&lt;xsl:copy-of select = &quot;doctitle&quot; /&gt;&lt;/title&gt; </codeline>
<codeline>	&lt;xsl:for-each select=&quot;info&quot;&gt; </codeline>
<codeline>	&lt;meta name=&quot;{name()}&quot;&gt; </codeline>
<codeline>		&lt;xsl:attribute name=&quot;content&quot;&gt; </codeline>
<codeline>			&lt;xsl:value-of select=&quot;.&quot; /&gt; </codeline>
<codeline>		&lt;/xsl:attribute&gt; </codeline>
<codeline>	&lt;/meta&gt; </codeline>
<codeline>	&lt;/xsl:for-each&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;section&quot;&gt; </codeline>
<codeline>	&lt;div class=&quot;section&quot;&gt; </codeline>
<codeline>	&lt;xsl:apply-templates select=&quot;*&quot;/&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;section-header&quot;&gt; </codeline>
<codeline>	&lt;a&gt; </codeline>
<codeline>	&lt;xsl:attribute name=&quot;name&quot;&gt; </codeline>
<codeline>		&lt;xsl:number count=&quot;section&quot; level=&quot;multiple&quot;&gt;&lt;/xsl:number&gt; </codeline>
<codeline>	&lt;/xsl:attribute&gt; </codeline>
<codeline>	&lt;xsl:text disable-output-escaping = &quot;yes&quot;&gt; </codeline>
<codeline>		&lt;![CDATA[&lt;h]]&gt; </codeline>
<codeline>	&lt;/xsl:text&gt; </codeline>
<codeline>	&lt;xsl:value-of select=&quot;count(ancestor::*)-1&quot; /&gt; </codeline>
<codeline>	&lt;xsl:text disable-output-escaping = &quot;yes&quot;&gt; </codeline>
<codeline>		&lt;![CDATA[&gt;]]&gt; </codeline>
<codeline>	&lt;/xsl:text&gt; </codeline>
<codeline>	&lt;xsl:number count=&quot;section&quot;  </codeline>
<codeline>						level=&quot;multiple&quot; format=&quot;1.1.1.1.a. &quot;/&gt; </codeline>
<codeline>	&lt;xsl:value-of select=&quot;.&quot;/&gt; </codeline>
<codeline>	&lt;xsl:text disable-output-escaping = &quot;yes&quot;&gt; </codeline>
<codeline>		&lt;![CDATA[&lt;/h]]&gt; </codeline>
<codeline>	&lt;/xsl:text&gt; </codeline>
<codeline>	&lt;xsl:value-of select=&quot;count(ancestor::*)-1&quot; /&gt; </codeline>
<codeline>	&lt;xsl:text disable-output-escaping = &quot;yes&quot;&gt; </codeline>
<codeline>		&lt;![CDATA[&gt;]]&gt; </codeline>
<codeline>	&lt;/xsl:text&gt; </codeline>
<codeline>	&lt;/a&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;code&quot;&gt; </codeline>
<codeline>	&lt;div class=&quot;code&quot;&gt; </codeline>
<codeline>	&lt;xsl:apply-templates select=&quot;label&quot; /&gt; </codeline>
<codeline>	&lt;xsl:for-each select=&quot;codeline&quot;&gt; </codeline>
<codeline>	&lt;div class=&quot;codeline&quot;&gt; </codeline>
<codeline>		&lt;pre&gt; </codeline>
<codeline>			&lt;xsl:value-of select=&quot;.&quot; disable-output-escaping=&quot;no&quot;/&gt; </codeline>
<codeline>		&lt;/pre&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>	&lt;/xsl:for-each&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;label&quot;&gt; </codeline>
<codeline>	&lt;div class=&quot;label&quot;&gt; </codeline>
<codeline>		&lt;xsl:value-of select=&quot;.&quot; /&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;ul&quot;&gt; </codeline>
<codeline>	&lt;ul&gt; </codeline>
<codeline>	&lt;xsl:for-each select=&quot;*&quot;&gt; </codeline>
<codeline>		&lt;li&gt;&lt;xsl:apply-templates select=&quot;.&quot;/&gt;&lt;/li&gt; </codeline>
<codeline>	&lt;/xsl:for-each&gt; </codeline>
<codeline>	&lt;/ul&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;para&quot;&gt; </codeline>
<codeline>	&lt;p&gt;&lt;xsl:value-of select=&quot;.&quot;/&gt;&lt;/p&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;/xsl:stylesheet&gt; </codeline>
</code>
<para>Die Syntax und die einzelnen im Stylesheet verwendeten Elemente werden in den nachfolgenden Abschnitten eläutert.</para>
</section>
<section><section-header>Aufbau eines Stylesheets</section-header>
<para>Ein XSLT-Stylesheet muß die Anforderungen an ein gültiges XML-Dokument erfüllen. Dementsprechend fängt ein solches Dokument mit einer XML-Deklaration an und enthält ein einzelnes Root-Element.</para>
<code>
<label>Beispiel 48: Minimales XSL-Dokument</label>
<codeline>&lt;?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?&gt; </codeline>
<codeline>&lt;xsl:stylesheet version=&quot;2.0&quot; </codeline>
<codeline>	xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&gt; </codeline>
<codeline>&lt;xsl:output method=&quot;html&quot;/&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;/&quot;&gt; </codeline>
<codeline>	&lt;xsl:value-of select=&quot;*&quot;/&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;/xsl:stylesheet&gt; </codeline>
</code>
<para>Im Beispiel wird gezeigt, dass das Root-Element stylesheet heissen muss. Es wird der Namensraum xls verwendet, der mit einer URL auf die w3.org-Seiten im Internet definiert wird.</para>
<para>Neben dieser Standalone-Lösung des Stylesheets ist es auch möglich, ein xsl:stylesheet-Element in einem normalen XML-Dokument (an beliebiger Stelle) abzulegen. Dieses Art des Stylesheets wird als embedded stylesheet module bezeichnet.</para>
<para>Eine weitere Form eines Stylesheets ist das sogenannte simplified stylesheet module. Dieses kann verwendet werden, wenn lediglich ein einziges Template definiert werden soll. In diesem Fall fallen das Templateelement und das xsl:stylesheet-Element zusammen.</para>
<code>
<label>Beispiel 49: simplified stylesheet module</label>
<codeline>&lt;html xsl:version=&quot;2.0&quot; </codeline>
<codeline>	xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot; </codeline>
<codeline>	xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt; </codeline>
<codeline>	&lt;head&gt; </codeline>
<codeline>		&lt;title&gt;Expense Report Summary&lt;/title&gt; </codeline>
<codeline>	&lt;/head&gt; </codeline>
<codeline>	&lt;body&gt; </codeline>
<codeline>		&lt;p&gt;Total Amount:  </codeline>
<codeline>		&lt;xsl:value-of select=&quot;expense-report/total&quot;/&gt; </codeline>
<codeline>		&lt;/p&gt; </codeline>
<codeline>	&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<para>Die eigentliche Arbeit im Stylesheet wird über die xsl:template-Elemente gesteuert. Im Beispiel ist eines vorhanden mit dem Attribut match=&quot;/&quot;. Der Wert des Attributs ist ein XPath-Ausdruck und der verwendete Wert gibt das Root-Element des Ausgangsdokuments zurück. Dementsprechend werden die in diesem Element enthaltenen Anweisungen auf das Root-Element angewendet. Da es möglich ist, dass verschiedene Templates auf ein einzelnes Element passen, gilt, dass jeweils das Template verwendet wird, welches am besten auf das Element passt.</para>
<para>Ein Template mit einem Match auf den Namen des Elements erhält in diesem Fall also den Vorzug zu einem Template mit einem Match auf * (alle Elemente).</para>
<para>Ist kein passendes Template im Stylesheet enthalten, so wird das build-in-Template aufgerufen. Dies hat zur folge, dass die die Templates der Kindelemente aufgerufen werden, bzw. der Textinhalt ausgegeben wird. Soll dies verhindert werden, empfielt sich die Verwendung eines leeren Templates mit einem match-Attribut mit dem Wert &quot;*&quot;, damit es auf alle passt. Dieses wird dann verwendet, wenn keine Templates vorhanden sind für ein spezifisches Element, welches besser passen würde.</para>
</section>
<section><section-header>Grundlegende XSLT-Elemente</section-header>
<para>An dieser Stelle werden die wesentlichen Elemente der XSLT-Syntax dargestellt. Weitere Elemente werden in einem späteren Abschnitt vorgestellt.</para>
<section>
<section-header>xsl:stylesheet</section-header>
<para>Das xsl:stylesheet-Element enthält das Stylesheet-Modul. Es darf keine Textinhalte ausser Whitespaces enthalten. Es muss ein Attribut namens version enthalten, dessen Wert derzeit, vlg. der derzeitigen Version des Standards, &quot;2.0&quot; lauten soll. Ausserdem ist der Namensraum für XSLT anzugeben.</para>
<para>Im stylesheet-Element enthalten sein dürfen folgende Elemente: xsl:import, xsl:include, xsl:attribute-set, xsl:decimal-format, xsl:function, xsl:import-schema, xsl:key, xsl:namespace-alias, xsl:output, xsl:param, xsl:preserve-space, xsl:sort-key, xsl:strip-space, xsl:template und xsl:variable. Abgesehen vom xsl:import-Element, welches vor allen anderen Elementen erscheinen muss, ist die Anordnung der Elemente beliebig.</para>
</section>
<section><section-header>xsl:template</section-header>
<para>Die Ausgabe wird über die Definition von Templates gesteuert. Ausgehend vom Root-Element lässt sich durch den Aufruf von xsl:apply-templates die Verarbeitung der Kindknoten nach ihren eigenen Templateregeln veranlassen.</para>
<para>Die Templates werden als Kindelementen des Rootelements xsl:stylesheet im XSLT-Dokument abgelegt. Über ihre Verwendung entscheidet ihr Attribut match. Das Attribut enthält ein Muster nach bestimmten Regeln, welches definiert, auf welche Knoten es angewendet werden soll. Ein Template kann einen Namen haben (name-Attribut), über den es direkt aufgerufen werden kann.</para>
<code>
<label>Beispiel 50: xsl:template und xsl:apply-templates</label>
<codeline>&lt;xsl:template match=&quot;emph&quot;&gt; </codeline>
<codeline>  &lt;b&gt; </codeline>
<codeline>    &lt;xsl:apply-templates/&gt; </codeline>
<codeline>  &lt;/b&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
<para>Das im Beispiel definierte Template passt auf alle emph-Elemente. Kommt es zur Anwendung, so wird ein b-Element ausgegeben, welches die Ausgaben der Templates zu allen Kindknoten des emph-Elements enthält.</para>
</section>
<section><section-header>xsl:apply-templates</section-header>
<para>Dieses Element ordnet an, dass alle Knoten durch ihre Templates, sofern passende gefunden werden, ausgegeben werden sollen. Gesteuert wird, welche Knoten ausgegeben werden sollen, über das select-Attribut. Fehlt dieses Attribut, werden für alle Kindknoten des aktuellen Elements die Templates, sofern passende vorhanden, aufgerufen. Es ist auch möglich, über den select-Ausdruck Templates von Knoten aufzurufen, die keine untergeordneten Kinder sind sondern sich oberhalb des aktuellen Knoten befinden, oder von solchen, die nicht direkt untergeordnet sind, sondern tiefer in der Verschachtelung liegen.</para>
</section>
<section><section-header>xsl:call-template</section-header>
<para>Benannte Templates können an einer Stelle nametlich aufgerufen werden, indem ein xsl:call-template-Element eingefügt wird, welches mit einem entsprechenden name-Attribut versehen ist.</para>
</section>
<section><section-header>xsl:value-of</section-header>
<para>Das xsl:value-of-Element gibt den PCData-Inhalt eines Knoten aus. Dabei wird über das Attribut select angegeben, auf welche Elemente der Vorgang angewendet werden soll. Das xsl:value-of-Element verfügt über ein zweites, optionales, Attribut namens disable-output-escaping, welches eines der Werte &quot;yes&quot; oder &quot;no&quot; (Standardwert)  enthalten kann. Dieses Attribut besagt ob die Zeichen &lt; und &amp; in der Ausgabe escaped werden sollen.</para>
</section>
<section><section-header>xsl:copy-of</section-header>
<para>Diese Methode wird als deep copy bezeichnet. Entgegen der xsl:value-of-Anweisung gibt xsl:copy-of die komplette Struktur rekursiv, einschliesslich der XML-Tags, der Attribute und Namespaces und sonstige Knoten, des angegebenen Knoten im Quelldokument aus.</para>
</section>
</section>
<section><section-header>Muster und Ausdrücke, XPath/XQuery</section-header>
<para>Im vorhergenden Abschnitt war des Öfteren die Rede von Muster bzw.Ausdrücken, die darüber entscheiden sollen, welche Elemente transformiert werden. Auch wurde von Knoten gesprochen, was bedeutet, dass sich die entsprechenden Angaben nicht auf Elemente allein beziehen.</para>
<section>
<section-header>Muster nach XPath und Abfragen nach XQuery</section-header>
<para>Die in diesen Ausdrücke Verwendung findende Syntax ist definiert in XPath und XQuery. XPath dient auch ausserhalb von XSLT dazu, innerhalb von XML-Dokumenten zu navigieren. Es ist u.a. im DOM von XML möglich, ausgehend von einem Element über einen XPath-Ausdruck, andere Elemente zu selektieren. Die Xquery-Syntax soll so etwas wie SQL für XML werden. Es ist also eine mächtige Abfragesprache für Mengen von Datensätzen. XPath und Xquery sind sehr eng verwand - eine getrennte Betracfhtung wäre daher unsinnig.</para>
<para>Ein XPath-Ausdruck geht immer von einem gewählten Knoten aus. Um andere Knoten anzusprechen werden sogenannte Achsen verwendet, kombiniert mit direkten Pfadangaben und anderen Filterausdrücken.</para>
<section>
<section-header>Achsen</section-header>
<para>Die über die Achse anvisierten Knoten werden durch Test-Ausdrücken gefiltert. Der Testausdruck wird hinter der Achse geschrieben, von ihm getrennt mit einem doppelten Doppelpunkt (&quot;::&quot;). Ein einfacher Knotentest ist die Angabe eines Namen der gesuchten Knoten. Damit würden all jene Elemente in der Ergebnismenge enthalten sein, die Teil der angegebenen Achse sind und zudem einen vorgegebenen Namen haben.</para>
<table>
<tr>
<th><para>Achse</para>
</th>
<th><para>Inhalt</para>
</th>
</tr>
<tr>
<td><para>child</para>
</td>
<td><para>Alle direkten Kindelemente</para>
</td>
</tr>
<tr>
<td><para>descendant</para>
</td>
<td><para>Alle untergeordneten Elemente (also auch jene unterhalb der direkten Kinder)</para>
</td>
</tr>
<tr>
<td><para>parent</para>
</td>
<td><para>Der übergeordnete Elemente, falls vorhanden</para>
</td>
</tr>
<tr>
<td><para>ancestor</para>
</td>
<td><para>Alle übergeordneten Elemente, sofern vorhanden (also der Vaten, dessen Vaten usw)</para>
</td>
</tr>
<tr>
<td><para>following-sibling</para>
</td>
<td><para>Alle benachbarten Elemente in der gleichen Ebene, die auf den aktuellen Knoten folgen</para>
</td>
</tr>
<tr>
<td><para>preceding-sibling</para>
</td>
<td><para>Alle benachbarten Elemente in der gleichen Ebene, die dem aktuellen Knoten vorausgehen</para>
</td>
</tr>
<tr>
<td><para>following</para>
</td>
<td><para>Alle auf den aktuellen Knoten folgenden Elemente im selben Zweig des Dokuments</para>
</td>
</tr>
<tr>
<td><para>preceding</para>
</td>
<td><para>Alle dem aktuellen Knoten vorausgehenden Elemente im selben Zweig des Dokuments</para>
</td>
</tr>
<tr>
<td><para>self</para>
</td>
<td><para>Der aktuelle Knoten selbst</para>
</td>
</tr>
<tr>
<td><para>descendant-or-self</para>
</td>
<td><para>Der aktuelle Knoten selbst und alle untergeordneten vlg. descendant</para>
</td>
</tr>
<tr>
<td><para>ancestor-or-self</para>
</td>
<td><para>Der aktuelle Knoten selbst und alle Eltern vlg. ancestor</para>
</td>
</tr>
<tr>
<td><para>attribute</para>
</td>
<td><para>Die Attribute des aktuellen Knoten</para>
</td>
</tr>
<tr>
<td><para>namespace</para>
</td>
<td><para>Der namespace-Knoten des aktuellen Knoten (deprecated)</para>
</td>
</tr>
<label>Tabelle 5: Achsen in XPath</label>
</table>
<para>Der einfachste Knotentest ist wohl der Ausdruck &quot;*&quot;, der schlicht alle Knoten selektiert. Ein Pfad mit einem solchen Test sähe beispielsweise so aus:</para>
<code>
<label>Beispiel 51: Einfache XPath-Abfrage</label>
<codeline>&lt;xsl:apply-templates select=&quot;child::*&quot; /&gt; </codeline>
<codeline>Diese Anweisung bewirkt, dass alle Kinder unterhalb des aktuellen Knoten verarbeitet werden.  </codeline>
</code>
</section>
<section><section-header>Schritte</section-header>
<para>Ein Pfad muss nicht zwangsläufig aus einer Achse bestehen sondern kann, auch teilweise, durch eine Pfadangabe beschrieben werden. Eine solche Pfadangabe besteht aus einem oder mehreren Schnitten, die mit &quot;/&quot; oder &quot;//&quot; getrennt werden, je nach dem, ob im Baum nach unten oder nach oben gelaufen werden soll.</para>
<code>
<label>Beispiel 52: Pfadausdruck</label>
<codeline>&lt;xsl:apply-templates select=&quot;child::div1/child::para&quot;&gt; </codeline>
</code>
<para>Dieser Ausdruck selektiert die para-Elemente, welche Kinder der div1-Elemente sind, die ihrerseits Kinder des aktuellen Knoten sind; Oder anders ausgedrückt: es werden diejenige para-Elemente gewählt, deren Großvater der aktuelle Knoten ist und wessen Väter div1-Elemente sind.</para>
<para>Wird ein &quot;/&quot; am Anfang einer Pfadangabe notiert, ist damit das Root-Element des Dokuments gemeint; ein &quot;//&quot; am Anfang selektiert alle Knoten des aktuellen Dokuments.</para>
</section>
<section><section-header>KindTest</section-header>
<para>Es ist auch möglich, Knoten in einer Achse auf ihren Typen zu Testen. Hiermit wird auch klar, warum bisher die Rede von Knoten war und nicht, wie es naheliegend war, von Elementen. Der Test auf einen Typen wird als KindTest bezeichnet.</para>
<table>
<tr>
<th><para>KindTest</para>
</th>
<th><para>Passt auf...</para>
</th>
</tr>
<tr>
<td><para>Node()</para>
</td>
<td><para>alle Knoten</para>
</td>
</tr>
<tr>
<td><para>Comment()</para>
</td>
<td><para>alle Kommentare</para>
</td>
</tr>
<tr>
<td><para>Text()</para>
</td>
<td><para>jeden Textknoten</para>
</td>
</tr>
<tr>
<td><para>Element()</para>
</td>
<td><para>jedes Element</para>
</td>
</tr>
<tr>
<td><para>Attribute()</para>
</td>
<td><para>alle Attribute</para>
</td>
</tr>
<label>Tabelle 6: KindTest auf Knoten</label>
</table>
<para>Damit ist klar: Als Knoten wird jeder Bestandteil eines XML-Dokuments bezeichnet (ausgenommen sind Processor Instructions).</para>
</section>
<section><section-header>Filter</section-header>
<para>Die Ergebnismenge an Knoten lässt sich über Filterangaben noch weiter eingrenzen. Anschliessend an der allen bisherigen Angaben zum Pfad, wird ein Ausdruck in eckigen Klammern verwendet. In diesen Klammern kann ein Test auf ein Attribut stehen, eine Indexangabe oder auch ein Test auf Kindelemente des gewünschten Knoten in der Ergebnismenge. Aber auch mathematische Tests sind erlaubt.</para>
<code>
<label>Beispiel 53: Filtern der Ergebnismenge</label>
<codeline>&lt;xsl:apply-templates select=&quot;child::chapter[2]&quot;&gt; </codeline>
<codeline>&lt;xsl:apply-templates select=&quot;child::employee[secretary]&quot;&gt; </codeline>
<codeline>&lt;xsl:apply-templates select=&quot;child::toy[attribute::color=&apos;red&apos;]&quot;&gt; </codeline>
</code>
<para>Die erste Zeile im Beispiel wählt das zweite chapter-Kindelement. Die zweite Zeile wählt jene Kindel-employee-Emente, die ihrerseits über ein secretary-Element als Kind verfügen. Schliesslich selektiert die dritte Zeile all jene toy-Kindelemente, die über einen Attributwert &quot;red&quot; für das Attribut color verfügen.</para>
</section>
<section><section-header>Weiter Selektionsmechanismen in XPath</section-header>
<para>XPath verfügt neben den gezeigten Methoden noch über weitere, die dazu verwendet werden können um Ergebnismengen so gezielt wie möglich zu beschreiben. Eine detaillierte Beschreibung dieser Methoden würde allerdings den Rahmen des Skripts sprengen, weswegen sie an dieser Stelle lediglich der Vollständigkeit halber kurz aufgezählt werden.</para>
<ul><para><li>
Es ist möglich, benannte Elemente in einer bestimmten Reihenfolge ausgeben zu lassen.</li>
</para>
<para><li>
Es ist möglich, einzelne vollständige Ausdrücke zu kombinieren (in logischer Manier; also union, intersect und except für or, and bzw. xor).</li>
</para>
<para><li>
Inhaltsprüfung von Elementen</li>
</para>
<para><li>
Testen ob Ergebnismengen identisch sind</li>
</para>
<para><li>
Testen auf Position im Dokument</li>
</para>
<para><li>
Ausserdem ist es sogar möglich, über die Ergebnismenge mittels einer for-Schleife zu itterieren oder eine bedingte Ausgabe mittels einer if-Konstruktion zu generieren.</li>
</para>
<para><li>
Schliesslich können sogenannte quantifizeirte Ausdrücke verwendet werden, auf Datentyp geprüft werden und Datentypen gecastet werden.</li>
</para>
</ul></section>
</section>
<section><section-header>Sonstige Muster</section-header>
<para>Die im vorausgehenden Abschnitt diskutierten Muster finden u.a. Verwendung bei der Selektion der Knoten, auf die Templates angewendet werden sollen.</para>
<para>Die für die match-Attribute eines Templates verwendeten Ausdrücke basieren auf die gleichen Vorschriften, wobei allerdings nicht der vollständige Funktionsumfang der XPath-Ausdrücke angewendet werden kann.</para>
<code>
<label>Beispiel 54: Beispiele für match-Attribute von Templates</label>
<codeline>&lt;xsl:template match=&quot;*&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;/&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;chapter|appendix&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;para[1]&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;olist/item&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;appendix//para&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
</code>
<para>Die Beispiele ergeben folgendes: In der ersten Zeile passt das Template auf alle Elemente, in der zweiten Zeile auf das Root-Element. Das Template in der dritten Zeile passt auf alle chapter- und appendix-Elemente; das in der vierten Zeile auf jedes para-Element, welches das erste Kind seines Vaters ist. Das Template in der vorletzten Zeile passt auf item-Elemente, die ein olist-Vater haben und das Template in der letzten Zeile passt auf alle para-Elemente, die ein übergeordnetes appendix-Element besitzen.</para>
</section>
<section><section-header>XPath-Operatoren</section-header>
<para>Die an dieser Stelle behandelten Funktionen sind zwar Teil von XPath, tragen aber wesentlich zur Gestaltung der Funktionalität eines XSLT-Stylesheets bei.</para>
<section>
<section-header>Arithmetische Operatoren</section-header>
<para>Es lassen sich einige mathematische Ausdrücke in XPath-Ausdrücken verwenden. Erwartungsgemäß funktioniert eine Addition über ein +, eine Subtraktion mit -, sowie die Multiplikation mittels *. Die Division über / ist allerdings nicht möglich, da das / ein Pfadoperator darstellt (s.o.). Die Division wird durch den Ausdruck div bewerkstelligt. Eine gerundete Division wird über idiv erreicht. Daneben gibt es einen Modulusoperator mod, der den Nachkommateil einer Division zurückgibt.</para>
</section>
<section><section-header>Vergleichsoperatoren</section-header>
<para>Innerhalb von Ausdrücken können zunächst die üblichen Vergleichsoperatoren wie &gt;. &gt;=, &lt;, &lt;= und = eingesetzt werden. So lässt sich beispielsweise Prüfen, ob das Element des aktuellen Kontexts einen bestimmten Namen (nicht) hat oder ob seine Position innerhalb Liste der Kinder des Elternknoten mit einem bestimmten Wert übereinstimmt. Dabei können Pfadausrücke Verwendung finden, genauso wie Konstanten (Zeichenketten, Zahlen, etc.).</para>
<para>Ein weiterer Vergleichoperator ist is, welches Prüft, ob die Ergebnisse der Ausdrücke auf beiden Seiten des Operators identisch (bspw. der selbe Knoten) sind.</para>
<code>
<label>Beispiel 55: is-Operator</label>
<codeline>//book[isbn=&quot;1558604820&quot;] is //book[call=&quot;QA76.9 C3845&quot;] </codeline>
</code>
<para>Die im Beispiel verwendeten eckigen Klammern enthalten Prüfungen bzgl. Attribute der selektierten book-Elemente.</para>
<para>Um Textknoten zu vergleichen gibt es die Vergleichsoperatoren eq (equal; ist gleich), ne (not equal; ist nicht gleich), lt (lesser than; kleiner als), le (lesser or equal; kleiner oder gleich), gt (greater than; grösser als) und ge (greater or equal; grösser oder gleich).</para>
<code>
<label>Beispiel 56: eq-Operator</label>
<codeline>$book1/author eq &quot;Kennedy&quot; </codeline>
</code>
<para>Der Ausdruck im Beispiel ist wahr, wenn das $book1-Element ein einzelnes author-Kindobjekt besitzt, wessen Wert &quot;Kennedy&quot; lautet.</para>
</section>
<section><section-header>Reihenfolgen-Operatoren</section-header>
<para>Mittels der Operatoren &lt;&lt; und &gt;&gt; lässt sich prüfen, ob ein Knoten vor oder nach einem anderen Knoten im Dokument enthalten ist.</para>
<code>
<label>Beispiel 57: Reihenfolge-Operatoren</label>
<codeline>//purchase[parcel=&quot;28-451&quot;] &lt;&lt; //sale[parcel=&quot;33-870&quot;] </codeline>
</code>
</section>
<section><section-header>Logische Ausdrücke</section-header>
<para>Einzelne Ausdrücke lassen sich über and und or Verknüpfen. Ausserdem gibt es die Negatorfunktion not(), welche den ihr übergebenen Ausdruck invertiert. Der Einfachheit halber ist es zudem möglich, einzelne Ausdrücke zu klammern.</para>
</section>
<section><section-header>Bedingungs-Ausdruck</section-header>
<para>Um die Rückgabe eines Ausdruck zu steuern, kann ein if-Konstrukt verwendet werden, der ein Teilausdruck auswertet und abhängig vom Ergebnis eine Rückgabe bestimmt.</para>
<code>
<label>Beispiel 58: if-Kontrukt</label>
<codeline>if ($widget1/unit-cost &lt; $widget2/unit-cost)  </codeline>
<codeline>  then $widget1 </codeline>
<codeline>  else $widget2 </codeline>
</code>
</section>
<section><section-header>Weitere Operatoren</section-header>
<para>Neben den hier erwähnten Operatoren, gibt es noch einige weitere wie quantifizierte Ausdrücke, Casts und Konstruktor-Funktionen. Auf eine ausführliche Darstellung dieser wird an dieser Stelle allerdings verzichtet.</para>
</section>
</section>
<section><section-header>XPath- und Xquery-Funktionen</section-header>
<para>Die Darstellung sämtlicher XPath- und Xquery-Funktionen würde den avisierten Umfang des Skriptes zweifellos übersteigen. Auch in Bezug auf diese sei auf die W3C-Spezifikationen verwiesen.</para>
<para>Einige wenige sollten allerdings bekannt sein. So dient bspw. die Funktion count() dazu, die Anzahl der in einer Menge befindlichen Elemente zu zählen. Die Funktion position() andererseits gibt auskunft darüber, an welcher Position innerhalb einer List sich ein Knoten befindet.</para>
</section>
</section>
<section><section-header>Weitere XSLT-Elemente</section-header>
<para>Die grundlegenden Elemente der XSLT-Syntax wurden bereits besprochen. Es werden nachfolgend weitere, wichtige Elemente kurz erläutert. Dabei werden keine vollständigen Definition vorgenommen.</para>
<section>
<section-header>xsl:import, xsl:include</section-header>
<para>Mittels dieser beiden Anweisungen lassen sich externe Stylesheets (egal, ob es sich dabei um normale, simplified oder embedded Stylesheets handelt) oder normale XML-Dokumente einbinden. Die beiden Anweisungen erfahren über das href-Attribut, welches Dokument eingebunden werden soll. Der Unterschied zwischen beiden liegt darin, dass die Templateregeln des importierenden Stylesheets vorrang haben gegenüber solche, die importiert werden; die Templates eines includierten Dokuments überschreiben jedoch die im includierenden Dokument.</para>
</section>
<section><section-header>xsl:output</section-header>
<para>Dieses Element kann optional im Top-Level des Stylesheets eingesetzt werden (auch mehrfach). Durch seine Verwendung kann die Ausgabe des Prozesses gesteuert werden. Dies betrifft bspw. die Zeichensatzkodierung als auch das Escapen von CData, sowie den Umgang mit Whitespace.</para>
</section>
<section><section-header>xsl:variable</section-header>
<para>Durch das xsl:variable-Element lassen sich Variablen in einem Stylesheet definieren. Das optionale Attribut as legt fest, um welchen Datentyp es sich handelt. Der Wert der Variablen wird über den ausgewerteten Ausdruck im select-Attribut festgelegt. Wird das select-Attribut verwendet, so muss das xsl:variable-Element leer sein. Wird kein select-Attribut verwendet, so wird der Inhalt des Elements als Wert für die Variable verwendet. Das Ergebnis der Zuweisung in den folgenden Beispielen ist demnach identisch.</para>
<code>
<label>Beispiel 59: xsl:variable</label>
<codeline>&lt;xsl:variable name=&quot;n1&quot; select=&quot;2&quot;&gt; </codeline>
<codeline>&lt;xsl:variable name=&quot;n2&quot; as=&quot;xs:integer&quot;&gt;2&lt;/xsl:variable&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;t[$n1]&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;t[$n2]&quot;&gt; ... &lt;/xsl:template&gt; </codeline>
</code>
<para>Die beiden Variablen n1 und n2 enthalten den numerischen Wert 2. Um die Bedeutung des as-Attributs zu verdeutlichen sei folgendes Angemerkt: Wenn bei der Deklaration der Variablen n2 auf das as-Attribut verzichtet würde, so wäre der Wert der Variablen die Zeichenkette &quot;2&quot;, wodurch das entsprechende match-Statement nicht den zweiten Knoten des t-Elemente selektieren würde.</para>
</section>
<section><section-header>xsl:copy</section-header>
<para>Das xsl:copy-Element ist prinzipiell identisch mit dem xsl:copy-of-Element, unterscheidet sich jedoch in der Hinsicht, dass es kein select-Attribut besitzt, womit gesteuert werden könnte, welche der Knoten selektiert bzw. kopiert werden sollen.</para>
</section>
<section><section-header>xsl:text</section-header>
<para>Um einen Text-Knoten zu erzeugen, kann das xsl:text-Element verwendet werden. Es besitzt lediglich ein einzelnes Attribut disable-output-escaping, welches bestimmt, ob die Ausgabe escapet werden soll oder nicht. Generell lässt sich ein Textknoten an jeder Stelle eines Templates erzeugen, indem schlicht der Textinhalt in das Template geschrieben wird. Die Verwendung des xsl:text-Elements erlaubt jedoch eine gezieltere Ausgabe. Dies ist gerade in dem Falle sinnvoll, wenn das indent-Attribut eines verwendeten output-Elements auf &quot;no&quot; gesetzt wurde.</para>
</section>
<section><section-header>xsl:element</section-header>
<para>So, wie einfacher Text in die Ausgabe eines Templates erzeugt werden kann, so können ebenfalls Elemente erzeugt werden, indem sie schlicht in das Template hineingeschrieben werden. Der gezielte Weg zur Ausgabe von neuen Elementknoten führt jedoch über die Verwendung des xsl:element-Elements, welcher einen neuen Elementknoten in der Ausgabe erzeugt. Es ist möglich, dem neuen Elementknoten über das Attribut use-attribute-sets bei der Erzeugung mit einem oder mehreren Attributgruppen auszustatten,die vorher definiert wurden. Über das name-Attribut wird der Tagname des zu erzeugenden Elements angegeben.</para>
</section>
<section><section-header>xsl:attribute</section-header>
<para>Befindet man sich innerhalb eines Elementknoten der Ausgabe, so kann dieser mit Attributen ausgestattet werden, indem ein xsl:attribut-Element verwendet wird. Über das name-Attribut wird der Attributnamen festgelegt, der Inhalt wird als Attributswert im Element verwendet.</para>
</section>
<section><section-header>xsl:attribute-set</section-header>
<para>Das xsl:attribute-set-Element fasst mehrere xsl:attribute-Elemente zu einer Gruppe zusammen, sodass diese sehr einfach in einem Zug an ein Element der Ausgabe weitergereicht werden können. Das name-Attribut bestimmt, über welchen Namen ein bestimmter Satz an Attributen angesprochen wird. Dies kann im use-attribute-sets-Attribut eines xsl:element geschehen, aber auch in jedem manuell erzeugten Elementknoten der Ausgabe, indem diesem ein Attribut mit der gleichen Bezeichnung allerdings ergänzt um den XSL-Namenraum verwendet wird.</para>
<para>Eine Attributgruppe kann auf einer anderen Gruppe basieren, dessen Inhalt übernommen wird und von den eigenen Inhalten überschrieben bzw. ergänzt werden kann. Hierzu wird das use-attribute-sets-Attribute des xsl:attribute-set-Element verwendet.</para>
<code>
<label>Beispiel 60: xsl:attribute und xsl:attribute-set</label>
<codeline>&lt;xsl:template match=&quot;chapter/heading&quot;&gt; </codeline>
<codeline>	&lt;fo:block font-stretch=&quot;condensed&quot;  </codeline>
<codeline>					xsl:use-attribute-sets=&quot;title-style&quot;&gt; </codeline>
<codeline>		&lt;xsl:apply-templates/&gt; </codeline>
<codeline>	&lt;/fo:block&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:attribute-set name=&quot;title-style&quot;&gt; </codeline>
<codeline>	&lt;xsl:attribute name=&quot;font-size&quot;&gt;12pt&lt;/xsl:attribute&gt; </codeline>
<codeline>	&lt;xsl:attribute name=&quot;font-weight&quot;&gt;bold&lt;/xsl:attribute&gt; </codeline>
<codeline>&lt;/xsl:attribute-set&gt; </codeline>
</code>
</section>
<section><section-header>xsl:if</section-header>
<para>Eine bedingte Ausgabe lässt über ein xsl:if-Element steuern. Sein test-Attribut nimmt einen Ausdruck auf, der darüber entscheidet ob die Methoden und Ausgaben im xsl:if-Element aufgerufen werden oder nicht. Das Beispiel zeigt, wie in einer generierten Tabelle jede gerade Zeile mit einer gelben Hintergrundfarbe versehen wird.</para>
<code>
<label>Beispiel 61: xsl:if</label>
<codeline>&lt;xsl:template match=&quot;item&quot;&gt; </codeline>
<codeline>	&lt;tr&gt; </codeline>
<codeline>		&lt;xsl:if test=&quot;fn:position() mod 2 = 0&quot;&gt; </codeline>
<codeline>			&lt;xsl:attribute name=&quot;bgcolor&quot;&gt;yellow&lt;/xsl:attribute&gt; </codeline>
<codeline>		&lt;/xsl:if&gt; </codeline>
<codeline>		&lt;xsl:apply-templates/&gt; </codeline>
<codeline>	&lt;/tr&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
</section>
<section><section-header>xsl:choose, xsl:when und xsl:otherwise</section-header>
<para>Ähnlich einer switch/case-Konstruktion in gängigen Programmiersprachen, dienen die Elemente xsl:choose, xsl:when und xsl:otherweise dazu, eine Fallunterscheidung zu konstruieren. Die Fallunterscheidung findet effektiv in den xsl:when-Elementen statt, indem der Ausdruck im jeweiligen test-Attribut vgl. xsl:if ausgewertet wird. Ein optional einmalig vorhandenes xsl:otherwise-Element kommt dann zum Zuge, wenn keines der vorhandenen xsl:when-Bedingungen passt.</para>
<para>Im Beispiel wird eine Tabellenzeile gelb hinterlegt, wenn die Verschachtelungstiefe des aktuellen Knoten eine Ebene beträgt, wenn sie zwei beträgt, wird die die Zeile blau, ansonsten silbern.</para>
<code>
<label>Beispiel 62: xsl:if</label>
<codeline>&lt;xsl:template match=&quot;item&quot;&gt; </codeline>
<codeline>	&lt;tr&gt; </codeline>
<codeline>		&lt;xsl:choose&gt;	 </codeline>
<codeline>			&lt;xsl:when test=&quot;count(ancestor::*) = 1&quot;&gt; </codeline>
<codeline>				&lt;xsl:attribute name=&quot;bgcolor&quot;&gt;yellow&lt;/xsl:attribute&gt; </codeline>
<codeline>			&lt;/xsl:when&gt; </codeline>
<codeline>			&lt;xsl:when test=&quot;count(ancestor::*) = 2&quot;&gt; </codeline>
<codeline>				&lt;xsl:attribute name=&quot;bgcolor&quot;&gt;blue&lt;/xsl:attribute&gt; </codeline>
<codeline>			&lt;/xsl:when&gt; </codeline>
<codeline>			&lt;xsl:otherwise&gt; </codeline>
<codeline>				&lt;xsl:attribute name=&quot;bgcolor&quot;&gt;silver&lt;/xsl:attribute&gt; </codeline>
<codeline>			&lt;/xsl:otherwise&gt; </codeline>
<codeline>		&lt;/xsl:choose&gt; </codeline>
<codeline>	    &lt;xsl:apply-templates/&gt; </codeline>
<codeline>	&lt;/tr&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
</section>
<section><section-header>xsl:for-each</section-header>
<para>Der xsl:for-each-Konstrukt iteriert über eine Ergebnismenge einer Knotenabfrage, die im select-Attribut angegeben wurde.</para>
<para>Im Beispiel werden alle car-Elemente ausgegeben, deren color-Attribute den Wert &quot;red&quot; enthalten.</para>
<code>
<label>Beispiel 63: xsl:for-each</label>
<codeline>&lt;xsl:for-each select=&quot;car[@color=&apos;red&apos;]&quot;&gt; </codeline>
<codeline>	&lt;tr&gt;&lt;td&gt; </codeline>
<codeline>		&lt;xsl:apply-templates /&gt; </codeline>
<codeline>	&lt;/td&gt;&lt;/tr&gt; </codeline>
<codeline>&lt;/xsl:for-each&gt; </codeline>
</code>
</section>
<section><section-header>xsl:for-each-group</section-header>
<para>Die xsl:for-each-group ermöglicht das Gruppieren von Inhalten. Über die Ergebnisgruppen wird itteriert, wobei die jeweils aktuelle Gruppe über die current-group()-Methode zugegriffen werden kann. Diese Funktion des Gruppieren ist sehr vielseitig in der Anwendung. Die Aufteilung der Ergebnismenge des select-Attributs basiert auf verschiedene Methoden, die durch die Verwendung unterschiedlicher Attribute erreicht wird. Zur Verfügung stehen die Attribute group-by, group-adjecent, group-starting-with und group-ending-with. Von diesen vier Attributen muss ein einzelnes angegeben werden.</para>
<table>
<tr>
<th><para>Gruppierungsmethode</para>
</th>
<th><para>Ergebnis</para>
</th>
</tr>
<tr>
<td><para>group-by</para>
</td>
<td><para>Der Ausdruck in diesem Attribut wird als Schlüsselbedingung interpretiert, nach der die Knoten gruppiert werden.</para>
</td>
</tr>
<tr>
<td><para>group-adjacent</para>
</td>
<td><para>Die Knoten werden nacheinander Ausgewertet. Solange das Ergebnis des Test gleich ist, mit dem des Vorgängers, wird der aktuelle Knoten zur Gruppe hinzugefügt. Ist das Ergebnis ein anderes, wird eine neue Gruppe begonnen.</para>
</td>
</tr>
<tr>
<td><para>group-starting-with</para>
</td>
<td><para>Fasst Knoten zusammen in der Reihenfolge ihres Erscheinen, bis ein Knoten auftritt, auf welchem die Bedingung passt. Dieser Knoten wird anschliessend zur ersten der nächsten Gruppe.</para>
</td>
</tr>
<tr>
<td><para>group-ending-with</para>
</td>
<td><para>Identisch zu group-starting-with, mit der Ausnahme, dass eine neue Gruppe angefangen wird, nachdem ein Knoten aufgetreten ist, auf dem die Bedingung passte.</para>
</td>
</tr>
<label>Tabelle 7: xsl:for-each-group Methoden</label>
</table>
<code>
<label>Beispiel 64: xsl:for-each-group mit group-starting-with-Methode: Quelldokument</label>
<codeline>&lt;body&gt; </codeline>
<codeline>	&lt;h2&gt;Introduction&lt;/h2&gt; </codeline>
<codeline>	&lt;p&gt;XSLT is used to write stylesheets.&lt;/p&gt; </codeline>
<codeline>	&lt;p&gt;XQuery is used to query XML databases.&lt;/p&gt; </codeline>
<codeline>	&lt;h2&gt;What is a stylesheet?&lt;/h2&gt; </codeline>
<codeline>	&lt;p&gt;A stylesheet is an XML document  </codeline>
<codeline>		used to define a transformation.&lt;/p&gt; </codeline>
<codeline>	&lt;p&gt;Stylesheets may be written in XSLT.&lt;/p&gt; </codeline>
<codeline>	&lt;p&gt;XSLT 2.0 introduces new grouping constructs.&lt;/p&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
</code>
<code>
<label>Beispiel 65: xsl:for-each-group mit group-starting-with-Methode: Verlangte Ausgabe</label>
<codeline>&lt;chapter&gt; </codeline>
<codeline>	&lt;section title=&quot;Introduction&quot;&gt; </codeline>
<codeline>		&lt;para&gt;XSLT is used to write stylesheets.&lt;/para&gt; </codeline>
<codeline>		&lt;para&gt;XQuery is used to query XML databases.&lt;/para&gt; </codeline>
<codeline>	&lt;/section&gt;  </codeline>
<codeline>	&lt;section title=&quot;What is a stylesheet?&quot;&gt; </codeline>
<codeline>		&lt;para&gt;A stylesheet is an XML document  </codeline>
<codeline>				used to define a transformation.&lt;/para&gt; </codeline>
<codeline>		&lt;para&gt;Stylesheets may be written in XSLT.&lt;/para&gt; </codeline>
<codeline>		&lt;para&gt;XSLT 2.0 introduces new grouping constructs.&lt;/para&gt; </codeline>
<codeline>	&lt;/section&gt; </codeline>
<codeline>&lt;/chapter&gt; </codeline>
</code>
<code>
<label>Beispiel 66: xsl:for-each-group mit group-starting-with-Methode: Verwendetes Template</label>
<codeline>&lt;xsl:template match=&quot;body&quot;&gt; </codeline>
<codeline>	&lt;chapter&gt; </codeline>
<codeline>		&lt;xsl:for-each-group select=&quot;*&quot; group-starting-with=&quot;h2&quot;	&gt; </codeline>
<codeline>			&lt;section title=&quot;{self::h2}&quot;&gt; </codeline>
<codeline>			&lt;xsl:for-each select=&quot;current-group()[self::p]&quot;&gt; </codeline>
<codeline>				&lt;para&gt;&lt;xsl:value-of select=&quot;.&quot;/&gt;&lt;/para&gt; </codeline>
<codeline>			&lt;/xsl:for-each&gt;  </codeline>
<codeline>			&lt;/section&gt; </codeline>
<codeline>		&lt;/xsl:for-each-group&gt; </codeline>
<codeline>	&lt;/chapter&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
</section>
<section><section-header>xsl:number</section-header>
<para>Bei der Transformierung eines XML-Dokuments kann auf einen integrierten Mechanismus zur Nummerierung zurückgegriffen werden. Erreicht wird diese über das xsl:number-Element. Es gibt eine formatierte Nummerierung als Textknoten aus. Die Formatierung wird über das format-Attribut gesteuert.</para>
<para>An jeder Stelle, an der eine Nummerierung eingefügt werden soll, wird ein xsl:number-Element in das Template eingefügt. Über das value-Attribut lässt sich eine Nummer für die Ausgabe vorgeben, wie das folgende Beispiel verdeutlichent.</para>
<code>
<label>Beispiel 67: xsl:number mit value-Attribut</label>
<codeline>&lt;xsl:template match=&quot;items&quot;&gt; </codeline>
<codeline>	&lt;xsl:for-each select=&quot;item&quot;&gt; </codeline>
<codeline>		&lt;xsl:sort select=&quot;.&quot;/&gt; </codeline>
<codeline>		&lt;p&gt; </codeline>
<codeline>			&lt;xsl:number value=&quot;fn:position()&quot; format=&quot;1. &quot;/&gt; </codeline>
<codeline>			&lt;xsl:value-of select=&quot;.&quot;/&gt; </codeline>
<codeline>		&lt;/p&gt; </codeline>
<codeline>	&lt;/xsl:for-each&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
<para>Soll die Ausgabe vielmehr anhand der Position im Dokument erfolgen, wird das value-Attribut nicht angegeben. An seiner Stelle werden die Attribute level, count und from eingefügt. Das level-Attribut spezifiziert dabei, welche Knoten in der Zählung berücksichtigt werden sollen. Sein Wert kann single, multiple oder any lauten.</para>
<para>Über das count-Attribut wird mitgeteilt, welche Knoten gezählt werden sollen. Wird es nicht angegeben, wird der Kontextknoten als Wert verwendet. Das from-Attribut gibt an, mit welcher Nummer die Zählung beginnen soll.</para>
<code>
<label>Beispiel 68: xsl:number nach Position im Dokument</label>
<codeline>&lt;xsl:template match=&quot;title&quot;&gt; </codeline>
<codeline>	&lt;fo:block&gt; </codeline>
<codeline>		&lt;xsl:number level=&quot;multiple&quot; </codeline>
<codeline>			count=&quot;chapter|section|subsection&quot; </codeline>
<codeline>			format=&quot;1.1 &quot;/&gt; </codeline>
<codeline>		&lt;xsl:apply-templates/&gt; </codeline>
<codeline>	&lt;/fo:block&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
<codeline>&lt;xsl:template match=&quot;appendix//title&quot; priority=&quot;1&quot;&gt; </codeline>
<codeline>	&lt;fo:block&gt; </codeline>
<codeline>		&lt;xsl:number level=&quot;multiple&quot; </codeline>
<codeline>			count=&quot;appendix|section|subsection&quot; </codeline>
<codeline>			format=&quot;A.1 &quot;/&gt; </codeline>
<codeline>		&lt;xsl:apply-templates/&gt; </codeline>
<codeline>	&lt;/fo:block&gt; </codeline>
<codeline>&lt;/xsl:template&gt; </codeline>
</code>
</section>
<section><section-header>Sonstige Elemente</section-header>
<para>Der Vollständigkeit halber seien an dieser Stelle die bisher nicht benannten XSLT-Elemente aufgelistet. Zu ihrer jeweiligen Bedeutung und Anwendung verweise ich auf die XSLT-Spezifikation des W3C (Version 2.0).</para>
<para>Im einzelnen sind die folgenden Elemente definiert: xsl:preserve-space, xsl:strip-space, xsl:processing-instruction, xsl:function, xsl:result, xsl:result-document, xsl:sort, xsl:matching-substring, xsl:non-matching-substring, xsl:namespace, xsl:key, xsl:import-schema, xsl:fallback, xsl:decimal-format, xsl:comment, xsl:apply-imports und xsl:analyze-string.</para>
</section>
</section>
</section>
</section>
<section><section-header>Teil: PHP</section-header>
<section>
<section-header>Grundlagen</section-header>
<para>Es ist unabdingbar, dass, wenn man sich mit serverseitigem Skripting auseinander setzt, die grundlegenden Mechanismen des Internets bekannt sind. Diese sollen in diesem Kapitel vermittelt werden, bevor danach auf die Funktionsweise von PHP näher eingegangen wird.</para>
<section>
<section-header>Geschichtliches zum Internet</section-header>
<table>
<tr>
<th><para>Jahr</para>
</th>
<th><para>Ereignis</para>
</th>
</tr>
<tr>
<td><para>1945</para>
</td>
<td><para>Vannevar Bush, Memex ("As We May Think")</para>
</td>
</tr>
<tr>
<td></td>
<td><para>Vannevar Bush diskutiert in seinem Artikel &quot;As We May Think&quot; ein persönliches Informationssystem mit Kommunikationsmöglichkeiten und Zugriff auf Bücher, Tonaufnahmen, etc. unter dem Namen Memex.</para>
</td>
</tr>
<tr>
<td><para>1965</para>
</td>
<td><para>Theodor Nelson&apos;s Xanadu-Projekt, Hypertext</para>
</td>
</tr>
<tr>
<td></td>
<td><para>Die Idee hinter dem Hypertext-Konzept postuliert neben der nicht-sequentiellen Organisation des Mediums auch zentrale Begriffe wie Knoten, Link, Anker und Netz. Ziel dieser Überlegungen war es, den auszudrückenden Inhalt von Editoriellen- und Präsentationsinformationen wie Seitenzahlen, Fußnoten, Paginierung usw. zu trennen. Durch die nicht-lineare Organisation soll es dem Leser freigestellt werden, auf welchen Pfaden er sich durch das Dokument bewegt.</para>
</td>
</tr>
<tr>
<td><para>1969</para>
</td>
<td><para>ARPA-Net</para>
</td>
</tr>
<tr>
<td></td>
<td><para>Zwischen einigen Forschungseinrichtungen und Universitäten wird für militärische Projekte ein kleines Telefonnetz eingerichtet, über das Daten ausgetauscht werden können - und zwar auch, wenn einzelne Knoten ausfallen. Versendete Pakete legen einen nicht vorher festgelegten Weg zurück.</para>
</td>
</tr>
<tr>
<td><para>1982</para>
</td>
<td><para>ARPA-Net: 235 Rechner, Elektronische Post (SMTP)</para>
</td>
</tr>
<tr>
<td><para>1983</para>
</td>
<td><para>Auftrag an Fa. BBN, TCP/IP in Berkeley-UNIX zu integrieren</para>
</td>
</tr>
<tr>
<td><para>1988</para>
</td>
<td><para>Internet: 25.000 Rechner</para>
</td>
</tr>
<tr>
<td><para>1989</para>
</td>
<td><para>Internet 100.000 Rechner</para>
</td>
</tr>
<tr>
<td><para>1990</para>
</td>
<td><para>Start des WWW im CERN (Europäisches Kernforschungszentrum) mit zwei Rechnern, erster Browser und Server</para>
</td>
</tr>
<tr>
<td><para>1992</para>
</td>
<td><para>Internet: 900.000 Rechner, Berners-Lee: HTML 1.0</para>
</td>
</tr>
<tr>
<td><para>1993</para>
</td>
<td><para>Grafischer Browser &quot;Mosaic&quot;</para>
</td>
</tr>
<tr>
<td><para>1994</para>
</td>
<td><para>Internet: über 3 Mio. Rechner, Netscape</para>
</td>
</tr>
<tr>
<td><para>1996</para>
</td>
<td><para>Internet: über 10 Mio. Rechner, Europa 2.6 Mio.; HTTP 1.0</para>
</td>
</tr>
<tr>
<td><para>1998</para>
</td>
<td><para>Internet: 30 Mio. Rechner (Europa: 6.3 Mio., Deutschland: 1.2 Mio.)</para>
</td>
</tr>
<tr>
<td><para>2001</para>
</td>
<td><para>Internet: 100 Mio. Rechner (Europa: 13 Mio., Deutschland: 2.3 Mio.)</para>
</td>
</tr>
<label>Tabelle 8: Geschichte des Internets</label>
</table>
</section>
<section><section-header>Funktionsweise des Internet</section-header>
<para>Das Internet ist eine sogenannte Client-/Server-Architektur. Ein zentraler Computer ist als Server mehr oder weniger öffentlich zugänglich und wird von den Clients angesprochen. Die dazu verwendete Kommunikation erfolgt über das TCP/IP-Protokoll. Darüber können Inhalte (bspw. HTML-Dokumente) übertragen werden, die vom Server zum Client geschickt werden, nachdem der Client beim Server über eine URL (bzw. den entsprechenden HTTP-Headern) eine Anfrage gestellt hatte. Ein Server, der über das HTTP-Protokoll ansprechbar ist, wird als Webserver bezeichnet.</para>
<section>
<section-header>Server</section-header>
<para>Dieser wird über eine eindeutige Adresse angesprochen. Auf diesem System laufen Programme, die von anderen Rechnern angesprochen werden können. Eines dieser Serverdienste ist ein Webserver, der, über HTTP angesprochen, HTML-Dokumente und sonstige Inhalte an den Client weiterreicht. Um einen Dienst auf einem Server anzusprechen, wird die Adresse des Servers um den Port ergänzt (für Webserver standardmäßig Port 80).</para>
</section>
<section><section-header>Client</section-header>
<para>Als Client wird ein Computer bezeichnet, der sich mit einem Server in Verbindung setzt. Im Falle des Internet ist ein Client bspw. ein Browser, der WWW-Inhalte abruft, oder ein Emailprogramm, welches Postfächer über POP/IMAP abrufen kann.</para>
</section>
<section><section-header>Topologie von Clients und Servern</section-header>
</section>
<section><section-header>TCP/IP</section-header>
<para>Das Transmission Control Protocol über Internet Protocol definiert, auf welcher Weise Computersysteme kommunizieren. Das Protokoll ist paketorientiert, was bedeutet, das die gesendeten Daten u.U. in kleinere Päckchen aufgeteilt versendet werden. Die einzelnen Pakete können unterschiedliche Wege vom Sender zum Empfänger zurücklegen, wobei der Empfänger Sorge tragen muss, das die ursprüngliche Nachricht wieder zusammengesetzt werden kann und evtl. fehlende oder fehlerhafte Pakete neu anfordern.</para>
<para>Neben HTTP sind FTP, SMTP, POP, IMAP, LDAP und Telnet geläufige aufsetzende Protokolle.</para>
<para>IP definiert die Adressierung der Pakete (aktuell IPv4, IPv6 steht kurz vor Einführung). IP-Pakete enthalten die Informationen der übergeordneten Dienste als Payload und können somit als Briefumschlag angesehen werden.</para>
<para>Eine IP-Adresse besteht aus vier Bytes. Um die Adressen für den Menschen lesbar zu gestalten hat man Domain-Namen eingeführt, die jedoch von DNS-(Domain Name-Server) wieder in normale IP-Adressen übersetzt werden.</para>
<table>
<tr>
<th></th>
<th><para>Protokoll-Schicht</para>
</th>
<th><para>Übliche Protokolle</para>
</th>
<th></th>
</tr>
<tr>
<td><para>5</para>
</td>
<td><para>Verarbeitung</para>
</td>
<td><para>Telnet, FTP, SMTP, NNTP, HTTP, POP, IMAP</para>
</td>
<td><para>TCP/IP-Implementation</para>
</td>
</tr>
<tr>
<td><para>4</para>
</td>
<td><para>Transport</para>
</td>
<td><para>TCP, UDP</para>
</td>
</tr>
<tr>
<td><para>3</para>
</td>
<td><para>Vermittlung</para>
</td>
<td><para>IP, ARP, ICMP</para>
</td>
</tr>
<tr>
<td><para>2</para>
</td>
<td><para>Sicherung</para>
</td>
<td><para>Adapter-Karten</para>
</td>
<td><para>Netzwerk</para>
</td>
</tr>
<tr>
<td><para>1</para>
</td>
<td><para>Bitübertragung</para>
</td>
<td><para>Leitungen, Elektronik</para>
</td>
</tr>
<label>Tabelle 9: Ebenen der Übermittlung von Daten</label>
</table>
</section>
<section><section-header>URL</section-header>
<para>Über die URI (Uniform Resource Identifier) werden Inhalte im Internet adressiert. Sie ist entweder eine URL (Uniform Resource Locator) oder eine URN (Uniform Resource Name). Dabei gibt die URL das Zugriffsprotokoll und den Ort im Internet an, woher die Informationen abgerufen werden sollen. Die URN ist andererseits ein eindeutiger Bezeichner eines Objekts an einer beliebigen Stelle im Internet (seine Verwendung hat sich bisher nicht durchsetzen können).</para>
<code>
<label>Beispiel 69: Anfrage über die Adress-Zeile eines Browsers</label>
<codeline>http://www.google.com/ </codeline>
<codeline>http://www.google.com/index.html </codeline>
<codeline>http://www.google.com:80/ </codeline>
<codeline>http://209.185.108.220:80/ </codeline>
<codeline>http://209.185.108.220/ </codeline>
</code>
<para>Sämtliche angegebenen Adressen landen geben die selbe HTML-Seite zurück.</para>
<para>Aufbau einer URL:</para>
<code>
<codeline>http://&lt;host&gt;:&lt;port&gt;/&lt;path&gt;?&lt;searchpart&gt; </codeline>
<codeline>http://&lt;host&gt;		Voll qualifizierter Rechnername oder IP-Adresse mit vorangestellter Protokollangabe </codeline>
<codeline>:&lt;port&gt;			(optional) Default-Port ist 80 </codeline>
<codeline>/&lt;path&gt;		(optional) Dokument-Pfad, Adressierung eines Dokuments am Server, default: index.html (wird in den Einstellungen des Webservers geregelt) </codeline>
</code>
<para>?&lt;searchpart&gt;  (optional): Query-String</para>
<para>Hinweis: Innerhalb von &lt;path&gt; und &lt;searchpart&gt; haben die Zeichen / ; ? eine Sonderbedeutung.</para>
</section>
<section><section-header>HTTP</section-header>
<para>Das auf TCP/IP aufsetzende Hypertext Transport Protokoll beschreibt, wie ein Webbrowser Dokumente anfordern kann und wie der Webserver darauf antworten kann. Es ist ein sogenanntes zustandsloses Protokoll (Idempotenz), was bedeutet, das die Verbindung nicht ständig aufrechterhalten, sonder nach Übermittlung der Informationen wieder getrennt wird.</para>
<code>
<label>Beispiel 70: Request über HTTP</label>
<codeline>GET /index.html HTTP/1.0 </codeline>
<codeline>User-Agent: MeinBrowser </codeline>
<codeline>Host: www.google.com </codeline>
<codeline> </codeline>
</code>
<para>In der ersten Zeile steht die HTTP Methode, gefolgt vom Dokumentnamen und der HTTP-Version. In den folgenden Zeilen steht der Request-Header mit Header-Field/-Value-Paaren. Der Request wird mit einer Leerzeile abgeschlossen.</para>
<code>
<label>Beispiel 71: Response Webservers</label>
<codeline>HTTP/1.1 200 OK </codeline>
<codeline>Date: Sat, 37 May 2001 10:12:53 GMT </codeline>
<codeline>Server: Apache/2.4.1 S.u.S.E./7 </codeline>
<codeline>Last-Modified: Thu, 21 May 2000 19:19:48 GMT </codeline>
<codeline>Content-Length: 1100 </codeline>
<codeline>Content-Type: text/html </codeline>
<codeline> </codeline>
<codeline>&lt;HTML&gt; </codeline>
<codeline>... </codeline>
<codeline>&lt;/HTML&gt; </codeline>
</code>
<para>Die Response beginnt mit der HTTP-Protokollversion und dem Statuscode des Servers. Ihm folgen weitere Reply-Header-Felder. Danach, mittels einer Leerzeile getrennt, folgt der Body der Nachricht.</para>
<section>
<section-header>Methoden einer HTTP-Anfrage</section-header>
<table>
<tr>
<th><para>Methode</para>
</th>
<th><para>Verwendung</para>
</th>
</tr>
<tr>
<td><para>GET</para>
</td>
<td><para>Abholen von Informationen</para>
</td>
</tr>
<tr>
<td><para>HEAD</para>
</td>
<td><para>Abholen von Headerinformationen</para>
</td>
</tr>
<tr>
<td><para>POST</para>
</td>
<td><para>Versenden von Informationen an den Server</para>
</td>
</tr>
<tr>
<td><para>PUT, DELETE, LINK, UNLINK</para>
</td>
<td><para>fast nie verwendet, nicht für HTTP 1.0 notwendig</para>
</td>
</tr>
<label>Tabelle 10: Methoden einer HTTP-Anfrage</label>
</table>
</section>
<section><section-header>HTTP-Statusmeldungen des Servers</section-header>
<table>
<tr>
<th><para>Statuscodebereich</para>
</th>
<th><para>Beispielcode</para>
</th>
<th><para>Bedeutung</para>
</th>
</tr>
<tr>
<td><para>100-199</para>
</td>
<td></td>
<td><para>Informationen, Hinweise</para>
</td>
</tr>
<tr>
<td><para>200-299</para>
</td>
<td></td>
<td><para>Clientanfrage erfolgreich verarbeitet</para>
</td>
</tr>
<tr>
<td></td>
<td><para>200</para>
</td>
<td><para>Die Operation wurde erfolgreich ausgeführt</para>
</td>
</tr>
<tr>
<td></td>
<td><para>201</para>
</td>
<td><para>Eine Ressource wurde erzeugt (PUT)</para>
</td>
</tr>
<tr>
<td><para>300-399</para>
</td>
<td></td>
<td><para>Clientanfrage wurde umgeleitet. Der Client muss weitere Aktionen veranlassen, um den Requerst zu vervollständigen</para>
</td>
</tr>
<tr>
<td></td>
<td><para>300</para>
</td>
<td><para>Multiple Choise</para>
</td>
</tr>
<tr>
<td></td>
<td><para>302</para>
</td>
<td><para>Moved Temporarily</para>
</td>
</tr>
<tr>
<td></td>
<td><para>304</para>
</td>
<td><para>Not Modified</para>
</td>
</tr>
<tr>
<td><para>400-499</para>
</td>
<td></td>
<td><para>Clientanfrage unvollständig, bzw. es liegt ein Fehler in der Anfrage vor</para>
</td>
</tr>
<tr>
<td></td>
<td><para>400</para>
</td>
<td><para>Bad Request</para>
</td>
</tr>
<tr>
<td></td>
<td><para>401</para>
</td>
<td><para>Unauthorized</para>
</td>
</tr>
<tr>
<td></td>
<td><para>402</para>
</td>
<td><para>Payment Required (future use)</para>
</td>
</tr>
<tr>
<td></td>
<td><para>403</para>
</td>
<td><para>Forbidden</para>
</td>
</tr>
<tr>
<td></td>
<td><para>404</para>
</td>
<td><para>Not Found</para>
</td>
</tr>
<tr>
<td><para>500-599</para>
</td>
<td></td>
<td><para>Server-Fehler</para>
</td>
</tr>
<tr>
<td></td>
<td><para>500</para>
</td>
<td><para>Internal Server Error</para>
</td>
</tr>
<tr>
<td></td>
<td><para>503</para>
</td>
<td><para>Service Unavailable</para>
</td>
</tr>
<label>Tabelle 11: HTTP-Statusmeldungen des Servers</label>
</table>
</section>
<section><section-header>Header-Felder</section-header>
<ul><para><li>
Allgemeine Header</li>
</para>
</ul><para>Connection (Close, Keep Alive), Date (Zeit und Datum), MIME-Version, Transfer-Encoding, diverse Cache Optionen</para>
<ul><para><li>
Client Anfragen</li>
</para>
</ul><para>Accept (type/subtype), MIME-Types die angenommen werden, Authorization, Cookies, If-Modified-Since (date), Referer (url), User-Agent, Host (hostname:port), diverse Cache und Match Optionen</para>
<ul><para><li>
Server Antworten</li>
</para>
</ul><para>Retry-After (date|seconds), Server, Set-Cookie, WWW-Authenticate, Inhaltsangaben, Content-Type (mimetype), Content-Length, Content-Encoding (scheme), Content-Transfer-Encoding (scheme), Content-Language, Expires (date), Last-Modified (date), Location (url)</para>
<table>
<tr>
<th><para>Typ/Subtyp</para>
</th>
<th><para>Datei-Erweiterung</para>
</th>
<th><para>Datei-Typ</para>
</th>
</tr>
<tr>
<td><para>application/pdf</para>
</td>
<td><para>pdf</para>
</td>
<td><para>Adobe Portable Document Format</para>
</td>
</tr>
<tr>
<td><para>application/ps</para>
</td>
<td><para>eps, ps</para>
</td>
<td><para>PostScript</para>
</td>
</tr>
<tr>
<td><para>application/x-tar</para>
</td>
<td><para>tar</para>
</td>
<td><para>&quot;Tape-Archive&quot;</para>
</td>
</tr>
<tr>
<td><para>audio/basic</para>
</td>
<td><para>au, snd</para>
</td>
<td><para>Audioformate</para>
</td>
</tr>
<tr>
<td><para>image/jpeg</para>
</td>
<td><para>jpg, jpeg</para>
</td>
<td><para>Graphikformat</para>
</td>
</tr>
<tr>
<td><para>image/gif</para>
</td>
<td><para>gif</para>
</td>
<td><para>Graphikformat</para>
</td>
</tr>
<tr>
<td><para>image/tiff</para>
</td>
<td><para>tiff, tif</para>
</td>
<td><para>Graphikformat</para>
</td>
</tr>
<tr>
<td><para>text/html</para>
</td>
<td><para>html, htm</para>
</td>
<td><para>HTML-Datei</para>
</td>
</tr>
<tr>
<td><para>text/plain</para>
</td>
<td><para>txt</para>
</td>
<td><para>ASCII-Datei</para>
</td>
</tr>
<label>Tabelle 12: Einige MIME (Multipurpose Internet Mail Extensions)-Typen</label>
</table>
</section>
</section>
</section>
<section><section-header>HTML, XHTML, DHTML</section-header>
<para>Hier wird lediglich ein kurzer Abriß von HTML geboten. Für weiterführende Informationen bietet sich selfHTML von TeamOne an (siehe Quellen).</para>
<para>Wie XML stammt HTML ab von SGML. Der Inhalt einer HTML-Datei ist denn auch ähnlich aufgebaut wie eine XML-Datei, allerdings werden Vorschriften, die eine XML-Datei als wohlgeformt auszeichnen nicht konsequent umgesetzt.</para>
<para>HTML läßt sich nicht wie XML erweitern; die Elemente sind vorgegeben.</para>
<para>Gegenüber XML ist es möglich, geöffnete Elemente nicht wieder zu schließen und auch eine nicht korrekte Verschachtelung wird akzeptiert. HTML-Markup ist nicht Case-Sensitive (ausgenommen sind Verweise auf Ressourcen). Attribute müssen nicht zwangsläufig in Hochkommata eingeschlossen sein.</para>
<para>Darüber hinaus gibt es einige herstellerabhängige Erweiterungen der eigentlichen HTML-Spezifikation, die Inkompatibilitäten hervorrufen. Und außerdem werden manche Elemente von verschiedenen Browsern unterschiedlich interpretiert und dargestellt.</para>
<para>Aus diesem Grund findet sich auf vielen Webseiten der Hinweis, die Inhalte seien für einen bestimmten Browser (und einer Mindestversion) optimiert (womöglich auch noch für eine spezifische Bildschirmauflösung). Damit deutet der Autor an, er habe zumindest bei diesem Browser geprüft, ob die Darstellung mit seiner Idee übereinstimmt (für die anderen war er zu faul).</para>
<para>Die Verwendung von WYSIWYG-Editoren ist weit verbreitet. Allerdings ist der Produzierte HTML-Code alles andere als übersichtlich und außerdem nicht gerade schlank. Häufig produzieren sie gewagte und tiefverschachtelte Tabellenkonstruktionen um die Seitenelemente zu positionieren.</para>
<para>Zudem verewigen sich solche Editoren gerne in den meta-Tags. Die nachträgliche, manuelle Bearbeitung ist dementsprechend fast unmöglich - und risikoreich, da nach einem Neuladen in der Anwendung diese den &apos;fehlerhaften&apos; (da nicht von ihm selbst produzierten) Code gerne auch korrigiert (und überschreibt).</para>
<para>Meine Empfehlung lautet daher, HTML in einfachen Texteditoren zu entwerfen und in verschiedenen, gängigen Browsern (aber nicht die neuesten Versionen) zu testen. Mittlerweile dürfte sich der Netscape Navigator der 4.7x-Reihe überlebt haben, so dass ich die zu testenden Plattformen als Microsoft Internet Explorer ab 5.0 (Priorität auf IE5, da der IE ab 5.0 insgesamt über 80% der Internetbenutzer diese Browser einsetzen), ergänzt durch Netscape Navigator 6, Opera 5 und Mozilla 1.x zusammenfassen würde.</para>
<para>Die in diesem Scriptum verwendete Syntax wird dabei XHTML sein, da diese XML-konform ist: Das bedeutet, das auch hier die XML-Regeln für wohlgeformte Dokumente zur Anwendung kommt.</para>
<code>
<label>Beispiel 72: HTML-Code der Index-Seite vanderkruijs.net</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; </codeline>
<codeline> 		&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt; </codeline>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt; </codeline>
<codeline>	&lt;meta name=&quot;robots&quot; content=&quot;index&quot;/&gt; </codeline>
<codeline>	&lt;meta name=&quot;robots&quot; content=&quot;follow&quot;/&gt; </codeline>
<codeline>	&lt;meta name=&quot;distribution&quot; content=&quot;global&quot;/&gt; </codeline>
<codeline>	&lt;meta name=&quot;robots&quot; content=&quot;all&quot;/&gt; </codeline>
<codeline>	&lt;link rel=&quot;shortcut icon&quot; href=&quot;img/vanderkruijs.ico&quot; </codeline>
<codeline>														type=&quot;image/x-icon&quot;/&gt; </codeline>
<codeline>	&lt;link rel=&quot;STYLESHEET&quot; type=&quot;text/css&quot; href=&quot;style.css&quot;/&gt; </codeline>
<codeline>	&lt;meta http-equiv=&quot;Content-Type&quot;  </codeline>
<codeline>								content=&quot;text/html; charset=ISO-8859-1&quot;/&gt; </codeline>
<codeline>	&lt;title&gt;Constantinus van der Kruijs&lt;/title&gt; </codeline>
<codeline>&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>	&lt;div class=&quot;header&quot;&gt; </codeline>
<codeline>		&lt;h1 style=&quot;margin:4px&quot;&gt;Constantinus van der Kruijs&lt;/h1&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>	&lt;div class=&quot;menu&quot; style=&quot;left: 1.5%; width: 15%; top: 50px&quot;&gt; </codeline>
<codeline>		&lt;!-- dynamischer inhalt --&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>	&lt;div class=&quot;menu&quot; </codeline>
<codeline>			style=&quot;left: 80%; top: 0px; background: transparent;&quot;&gt; </codeline>
<codeline>		&lt;table align=&quot;center&quot;&gt;&lt;tr&gt; </codeline>
<codeline>			&lt;!-- dynamischer inhalt --&gt; </codeline>
<codeline>		&lt;/tr&gt;&lt;/table&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>	&lt;div class=&quot;main&quot; style=&quot;left: 20%; width: 75%;&quot;&gt; </codeline>
<codeline>		&lt;!-- dynamischer inhalt --&gt; </codeline>
<codeline>		&lt;div class=&quot;footer&quot;&gt; </codeline>
<codeline>			&amp;copy; 2002-2003 C. van der Kruijs  </codeline>
<codeline>			&lt;a href=&quot;http://www.vanderkruijs.net&quot;&gt; </codeline>
<codeline>				www.vanderkruijs.net </codeline>
<codeline>			&lt;/a&gt; </codeline>
<codeline>			e-Mail: </codeline>
<codeline>			&lt;a href=&quot;mailto:info@vanderkruijs.net&quot;&gt; </codeline>
<codeline>				info@vanderkruijs.net </codeline>
<codeline>			&lt;/a&gt; </codeline>
<codeline>			Quick-Links: </codeline>
<codeline>			&lt;!-- dynamischer inhalt --&gt; </codeline>
<codeline>		&lt;/div&gt; </codeline>
<codeline>	&lt;/div&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<section>
<section-header>Dokumentenaufbau</section-header>
<para>Es hat sich durchgesetzt, das Browser versuchen, auch nicht HTML-konformen (also prinzipiell ungültiges HTML) Code darzustellen. Dieser Umstand verleitet dazu, nicht durchgängig auf die Korrektheit des verfaßten Codes zu achten.</para>
<para>Da bereits mit XML gearbeitet wurde, wird hier die XHTML-Variante benutzt. Das führt dazu, das der produzierte HTML-Code XML-konform sein muss; also ein wohlgeformtes und gültiges XML-Dokument darstellt.</para>
<para>Demnach beginnen XHTML-Dokumente mit der XML-Deklaration und einer Dokumenttypdefinition nach XML-Vorbild. Sämtliche Inhalte sind im Top-Level-Element html gekapselt.</para>
<para>Der HTML-Inhalt eines Dokuments gliedert sich in zwei Teile: Header und Body. Innerhalb des Headers finden Informationen ihren Platz, die das Dokument und dessen Inhalt näher spezifizieren (wichtig u.a. für Suchmaschinen-Roboter um die Seite zu indizieren). Im Body findet sich der im Browser dargestellte Inhalt wieder.</para>
</section>
<section><section-header>Wesentliche Elemente der HTML-Syntax</section-header>
<table>
<tr>
<th><para>Element</para>
</th>
<th><para>Bedeutung</para>
</th>
<th><para>Inhalte</para>
</th>
</tr>
<tr>
<td><para>html</para>
</td>
<td><para>SGML Anwendung</para>
</td>
<td><para>head body</para>
</td>
</tr>
<tr>
<td><para>head</para>
</td>
<td><para>Kopfinformationen</para>
</td>
<td><para>title (script | style | meta | link)+</para>
</td>
</tr>
<tr>
<td><para>body</para>
</td>
<td><para>eigentlicher HTML Teil</para>
</td>
<td><para>alles ohne Kopfelemente</para>
</td>
</tr>
<tr>
<td><para>title</para>
</td>
<td><para>Titel, Inhaltsbezeichnung</para>
</td>
<td><para>Text</para>
</td>
</tr>
<tr>
<td><para>h1, ..., h6</para>
</td>
<td><para>Überschriften</para>
</td>
<td><para>Text</para>
</td>
</tr>
<tr>
<td><para>a</para>
</td>
<td><para>Verweis, Link, Anker</para>
</td>
<td><para>Linktext etc.</para>
</td>
</tr>
<tr>
<td><para>p</para>
</td>
<td><para>Paragraph</para>
</td>
<td><para>alles ohne Block-Elemente</para>
</td>
</tr>
<tr>
<td><para>ul, ol</para>
</td>
<td><para>Listen: nicht-numeriert, numeriert</para>
</td>
<td><para>li+</para>
</td>
</tr>
<tr>
<td><para>li</para>
</td>
<td><para>Listenelement</para>
</td>
<td><para>alles mit Ausnahmen</para>
</td>
</tr>
<tr>
<td><para>img</para>
</td>
<td><para>Bild im Text</para>
</td>
<td><para>empty</para>
</td>
</tr>
<tr>
<td><para>pre</para>
</td>
<td><para>vorformatierter Text</para>
</td>
<td><para>Text</para>
</td>
</tr>
<tr>
<td><para>br</para>
</td>
<td><para>Zeilenumbruch</para>
</td>
<td><para>empty</para>
</td>
</tr>
<tr>
<td><para>em, strong, code</para>
</td>
<td><para>Betonung, Hervorhebung, Auszeichnung</para>
</td>
<td><para>Text</para>
</td>
</tr>
<tr>
<td><para>blockquote, q</para>
</td>
<td><para>Einrückung</para>
</td>
<td><para>Text</para>
</td>
</tr>
<tr>
<td><para>table</para>
</td>
<td><para>Tabelle</para>
</td>
<td><para>tr+</para>
</td>
</tr>
<tr>
<td><para>tr</para>
</td>
<td><para>Tabellenzeile</para>
</td>
<td><para>(td|th)+</para>
</td>
</tr>
<tr>
<td><para>td, th</para>
</td>
<td><para>Tabellenzelle, Tabellen-Headerzelle</para>
</td>
<td><para>alles mit Ausnahmen</para>
</td>
</tr>
<tr>
<td><para>hr</para>
</td>
<td><para>Horizontale Linie</para>
</td>
<td><para>empty</para>
</td>
</tr>
<label>Tabelle 13: Unvollständige Auswahl von HTML-Markup</label>
</table>
<para>Auf formatierende Elemente (als da währen: font, b für bold, i für italic, u für underlined, s für stroke, big für größer, blink/marquee für blinkend/Laufschrift: proprietär) wird hier weitestgehend verzichtet, da das Layout an einer anderen Stelle definiert werden sollte um die Inhalte portabel zu gestalten.</para>
<para>Nahezu alle Elemente verfügen über anwendbare Attribute. Im Grunde gibt es allerdings nur wenige, dessen Nutzung im allgemeinen Sinn macht. Genannt seien hier: class für die Zuweisung einer CSS-Klasse und style für die Inline-Zuweisung von Stilattributen nach CSS-Syntax. Wichtig sind auch id bzw. name, wenn man innerhalb des DHTML/JavaScript auf die Elemente zugreifen möchte.</para>
</section>
<section><section-header>Tabellen</section-header>
<para>Genutzt werden Tabellen in HTML-Seiten und einerseits Daten in einer tabellarischen Form darzustellen. Andererseits leisten Tabellen aber auch große Dienste dabei, das Layout einer Seite gestalten zu können. Über das Für und Wider dieser Methode der Seitengestaltung läßt sich streiten, allerdings sollte man, soweit es geht, auf Tabellen zur Einteilung der Seite verzichten, und statt dessen lieber auf die Funktionalität von CSS zurückgreifen.</para>
<para>Das Erzeugen von Tabellen ist in HTML mittels drei Elementen gelöst. Zunächst wird der table-Tag benutzt um die Tabelle zu begrenzen. In ihm werden die Zellen zeilenweise eingetragen. Daher sind innerhalb des table-Tags nur tr-Tags zugelassen (optional jedoch auch caption). Innerhalb der Zeilen werden dann die eigentlichen Zellen mittels td ausgezeichnet. Zu den drei genannten gesellen sich noch zwei weitere Elemente, die optional in einer Tabelle zum Einsatz kommen: caption für eine Beschriftung der gesamten Tabelle und th als alternatives Element für td als Spaltenüberschriftszelle.</para>
<code>
<label>Beispiel 73: HTML-Tabellenquelltext</label>
<codeline>&lt;table&gt; </codeline>
<codeline>&lt;caption&gt;Gitternetz-Tabelle&lt;/caption&gt; </codeline>
<codeline>&lt;tr&gt; </codeline>
<codeline>	&lt;th&gt;Spalte 1&lt;/th&gt; </codeline>
<codeline>	&lt;th&gt;Spalte 2&lt;/th&gt; </codeline>
<codeline>	&lt;th&gt;Spalte 3&lt;/th&gt; </codeline>
<codeline>&lt;/tr&gt;&lt;tr&gt; </codeline>
<codeline>	&lt;td&gt; &lt;/td&gt; </codeline>
<codeline>	&lt;td&gt;Zeile 1; Zelle 2&lt;/td&gt; </codeline>
<codeline>	&lt;td&gt;Zeile 1; Zelle 3&lt;/td&gt; </codeline>
<codeline>&lt;/tr&gt;&lt;tr&gt; </codeline>
<codeline>	&lt;td rowspan=&quot;2&quot;&gt;Zelle über zwei Zeilen&lt;/td&gt; </codeline>
<codeline>	&lt;td colspan=&quot;2&quot;&gt;Zelle über zwei Spalten&lt;/td&gt; </codeline>
<codeline>&lt;/tr&gt;&lt;tr&gt; </codeline>
<codeline>	&lt;td&gt;Zeile 3; Zelle 2&lt;/td&gt; </codeline>
<codeline>	&lt;td&gt;Zeile 3; Zelle 3&lt;/td&gt; </codeline>
<codeline>&lt;/tr&gt; </codeline>
<codeline>&lt;/table&gt; </codeline>
</code>
<para>Gitternetz-Tabelle</para>
<table>
<tr>
<th><para>Spalte 1</para>
</th>
<th><para>Spalte 2</para>
</th>
<th><para>Spalte 3</para>
</th>
</tr>
<tr>
<td><para>Zeile 1; Zelle 1</para>
</td>
<td><para>Zeile 1; Zelle 2</para>
</td>
<td><para>Zeile 1; Zelle 3</para>
</td>
</tr>
<tr>
<td><para>Zelle über zwei Zeilen</para>
</td>
<td><para>Zelle über zwei Spalten</para>
</td>
</tr>
<tr>
<td><para>Zeile 3; Zelle 2</para>
</td>
<td><para>Zeile 3; Zelle 3</para>
</td>
</tr>
</table>
<para>Aus einer HTML-Seite heraus kann auf weitere Ressourcen verknüpft werden. Diese fremden Inhalte können zum einen in der Seite eingebunden werden, zum anderen als Sprungziel fungieren.</para>
<para>Sollen Inhalte in der Seite selbst verwendet oder dargestellt werden, wird das Attribut src (bei Grafiken in einem img-Tag)  oder rel  (bei einem link-Tag im Header) verwendet, um die Datenquelle anzugeben.</para>
<para>Darüber hinaus können auch Multimediainhalte wie Audio oder Video in einer Seite eingebettet werden. Allerdings werden nicht sehr viele solcher Datenformate unterstützt und in vielen Fällen muss auf Plugins zurückgegriffen werden, die die Wiedergabe erst ermöglichen.</para>
<para>Die Quelle wird in beiden Fällen als URI angegeben, die entweder absolut, oder aber auch relativ (zur Seite selbst) angegeben werden kann.</para>
<para>Eine Sprungmarke (a-Tag) verweist auf Inhalte an einem anderen Ort (innerhalb oder außerhalb der aktuellen Seite). Über das href-Attribut wird spezifiziert wohin gelinkt wird; möglich sind andere Dateien, die daraufhin geladen werden, oder benannte Sprungmarken innerhalb der selben Seite (diese werden auch mittels eines a-Tags definiert, allerdings versehen mit einem name-Attribut, welches wiederum im href-Attribut der verweisenden Verknüpfung verwendet wird).</para>
<code>
<label>Beispiel 75: Links</label>
<codeline>&lt;img src=&quot;meindolleslogo.jpg&quot;/&gt; </codeline>
<codeline>&lt;a href=&quot;impressum.html&quot; title=&quot;wissenswert&quot;&gt;Impressum&lt;/a&gt; </codeline>
<codeline>&lt;a href=&quot;http://www.google.de&quot;&gt;Hier kann gesucht werden&lt;/a&gt; </codeline>
<codeline>&lt;a name=&quot;top&quot;/&gt; </codeline>
<codeline>&lt;a href=&quot;#top&quot;&gt; </codeline>
<codeline>&lt;embed src=&quot;hintergrundlala.mid&quot; autostart=&quot;true&quot;/&gt; </codeline>
<codeline>&lt;link rel=&quot;STYLESHEET&quot; type=&quot;text/css&quot; href=&quot;style.css&quot;/&gt; </codeline>
<codeline>&lt;a href=&quot;gross.jpg&quot;&gt;&lt;img src=&quot;klein.jpg&quot;/&gt;&lt;/a&gt; </codeline>
</code>
</section>
<section><section-header>Frames</section-header>
<para>Mittels Frames kann das Browserfenster beliebig in unabhängige Bereiche unterteilt werden, die jeweils eine Resource darstellen können. Häufig wird diese Technik angewendet, um eine Navigationsstruktur unabhängig der gewählten Inhalte darstellen zu können.</para>
<para>Setzt man Frames ein, sollte man sich über folgendes im Klaren sein:</para>
<para>Es kann immer auf Seiten gelinkt werden, die in einem der Frames erscheinen. Damit bekommt jemand, der diesem Link folgt, in seinem Browser nicht das komplette Frameset angezeigt, sondern eben nur diese Seite. Unter Umständen kann er dann die weiteren Inhalte der Homepage nicht mehr erreichen.</para>
<para>Es kann passieren, das Suchmaschinen sich nicht die Mühe machen, die einzelnen Seiten des Framesets zu durchsuchen.</para>
<para>Ältere Browser (oder Textbrowser) können Frames nicht darstellen.</para>
<code>
<label>Beispiel 76: Eine Frameseite</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Frameset//EN&quot; </codeline>
<codeline>     &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd&quot;&gt; </codeline>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt;&lt;title&gt;Framesets&lt;/title&gt;&lt;/head&gt; </codeline>
<codeline>&lt;frameset cols=&quot;100px,*&quot; border=&quot;1&quot; frameborder=&quot;yes&quot;&gt; </codeline>
<codeline>	&lt;frame src=&quot;navi.html&quot; noresize=&quot;true&quot; name=&quot;frmNavi&quot;/&gt; </codeline>
<codeline>	&lt;frame src=&quot;main.html&quot; name=&quot;frmMain&quot;/&gt; </codeline>
<codeline>&lt;/frameset&gt; </codeline>
<codeline>&lt;noframes&gt; </codeline>
<codeline>	Ihr Browser unterstützt keine Frames </codeline>
<codeline>&lt;/noframes&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
</section>
<section><section-header>Client-Seitiges Scripting</section-header>
<para>HTML kann neben der Auszeichnungssyntax komplette Programme zum Browser transportieren, die dann dort zur Ausführung kommen (falls der Browser dies zuläßt). Am meisten Verbreitung hat sicherlich JavaScript gefunden. In diesem Zusammenhang fällt wird häufig der Begriff DHTML genannt. DHTML bildet dabei die Schnittstelle zwischen HTML, CSS und einem Document Object Model (DOM). Das DOM erlaubt JavaScript den Zugriff auf Objekte innerhalb einer HTML-Seite um diese bzw. ihr Attribute zu verändern, hieraus ergibt sich Dynamisches HTML.</para>
<code>
<label>Beispiel 77: HTML-Seite mit eingebundenem Client-Script</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; </codeline>
<codeline> 		&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt; </codeline>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt; </codeline>
<codeline>	&lt;title&gt;Text des Titels&lt;/title&gt; </codeline>
<codeline>	&lt;script type=&quot;text/javascript&quot;&gt; </codeline>
<codeline>&lt;!-- </codeline>
<codeline>function Zeit() { </codeline>
<codeline> var Jetzt = new Date(); </codeline>
<codeline> var Tag = Jetzt.getDate(); </codeline>
<codeline> var Monat = Jetzt.getMonth() + 1; </codeline>
<codeline> var Jahr = Jetzt.getYear(); </codeline>
<codeline> if(Jahr &lt; 999) Jahr += 1900; </codeline>
<codeline> var Vortag  = ((Tag &lt; 10) ? &quot;0&quot; : &quot;&quot;); </codeline>
<codeline> var Vormon  = ((Monat &lt; 10) ? &quot;.0&quot; : &quot;.&quot;); </codeline>
<codeline> var Datum = Vortag + Tag + Vormon + Monat  + &quot;.&quot; + Jahr; </codeline>
<codeline> document.write(&quot;&lt;h1&gt;&quot; + Datum + &quot;&lt;\/h1&gt;&quot;) </codeline>
<codeline>} </codeline>
<codeline>//--&gt; </codeline>
<codeline>	&lt;/script&gt; </codeline>
<codeline>&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>	&lt;script type=&quot;text/javascript&quot;&gt; </codeline>
<codeline>&lt;!-- </codeline>
<codeline>Zeit(); </codeline>
<codeline>//--&gt; </codeline>
<codeline>&lt;/script&gt; </codeline>
<codeline>&lt;noscript&gt; </codeline>
<codeline>	&lt;h1&gt;Guten Tag!&lt;/h1&gt; </codeline>
<codeline>&lt;/noscript&gt; </codeline>
<codeline>&lt;p&gt;Aktuelle Nachrichten ...&lt;/p&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<para>In diesem Beispiel ist der Komplette JavaScript-Code im Dokument enthalten. Alternativ lassen sich Funktionen und Klassendefinitionen auch sehr gut in Dateien auslagern, die dann mittels eines link-Elements im head-Abschnitt der HTML-Seite eingebunden wird.</para>
<para>Der Einsatz von clientseitigen Skripten ist dann empfehlenswert, wenn auf Aktionen des Nutzers reagiert werden soll, ein Neuladen der Seite aber nicht erforderlich sein muss.</para>
<para>Skripte können auch zur Ausführung kommen, wenn auf Ereignisse reagiert wird, die von dargestellten Elementen ausgelöst werden. Dazu verfügen HTML-Elemente über folgende Attribute.</para>
<table>
<tr>
<th><para>Ereignis</para>
</th>
<th><para>Bedeutung</para>
</th>
</tr>
<tr>
<td><para>onLoad, onUnload</para>
</td>
<td><para>Aufruf beim Laden</para>
</td>
</tr>
<tr>
<td><para>OnChange</para>
</td>
<td><para>Aufruf bei änderungen</para>
</td>
</tr>
<tr>
<td><para>OnClick</para>
</td>
<td><para>Aufruf beim Anklicken</para>
</td>
</tr>
<tr>
<td><para>OnMouseOver</para>
</td>
<td><para>Maus über dem Element</para>
</td>
</tr>
<tr>
<td><para>OnMouseOut</para>
</td>
<td><para>Maus verläßt Element</para>
</td>
</tr>
<tr>
<td><para>OnSelect</para>
</td>
<td><para>bei Auswahl</para>
</td>
</tr>
<tr>
<td><para>OnSubmit</para>
</td>
<td><para>beim Versenden</para>
</td>
</tr>
<label>Tabelle 14: Script-Ereignisse von HTML-Elementen</label>
</table>
<para>Das folgende Beispiel zeigt, wie über eine Listenauswahl die Seite gewechselt werden kann. Vorausgesetzt, das Skript ist auf jeder Seite vorhanden, bietet es eine geschickte Navigationshilfe.</para>
<code>
<label>Beispiel 78: Seitennavigation mittels onChange</label>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; </codeline>
<codeline> 		&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt; </codeline>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt; </codeline>
<codeline>	&lt;title&gt;Test&lt;/title&gt; </codeline>
<codeline>	&lt;script type=&quot;text/javascript&quot;&gt; </codeline>
<codeline>&lt;!-- </codeline>
<codeline>funcion Go(x) { </codeline>
<codeline>	if(x != &quot;&quot;) { </codeline>
<codeline>		document.location.href = x; </codeline>
<codeline>	} </codeline>
<codeline>//--&gt; </codeline>
<codeline>	&lt;/script&gt; </codeline>
<codeline>&lt;/head&gt; </codeline>
<codeline>&lt;body bgcolor=&quot;#EEEEEE&quot;&gt; </codeline>
<codeline>	&lt;form action=&quot;&quot;&gt; </codeline>
<codeline>		&lt;select size=&quot;1&quot; name=&quot;Auswahl&quot; </codeline>
<codeline>					onChange=&quot;Go(this.form.Auswahl.options[ </codeline>
<codeline>							this.form.Auswahl.options.selectedIndex </codeline>
<codeline>							].value)&quot; </codeline>
<codeline>			width=&quot;250&quot;&gt; </codeline>
<codeline>				&lt;option value=&quot;&quot;&gt;[ bitte auswählen! ]&lt;/option&gt; </codeline>
<codeline>				&lt;option value=&quot;&quot;&gt;--------------------&lt;/option&gt; </codeline>
<codeline>				&lt;option value=&quot;zieldatei1.htm&quot;&gt; </codeline>
<codeline>					Ziel 1 </codeline>
<codeline>				&lt;/option&gt; </codeline>
<codeline>				&lt;option value=&quot;zieldatei2.htm&quot;&gt; </codeline>
<codeline>					Ziel 2 </codeline>
<codeline>				&lt;/option&gt; </codeline>
<codeline>		&lt;/select&gt; </codeline>
<codeline>	&lt;/form&gt; </codeline>
<codeline>	&lt;!-- Weiterer Seiteninhalt --&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
</section>
<section><section-header>CSS</section-header>
<para>Um eine bessere Trennung von Inhalten und Layout umsetzen zu können wurde CSS (Cascading Style Sheets) entworfen. Sie wird als Ergänzung zu HTML angesehen und folgt einer eigenen Syntax. Mittels CSS lassen sich sehr weitreichende Layoutvorgaben machen.</para>
<para>Auch wenn CSS 2 schon seit längerem existiert, wird es noch bei weitem nicht von allen Browsern vollständig bzw. richtig dargestellt. Ein umfangreiches Testen ist also angebracht.</para>
<para>Die CSS-Angaben können auf unterschiedlicher Weise in das Dokument gelangen.</para>
<code>
<label>Beispiel 79: CSS im link Element</label>
<codeline>&lt;link rel=&quot;STYLESHEET&quot; type=&quot;text/css&quot;  </codeline>
<codeline>							href=&quot;http://host/path/file.css&quot;&gt; </codeline>
</code>
<code>
<label>Beispiel 80: CSS im style-Element</label>
<codeline>&lt;style type=&quot;text/css&quot;&gt;   </codeline>
<codeline>h3 { color: lime } </codeline>
<codeline>&lt;/style&gt;   </codeline>
</code>
<code>
<label>Beispiel 81: CSS im style-Element mit @import:</label>
<codeline>&lt;style type=&quot;text/css&quot;&gt;   </codeline>
<codeline>@import url(http://style.org/company.css) </codeline>
<codeline>h1 { color: lime } </codeline>
<codeline>&lt;/style&gt; </codeline>
</code>
<code>
<label>Beispiel 82: CSS als Attribut</label>
<codeline>&lt;p style=&quot;color: red&quot; &gt; roter Text &lt;/p&gt;  </codeline>
</code>
<para>Empfehlenswert ist allerdings das Erzeugen und Verlinken einer zentralen CSS-Datei, da diese sehr einfach auf alle Seiten eines Projekts angewendet werden kann. Über das style-Attribut können beliebige Elemente auch vor Ort noch mit spezifischen CSS-Stilen versehen werden. Diese Style-Angaben im Elementattribut überschreiben die der HTML-Seite, die wiederum diejenigen in der externen Datei überschreiben.</para>
</section>
</section>
</section>
<section><section-header>Dynamischer Webcontent mit PHP</section-header>
<para>Die Verbreitung von PHP hat in den letzten Jahren sprunghaft zugenommen, obwohl, oder gerade deswegen, es niemals ein kommerzielles Produkt gewesen ist. Dass aber auch Open Source Software in geschäftskritischen Bereichen eingesetzt werden kann, dürfte seit Linux bekannt sein. Die Vorteile von Open Source liegen auf der Hand, der wichtigste Aspekt der zur weiten Verbreitung beigetragen haben dürfte, ist jedoch der Kostenfaktor.</para>
<para>Nichts destotrotz ist PHP mittlerweile ein ernst zu nehmendes Produkt, welches viel unterstützung auch von kommerziellen Unternehmen erhält. In den letzten Versionen wurde zudem das Thema Sicherheit zu einem zentralen Anliegen bei der Weiterentwicklung. Dies wird auch in den nächsten grösseren Releases so sein. Dabei geht man deutlich konsequenter vor als manch grosser, kommerzieller Anbieter, der sich eine Sicherheitsinitiative auf die Fahnen schreibt, und wirft auch bis dato akzeptierte Konzepte über Bord.</para>
<section>
<section-header>Geschichtliches</section-header>
<table>
<tr>
<th><para>Version</para>
</th>
<th><para>Anmerkungen</para>
</th>
</tr>
<tr>
<td><para>1</para>
</td>
<td><para>Ausgedacht im Herbst 1994 von Rasmus Lerdorf; Veröffentlichung im Frühling 1995 unter dem Namen Personal Home Page Tools</para>
</td>
</tr>
<tr>
<td><para>2</para>
</td>
<td><para>Mitte 1995 veröffentlicht als PHP/FI (Form Interpreter)</para>
<para>PHP wird OpenSource und als &quot;PHP Hypertext Preprocessor&quot; weiterentwickelt</para>
</td>
</tr>
<tr>
<td><para>3</para>
</td>
<td><para>1997 kompletter Rewrite</para>
</td>
</tr>
<tr>
<td><para>4</para>
</td>
<td><para>Mai 2000</para>
</td>
</tr>
<tr>
<td><para>5</para>
</td>
<td><para>.... irgendwann in der zweiten Hälfte von 2003 (wir hoffen es)</para>
</td>
</tr>
<label>Tabelle 15: Geschichtliche Entwicklung von PHP</label>
</table>
<para>Da PHP ein sogenanntes Open Source Projekt ist, sind an seiner Entwicklung sehr viele Leute in der ganzen Welt beteiligt. Die wesentlichen Köpfe hinter PHP sind unter anderen Zeev Suraski und Andi Gutsman, die eine Firma mit dem Namen Zend Technologies gegründet haben, die kommerzielle Produkte rund PHP entwickelt. Bei der Weiterentwicklung von PHP spielen sie zudem eine tragende Rolle.</para>
<para>Für Q3 2003 ist das Release der Version 5 von PHP anvisiert, doch darauf festlegen mochte sich Zeev Suraski nicht (nachzulesen unter http://www.zend.com/lists/php-dev/200301/msg00598.html). Derzeit sind bereits Betaversionen erhältlich; aber für den produktiven Einsatz sind diese nicht empfohlen.</para>
</section>
<section><section-header>Scripting-Methoden</section-header>
<para>Dynamik bedeutet in diesem Zusammenhang die Veränderlichkeit von Inhalten, also von Texten, Bildern, ganzen Seiten. Diese tiefen Eingriffe ist die Dokumentenstruktur läßt sich technisch nur auf dem Server umsetzen (Serverseitig).</para>
<para>Prinzipiell folgen bei einer Anfrage an den Server folgende Abläufe:</para>
<table>
<tr>
<th><para>Schritt</para>
</th>
<th><para>Aktion</para>
</th>
</tr>
<tr>
<td><para>1</para>
</td>
<td><para>Client (Browser) schickt die Anfrage an den Webserver</para>
</td>
</tr>
<tr>
<td><para>2</para>
</td>
<td><para>Webserver reicht Anfrage an Skriptsprache (zum Beispiel PHP) weiterr</para>
</td>
</tr>
<tr>
<td><para>3</para>
</td>
<td><para>PHP generiert eine Ausgabe (zum Beispiel HTML-Code)</para>
</td>
</tr>
<tr>
<td><para>4</para>
</td>
<td><para>Webserver schickt die Ausgabe an den Client</para>
</td>
</tr>
<tr>
<td><para>5</para>
</td>
<td><para>Client stellt die Ausgabe dar</para>
</td>
</tr>
<tr>
<td><para>6</para>
</td>
<td><para>Client beendet die Verbindung zum Webserver</para>
</td>
</tr>
<label>Tabelle 16: Prinzipieller Ablauf der Verarbeitung eines Client-Requests</label>
</table>
<para>Der Webserver wird dazu i.d.R. um Scriptingfunktionen erweitert, wie PHP, ASP oder JSP. Dabei kann die Scriptengine entweder als externe Servererweiterung vorliegen, oder im Webserver bereits als Modul integriert sein. Bei Ersterem wird bei einer entsprechenden Anfrage an der Webserver ein Prozeß der Scriptapplikation gestartet. Diese CGI-Technik ist weit verbreitet, beansprucht allerdings deutlich mehr Ressourcen auf dem Serversystem als die integrierte Lösung.</para>
<para>Der Server leitet allerdings nicht unbedingt alle Anfragen an die Skripterweiterung. Gesteuert wird dies durch die Zuordnung einer Dateierweiterung. Üblich bei der Verwendung von PHP ist die Dateierweiterung .php (früher .php3, noch früher .phtml). Allerdings kann prinzipiell jede Erweiterung mit PHP verknüpft werden, auch .html.</para>
</section>
<section><section-header>Ausführung</section-header>
<para>Die PHP-Engine funktioniert als sogenannter Interpreter. Dies bedeutet, das Codezeilen geparst werden und anschliessend zur Ausführung gebracht werden. Dies geschieht bei jedem Aufruf des Dokuments (sofern nicht zusätzlich kommerzielle Produkte eingesetzt werden).</para>
<para>Daher kann die Ausführung prinzipbedingt niemals so schnell sein, wie ein kompiliertes Programm. Die Programmstruktur von PHP läßt ein Kompilieren auch gar nicht ohne weiteres zu.</para>
<para>Mit Kompilaten wäre man zudem auch abhängig von der Serverplattform.</para>
</section>
</section>
<section><section-header>Anwendung von PHP</section-header>
<para>In diesem Scriptum wird die Verwendung von PHP in der Version 4.3.0 vorausgesetzt, wenngleich viele der dargestellten Quelltexte auch unter älteren Versionen funktionieren. Die Verwendung von PHP in einer Version älter als 4.0 wird allerdings nicht berücksichtigt.</para>
<section>
<section-header>Einbindung von PHP-Quelltext</section-header>
<para>Quelltexte, die von der PHP-Engine ausgeführt werden sollen, werden in HTML-Dateien abgelegt. Die Trennung von PHP und HTML geschieht damit, das sämtliche, von der PHP-Engine auszuführende Codezeilen, in PHP-Tags gekapselt werden.</para>
<code>
<label>Beispiel 83: Methoden zum Einbinden von PHP-Quelltexten</label>
<codeline>&lt;?php phpcode ?&gt; </codeline>
<codeline>&lt;? phpcode ?&gt; </codeline>
<codeline>&lt;% phpcode %&gt; </codeline>
<codeline>&lt;script language=&quot;php&quot;&gt;phpcode&lt;/script&gt; </codeline>
</code>
<para>Die erste Variante stellt dabei die am meisten unterstützte und portabelste Methode dar und sollte durchgehend angewendet werden.</para>
<para>Wenn ein Dokument mit solchen PHP-Tags zur PHP-Engine gelangt, wird der HTML-Teil unverändert beibehalten. An den Stellen, an denen PHP-Code steht, wird dieser von der Engine aus dem Dokument entfernt; Stehen in diesem Codeteil Anweisungen, die Textausgabe produzieren, wird dieser an dieser Stelle in das HTML-Dokument eingefügt.</para>
<para>Nach Abarbeitung sämtlicher Codezeilen wird das resultierende HTML-Dokument wieder an den Webserver übergeben, der es anschließen an den Client sendet.</para>
</section>
<section><section-header>Hallo Welt</section-header>
<code>
<label>Beispiel 84: Hallo-Welt Beispiel mit PHP</label>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt;&lt;title&gt;Hallo-Welt Beispiel&lt;/title&gt;&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>&lt;?php  </codeline>
<codeline>print &quot;&lt;h1&gt;Hallo Welt&lt;/h1&gt;&quot;;  </codeline>
<codeline>?&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<para>Das Hallo-Welt Beispiel liefert folgendes Dokument an den Browser:</para>
<code>
<label>Beispiel 85: Ausgabe von Hallo-Welt</label>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt;&lt;title&gt;Hallo-Welt Beispiel&lt;/title&gt;&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>&lt;h1&gt;Hallo Welt&lt;/h1&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
<para>Wenn lediglich eine print-Anweisung im PHP-Teil erfolgt, kann diese auch verkürzt dargestellt werden. Das Ergebnis bleibt dabei identisch.</para>
<code>
<label>Beispiel 86: Hallo-Welt Beispiel verkürzt</label>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt;&lt;title&gt;Hallo-Welt Beispiel&lt;/title&gt;&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>&lt;?=&quot;&lt;h1&gt;Hallo Welt&lt;/h1&gt;&quot;?&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
</section>
<section><section-header>Typen</section-header>
<section>
<section-header>Übersicht</section-header>
<para>Variablen werden mit einem $-Zeichen gefolgt von ihrem Namen ausgezeichnet. Der Name muss mit einem Buchstaben oder einem Unterstrich ( _ ) beginnen und darf aus einer beliebigen Anzahl von Buchstaben, Ziffern und Unterstrichen bestehen.</para>
<para>PHP unterscheidet in Groß-/Kleinschreibung.</para>
<para>Der Vorrat unterschiedlicher Typen ist in PHP relativ klein. Es wird im wesentlichen zwischen skalaren und zusammengesetzten Typen unterschieden.</para>
<table>
<tr>
<th><para>Bezeichnung</para>
</th>
<th><para>Erklärung</para>
</th>
<th><para>Typ</para>
</th>
</tr>
<tr>
<td><para>String</para>
</td>
<td><para>Zeichenkette</para>
</td>
<td><para>Skalare Typen</para>
</td>
</tr>
<tr>
<td><para>Integer</para>
</td>
<td><para>ganzzahliger Wert</para>
</td>
</tr>
<tr>
<td><para>Float</para>
</td>
<td><para>Gleitkomma Zahl</para>
</td>
</tr>
<tr>
<td><para>Boolean</para>
</td>
<td><para>boolscher Wert, wahr oder falsch</para>
</td>
</tr>
<tr>
<td><para>Array</para>
</td>
<td><para>Listenobjekt</para>
</td>
<td><para>Zusammengesetzte Typen</para>
</td>
</tr>
<tr>
<td><para>Object</para>
</td>
<td><para>Ojektorientierte Programmierung</para>
</td>
</tr>
<tr>
<td><para>NULL</para>
</td>
<td><para>NIL-Wert</para>
</td>
<td><para>Spezielle Typen</para>
</td>
</tr>
<tr>
<td><para>ResourceID</para>
</td>
<td><para>Integerwert als Rückgabe aus resourcenbindenen Funktionen</para>
</td>
</tr>
<label>Tabelle 17: Primitive Variablentypen in PHP</label>
</table>
<para>Variablen sind typdynamisch und bedürfen keiner Deklaration. Bei einer Zuweisung wird automatisch der Typ des zugewiesen Werts übernommen.</para>
<para>Es gibt im PHP-Kontext eine Menge bereits initialisierter Variablen. Diese, zusammen mit weiteren Informationen über den Serverkontext, können mittels eines Funktionsaufrufs angezeigt werden.</para>
<code>
<label>Beispiel 87: phpinfo();</label>
<codeline>&lt;html&gt; </codeline>
<codeline>&lt;head&gt;&lt;title&gt;Hallo-Welt Beispiel&lt;/title&gt;&lt;/head&gt; </codeline>
<codeline>&lt;body&gt; </codeline>
<codeline>&lt;?php  </codeline>
<codeline>phpinfo(); </codeline>
<codeline>?&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>&lt;/html&gt; </codeline>
</code>
</section>
<section><section-header>Boolean</section-header>
<para>Eine Variable des Typs Boolean kann entweder den Wert TRUE oder FALSE annehmen. Um ihr einen Wert zuzuweisen werden diese Schlüsselworte (unabhängig von Groß-/Kleinschreibung) verwendet.</para>
<code>
<label>Beispiel 88: Boolescher Werts</label>
<codeline>$foo = True; </codeline>
<codeline>$foo = FALSE; </codeline>
</code>
<para>In der Regel stellt ein Ergebnis eines Vergleichsoperators einen boolschen Wert dar, der von einer Kontrollstruktur verwendet wird.</para>
<para>Wenn numerische Variablen als Boolean ausgewertet werden, werden alle Werte abweichend der 0 als TRUE interpretiert - auch negative Werte wie -1.</para>
<para>Folgende Werte werden als FALSE angesehen: Boolean FALSE, Integer 0, Fließkomma 0.0, leere Zeichenkette oder &quot;0&quot;, Array oder Objekt ohne Elemente, der Typ NULL und nicht definierte Variablen. Bei der Umwandlung aller anderen Werte wird TRUE angenommen.</para>
</section>
<section><section-header>Integer</section-header>
<para>Ein Integerwert ist eine Nummer aus der Menge { ... , -2 , -1 , 0 , 1 , 2 , ... }. Ganzzahlen können in dezimaler (10-basierter), hexadezimaler (16-basierter) oder oktaler (8-basierter) Schreibweise angegeben werden, wahlweise mit einem vorangestellten Zeichen (- oder +).</para>
<para>Wenn die oktale Schreibweise verwendet wird, muss die Zahl mit einer vorangestellten Null 0 geschrieben werden; in hexadezimaler Schreibweise muss vor der Zahl ein 0x vorangestellt sein.</para>
<para>PHP unterstützt keine vorzeichenlose Integer-Werte.</para>
<code>
<label>Beispiel 89: Integerwerte</label>
<codeline>$a = 1234; // Dezimalzahl </codeline>
<codeline>$a = -123; // eine negative Zahl </codeline>
<codeline>$a = 0123; // Oktalzahl (entspricht 83 dezimal) </codeline>
<codeline>$a = 0x1A; // Hexadezimalzahl (entspricht 26 dezimal) </codeline>
</code>
<para>Die Größe eines Integer-Wertes ist plattformabhängig, ein Maximalwert von ungefähr zwei Milliarden ist jedoch üblich. (Vorzeichenbehafteter 32-Bit-Wert). Wird der Maximalwert überschritten, wird der Wert als Float interpretiert; Ebenso das Ergebnis einer Operation mit Integerwerten, die die Integer-Grenzen überschreiten.</para>
<para>Bei der Umwandlung von Integer nach Boolean, wird nur die 0 als FALSE interpretiert, alle anderen Werte sind TRUE, also auch -1.</para>
<para>Wird ein Float-Wert nach Integer umgewandelt, wird dieser in Richtung 0 gerundet. Wird ein Float nach Integer umgewandelt, dessen Wert außerhalb der Integer-Grenzen liegt, ist das Ergebnis undefiniert. Achtung: Es wird bei einem solchen Vorgang keine Warnung oder Notiz ausgegeben.</para>
</section>
<section><section-header>Float</section-header>
<para>Fließkomma-Zahlenwerte (double, float) sind reelle Zahlen.</para>
<code>
<label>Beispiel 90: Float-Werte</label>
<codeline>$a = 1.234; </codeline>
<codeline>$a = 1.2e3; </codeline>
<codeline>$a = 7E-10; </codeline>
</code>
<para>Die Größe einer Fließkomma-Zahl ist plattformabhängig, dennoch stellt ein Maximum von ~1.8e308 mit einer Genauigkeit von 14 Nachkommastellen einen üblichen Wert dar (das entspricht 64-Bit im IEEE-Format).</para>
</section>
<section><section-header>String</section-header>
<para>In PHP ist ein String eine Kette von Zeichen, wobei ein Zeichen in einem Byte gespeichert wird. Damit sind 256 Zeichen (also kein Unicode) möglich. Die Länge der Zeichenkette ist praktisch nicht begrenzt.</para>
<para>Es gibt drei Wege, eine Zeichenkette zu schreiben.</para>
<section>
<section-header>Einfache Anführungszeichen</section-header>
<para>Das Anführungszeichen kann in der Zeichenkette selbst nur escaped verwendet werden. Der Backslash als Escape-Zeichen muss nur dann selbst escaped werden, wenn auf ihm ein einfaches Anführungszeichen folgt. Andere Zeichen können nicht escaped werden. Variablen innerhalb einer single-quoted Zeichenkette nicht ausgewertet.</para>
</section>
<section><section-header>Doppelte Anführungszeichen</section-header>
<para>Innerhalb von Zeichenketten in doppelten Anführungszeichen werden folgende Escape-Sequenzen erkannt:</para>
<table>
<tr>
<th><para>Escape-Sequenz</para>
</th>
<th><para>Bedeutung</para>
</th>
</tr>
<tr>
<td><para>\n</para>
</td>
<td><para>Zeilenvorschub (LF oder 0x0A als ASCII-Code)</para>
</td>
</tr>
<tr>
<td><para>\r</para>
</td>
<td><para>Wagenrücklauf (CR oder 0x0D als ASCII-Code)</para>
</td>
</tr>
<tr>
<td><para>\t</para>
</td>
<td><para>horizontaler Tabulator (HT oder 0x09 als ASCII-Code</para>
</td>
</tr>
<tr>
<td><para>\\</para>
</td>
<td><para>Backslash / Rückstrich</para>
</td>
</tr>
<tr>
<td><para>\$</para>
</td>
<td><para>Dollarsymbol</para>
</td>
</tr>
<tr>
<td><para>\&quot;</para>
</td>
<td><para>doppelte Anführungszeichen</para>
</td>
</tr>
<tr>
<td><para>\[0-7]{1,3}</para>
</td>
<td><para>die Zeichenfolge, die dem regulären Ausdruck entspricht ist ein Zeichen in Oktal-Schreibweise</para>
</td>
</tr>
<tr>
<td><para>\x[0-9A-Fa-f]{1,2}</para>
</td>
<td><para>die Zeichenfolge, die dem regulären Ausdruck entspricht ist ein Zeichen in Hexadezimal-Schreibweise</para>
</td>
</tr>
<label>Tabelle 18: Escape-Sequenzen in Zeichenketten</label>
</table>
<para>Innerhalb einer von doppelten Anführungszeichen werden Variablennamen durch ihren Wert ersetzt.</para>
</section>
<section><section-header>Heredoc</section-header>
<para>Mittels der Heredoc-Syntax lassen sich bequem größere Textblöcke einer Variablen zuweisen. Sie wird angewendet, indem die Zeichenfolge &quot;&lt;&lt;&lt;&quot; (ohne Anführungszeichen) und ein Bezeichner angegeben werden, gefolgt vom Inhalt und dem selben Bezeichner als Abschluß. Der abschließende Bezeichner muss (möglicherweise mit einem direkt anschliessenden Semikolon) alleine und in der ersten Spalte in einer Zeile stehen.</para>
<para>Escape-Sequenzen können verwendet werden und werden, genauso wie Variablennamen, ausgewertet.</para>
<code>
<label>Beispiel 91: String-Variablen</label>
<codeline>$var = &apos;\nString&apos;; </codeline>
<codeline>$str = &apos;Text mit \n in einem $var.&apos;; </codeline>
<codeline>// Ausgabe: Text mit \n in einem $var. </codeline>
<codeline>$str = &quot;Text mit \&quot;\n\&quot;  </codeline>
<codeline>in einem $var.&quot;; </codeline>
<codeline>/* Ausgabe:  </codeline>
<codeline>Text mit &quot; </codeline>
<codeline>&quot; </codeline>
<codeline>in einem </codeline>
<codeline>String. </codeline>
<codeline>*/ </codeline>
<codeline>$str = &lt;&lt;&lt;EOD </codeline>
<codeline>Beispiel von einem $var </codeline>
<codeline>über mehrere Script-Zeilen </codeline>
<codeline>durch Gebrauch der heredoc-Syntax. </codeline>
<codeline>EOD; </codeline>
<codeline>/* Ausgabe:  </codeline>
<codeline>Beispiel von einem </codeline>
<codeline>String </codeline>
<codeline>über mehrere Script-Zeilen </codeline>
<codeline>durch Gebrauch der heredoc-Syntax. </codeline>
<codeline>*/  </codeline>
</code>
<para>Sobald in einer Zeichenkette nach Heredoc-Syntax oder in doppelten Anführungszeichen ein nicht escapetes Dollarzeichen verwendet wird, werden alle darauf folgenden Zeichen, die in einem Variablennamen verwendet werden dürfen (Ziffer, Buchstabe, Unterstrich), zu einem Variablenbezeichner zusammengezogen, dessen Inhalt anschliessend diesen Namen in der Zeichenkette ersetzt.</para>
<para>Dies funktioniert bei skalaren Variablen wie auch, in Grenzen, bei Objekten und Arrays.</para>
<code>
<label>Beispiel 92: Geparste Variablennamen in Zeichenketten</label>
<codeline>$beer = &apos;Heineken&apos;; </codeline>
<codeline>$beers = array(  </codeline>
<codeline>	&quot;nl&quot;=&gt;array(&quot;Heineken&quot;, &quot;Dommelsch&quot;),  </codeline>
<codeline>	&quot;d&quot;=&gt;&quot;Krombacher&quot; </codeline>
<codeline>); </codeline>
<codeline>echo &quot;$beer&apos;s Geschmack ist großartig&quot;;    // funktioniert </codeline>
<codeline>echo &quot;Er hat einige $beers getrunken&quot;;     // funktioniert nicht </codeline>
<codeline>echo &quot;Er hat einige ${beer}s getrunken&quot;;   // funktioniert </codeline>
<codeline>echo &quot;Er hat einige {$beer}s getrunken&quot;;   // funktioniert </codeline>
<codeline>echo &quot;Er hat einige &quot;.$beer.&quot;s getrunken&quot;; // funktioniert </codeline>
<codeline>echo &quot;$beers[nl][0] schmeckt am besten&quot;;  </codeline>
<codeline>// funktioniert nicht </codeline>
<codeline>echo &quot;{$beers[nl][0]} schmeckt besser als $beers[d]&quot;;  </codeline>
<codeline>// funktioniert beides </codeline>
<codeline>echo $beers[&quot;nl&quot;][0].&quot; schmeckt besser als &quot;.$beers[&quot;d&quot;]; </codeline>
<codeline>// funktioniert auch beides  </codeline>
<codeline>echo $beers[&quot;nl&quot;][0].&quot; schmeckt besser als alles aus &quot;;  </codeline>
<codeline>echo $beers[&quot;nl&quot;][1]{0}; </codeline>
<codeline>// passt auch </codeline>
</code>
<para>String-Variablen werden wie folgt in numerische Werte umgewandelt: Enthält die Zeichenkette ein &apos;.&apos;, &apos;e&apos; oder &apos;E&apos;, wird er als Float ausgewertet, ansonsten als Integer. Ausgehend vom Anfang der Zeichenkette wird versucht, den Inhalt in einen numerischen Wert um zu wandeln. Fängt die Zeichenkette nicht mit gültigen numerischen Daten an, so wird die gesamte Zeichenkette als 0 gewertet.</para>
<para>Gültige numerische Daten sind ein optionales Vorzeichen, gefolgt von einer oder mehreren Zahlen (optional mit einem Dezimalpunkt). Wahlweise kann auch ein Exponent angegeben werden. Der Exponent besteht aus einem &apos;e&apos; oder &apos;E&apos;, gefolgt von einer oder mehreren Zahlen.</para>
<code>
<label>Beispiel 93: Beispiele für die Umwandlung von Zeichenketten in numerische Werte</label>
<codeline>$foo = 1 + &quot;zwei Schweine&quot;			// $foo ist integer (1) </codeline>
<codeline>$foo = &quot;eins&quot; + 1;					// $foo ist integer (1) </codeline>
<codeline>$foo = 1 + &quot;10.5&quot;;               // $foo ist float   (11.5) </codeline>
<codeline>$foo = 1 + &quot;-1.3e3&quot;;             // $foo ist float   (-1299) </codeline>
<codeline>$foo = 1 + &quot;bob-1.3e3&quot;;          // $foo ist integer (1) </codeline>
<codeline>$foo = 1 + &quot;bob3&quot;;               // $foo ist integer (1) </codeline>
<codeline>$foo = 1 + &quot;10 Kleine Schweine&quot;; // $foo ist integer (11) </codeline>
<codeline>$foo = 4 + &quot;10.2 Ferkel&quot;;        // $foo ist float   (14.2) </codeline>
<codeline>$foo = &quot;10 Schweine &quot; + 1;       // $foo ist integer (11) </codeline>
<codeline>$foo = &quot;10.0 Schweine &quot; + 1;     // $foo ist float   (11) </codeline>
<codeline>$foo = &quot;10.0 Schweine &quot; + 1.0;   // $foo ist float   (11) </codeline>
</code>
</section>
</section>
<section><section-header>Array</section-header>
<para>Mit Arrays ist es möglich, in einer Variable eine beliebige Anzahl von Werten zu speichern. Die Elemente des Arrays können von beliebigem Typ sein; auch Arrays mit gemischten Elementtypen sind möglich.</para>
<para>Neben skalaren Typen ist es auch möglich, Array- oder Objektvariablen in einem Array zu speichern.</para>
<para>Ein Array kann mit numerischen Schlüsseln organisiert sein (indiziert). Auch möglich ist die Verwendung von Zeichenketten-Keys. Diese Form eines Arrays wird Hash oder assoziatives Array genannt.</para>
<para>Eine Arrayvariable kann explizit über das Schlüsselwort array erzeugt werden. Daneben ist es möglich, das Array implizit zu erzeugen. Dazu weißt einem benannten Element des Arrays einen Wert zu, oder fügt es mit den leeren eckigen Klammern an das Ende des Arrays an. Ist die Arrayvariable noch nicht vorhanden, wird sie erzeugt.</para>
<para>Besteht das Array bereits und unter dem verwendeten Schlüssel ist ein Wert vorhanden, wird dieser durch den neu zugewiesenen überschrieben.</para>
<para>Ist die Variable bereits als skalare Variable benutzt worden, muss ihr entweder explizit ein Array zugewiesen werden, oder sie muss vor der impliziten Erzeugung gelöscht werden.</para>
<code>
<label>Beispiel 94: Erzeugung und Änderung von Arrays</label>
<codeline>$a = array(); </codeline>
<codeline>$a = array( &quot;grün&quot;, &quot;blau&quot;, &quot;rot&quot; ); </codeline>
<codeline>var_dump($a); </codeline>
<codeline>/* Ausgabe </codeline>
<codeline>array(3) { </codeline>
<codeline>  [0]=&gt; </codeline>
<codeline>  string(4) &quot;grün&quot; </codeline>
<codeline>  [1]=&gt; </codeline>
<codeline>  string(4) &quot;blau&quot; </codeline>
<codeline>  [2]=&gt; </codeline>
<codeline>  string(3) &quot;rot&quot; </codeline>
<codeline>} */ </codeline>
<codeline>$a[] = &quot;gelb&quot;; </codeline>
<codeline>/* Ausgabe </codeline>
<codeline>array(4) { </codeline>
<codeline>  [0]=&gt; </codeline>
<codeline>  string(4) &quot;grün&quot; </codeline>
<codeline>  [1]=&gt; </codeline>
<codeline>  string(4) &quot;blau&quot; </codeline>
<codeline>  [2]=&gt; </codeline>
<codeline>  string(3) &quot;rot&quot; </codeline>
<codeline>  [3]=&gt; </codeline>
<codeline>  string(4) &quot;gelb&quot; </codeline>
<codeline>} */ </codeline>
<codeline>$b = array( &quot;farbe&quot;=&gt;&quot;blau&quot;, &quot;gewicht&quot;=&gt;100, &quot;preis&quot;=&gt;12.98 ); </codeline>
<codeline>/* Ausgabe </codeline>
<codeline>array(3) { </codeline>
<codeline>  [&quot;farbe&quot;]=&gt; </codeline>
<codeline>  string(4) &quot;blau&quot; </codeline>
<codeline>  [&quot;gewicht&quot;]=&gt; </codeline>
<codeline>  int(100) </codeline>
<codeline>  [&quot;preis&quot;]=&gt; </codeline>
<codeline>  float(12.98) </codeline>
<codeline>} */ </codeline>
<codeline>$b[&quot;farbe&quot;] = $a[0]; </codeline>
<codeline>$b[&quot;preis&quot;] = 10.98; </codeline>
<codeline>/* Ausgabe </codeline>
<codeline>array(3) { </codeline>
<codeline>  [&quot;farbe&quot;]=&gt; </codeline>
<codeline>  string(4) &quot;grün&quot; </codeline>
<codeline>  [&quot;gewicht&quot;]=&gt; </codeline>
<codeline>  int(100) </codeline>
<codeline>  [&quot;preis&quot;]=&gt; </codeline>
<codeline>  float(10.98) </codeline>
<codeline>} */ </codeline>
</code>
</section>
<section><section-header>Object</section-header>
<para>Eine Variable des Typs Object enthält eine Instanz einer Klasse, die mittels des new-Konstruktors erzeugt wurde.</para>
<code>
<label>Beispiel 95: Objekt-Variable</label>
<codeline>class foo { </codeline>
<codeline>    function do_foo() {  </codeline>
<codeline>        echo &quot;Doing foo.&quot;;  </codeline>
<codeline>    } </codeline>
<codeline>} </codeline>
<codeline>$bar = new foo; </codeline>
<codeline>$bar-&gt;do_foo(); </codeline>
</code>
</section>
<section><section-header>Resource</section-header>
<para>Eine Resource ist eine Referenz auf eine PHP-interne Resource. Ressourcenreferenzen sind Rückgabewerte von bestimmten Funktionen, die in PHP-Bibliotheken Objekte erzeugen. Mit ihnen kann in späteren Funktionsaufrufen auf dieses Objekt zugegriffen werden.</para>
<code>
<label>Beispiel 96: Resource</label>
<codeline>$mysql_resource = mysql_connect( HOST, LOGIN, PW ); </codeline>
<codeline>mysql_select_db( &quot;meinedatenbank&quot;, $mysql_resource ); </codeline>
</code>
<para>PHP verfügt über einen Garbage-Collector, so dass nach der letzten Verwendung einer Resource diese automatisch von PHP freigegeben wird. Die Verwendung von free_result-Funktionen ist also nicht zwingend erforderlich.</para>
</section>
<section><section-header>NULL</section-header>
<para>Eine Variable mit dem Typ NULL kann nur den Wert NULL enthalten. Alle nicht initialisierten Variablen und alle mit unset gelöschten Variablen sind vom Typ, bzw. haben den Wert NULL.</para>
</section>
</section>
<section><section-header>Umgang mit Variablen</section-header>
<section>
<section-header>Typkonvertierung</section-header>
<para>Variablenwerte können explizit zwischen Typen konvertiert werden. Dazu wird (ähnlich zu C) der Name des Typs vor der umzuwandelnden Variable in Klammern gesetzt.</para>
<code>
<label>Beispiel 97: Typkonvertierungen</label>
<codeline>$foo = 10;           // $foo ist ein Integer-Wert </codeline>
<codeline>$bar = (float) $foo; // $bar ist vom Typ float </codeline>
</code>
<para>Folgende Umwandlungen sind möglich:</para>
<table>
<tr>
<th><para>Cast</para>
</th>
<th><para>Umwandlung...</para>
</th>
</tr>
<tr>
<td><para>(int), (integer)</para>
</td>
<td><para>nach integer</para>
</td>
</tr>
<tr>
<td><para>(bool), (boolean)</para>
</td>
<td><para>nach boolean</para>
</td>
</tr>
<tr>
<td><para>(float), (double), (real)</para>
</td>
<td><para>nach float</para>
</td>
</tr>
<tr>
<td><para>(string)</para>
</td>
<td><para>nach string</para>
</td>
</tr>
<tr>
<td><para>(array)</para>
</td>
<td><para>nach array</para>
</td>
</tr>
<tr>
<td><para>(object)</para>
</td>
<td><para>Wandlung zum Objekt</para>
</td>
</tr>
<label>Tabelle 19: Typumwandlungen</label>
</table>
</section>
<section><section-header>Funktionen für Variablen</section-header>
<para>PHP enthält eine Vielzahl von Funktionen, die den Umgang mit Variablen erheblich sicherer machen. Einige seien an dieser Stelle kurz vorgestellt.</para>
<table>
<tr>
<th><para>Funktion</para>
</th>
<th><para>Beschreibung</para>
</th>
</tr>
<tr>
<td><para>empty</para>
</td>
<td><para>Prüft, ob eine Variable einen Wert enthält</para>
</td>
</tr>
<tr>
<td><para>doubleval, floatval, strval, intval</para>
</td>
<td><para>Konvertierung zu Float bzw. String</para>
</td>
</tr>
<tr>
<td><para>get_defined_vars</para>
</td>
<td><para>Gibt ein Array mit allen verwendeten Variablen zurück</para>
</td>
</tr>
<tr>
<td><para>get_resource_type</para>
</td>
<td><para>Gibt den Typ der Ressource als Zeichenkette zurück</para>
</td>
</tr>
<tr>
<td><para>gettype</para>
</td>
<td><para>Liefert den Datentyp einer Variablen</para>
</td>
</tr>
<tr>
<td><para>import_request_variables</para>
</td>
<td><para>Importiert GET/POST/Cookie-Variablen in den Globalen Namensraum (wichtig wenn register_globals in der ini ausgeschaltet wurde)</para>
</td>
</tr>
<tr>
<td><para>is_double (is_array, is_float, is_real),</para>
<para>is_integer (is_long, is_int),</para>
<para>is_string, is_bool</para>
<para>is_object, is_resource, is_null</para>
</td>
<td><para>Prüft, ob Variable von einem bestimmten Typ ist ( is_float und is_real sind Synomyme für is_double; is_long und is_int sind Synonyme für is_integer)</para>
</td>
</tr>
<tr>
<td><para>is_numeric, is_scalar</para>
</td>
<td><para>Prüft, ob die Variable eine Zahl oder ein numerischer String ist bzw. ob eine skalare Variable vorliegt</para>
</td>
</tr>
<tr>
<td><para>isset</para>
</td>
<td><para>Prüft die Existenz einer Variablen</para>
</td>
</tr>
<tr>
<td><para>settype</para>
</td>
<td><para>Legt den Typ einer Variablen fest</para>
</td>
</tr>
<tr>
<td><para>unset</para>
</td>
<td><para>Löschen einer Variablen</para>
</td>
</tr>
<tr>
<td><para>print_r, var_dump, var_export</para>
</td>
<td><para>Gibt Variablen-Informationen in lesbarer Form aus (print_r) bzw. gibt alle Informationen zu einer Variablen aus (var_dump, var_export) in gültiger PHP-Syntax (var_export)</para>
</td>
</tr>
<tr>
<td><para>serialize, unserialize</para>
</td>
<td><para>Erzeugt ein speicherbares Datenformat bzw. stellt Variablen aus mittels serialize in eine Zeichenkette umgewandelte Variablen wieder her</para>
</td>
</tr>
<label>Tabelle 20: Variablen-Funktionen</label>
</table>
</section>
<section><section-header>Variable Variablen</section-header>
<para>Mit diesem Mechanismus gestattet PHP die Verwendung von variablen Variablennamen. Damit wird die Nutzung von dynamischen Variablen es möglich.</para>
<para>Diese Art von Variablen werden durch Verwendung eines zusätzlichen Dollarzeichens gekennzeichnet. Alternativ bietet sich, bei Arrays wegen der Doppeldeutigkeit zwingend - ansonsten aufgrund der besseren Lesbarkeit des Codes, die Schreibweise mit den geschweiften Klammern an.</para>
<code>
<label>Beispiel 98: Variable Variablen</label>
<codeline>$hallo = &quot;Hallo&quot;; </codeline>
<codeline>$$hallo = &quot;Welt&quot;; </codeline>
<codeline>print $hallo.&quot; &quot;.$Hallo; </codeline>
<codeline>print $hallo.&quot; &quot;.${$hallo}; // Ausgabe jeweils: Hallo Welt </codeline>
</code>
</section>
<section><section-header>Variablen von Außerhalb</section-header>
<para>Informationen aus Formularen stehen (wenn die PHP-ini-Direktive track_vars auf &quot;on&quot; steht) in PHP-Skripten automatisch in den assoziativen Array zur Verfügung. Das gleiche gilt auch für Cookie-Daten und einige weitere Informationen aus dem Kontext, in dem das Skript läuft.</para>
<para>Folgende Tabelle gibt Auskunft über die einzelnen verfügbaren Arrays. Diejenigen Bezeichner, dessen Namen mit einem Unterstrich beginnen sind superglobal in jedem Geltungsbereich verfügbar, die anderen sind lediglich global verfügbar (also nicht innerhalb von Klassen und Funktionen, es sei denn, sie werden mit dem Schlüsselwort global in diesen Kontext hinein importiert).</para>
<table>
<tr>
<th><para>Umgebungsvariable</para>
</th>
<th><para>Beschreibung</para>
</th>
</tr>
<tr>
<td><para>$HTTP_GET_VARS ($_GET), $HTTP_POST_VARS ($_POST), $HTTP_POST_FILES ($_FILES)</para>
</td>
<td><para>Von Formularen mittels Post bzw. Get versendete Variablen und auf den Server hochgeladene Dateien</para>
</td>
</tr>
<tr>
<td><para>$HTTP_COOKIE_VARS ($_COOKIE)</para>
</td>
<td><para>Vom Browser an den Server übermittelte Informationen, die in einem Cookie auf dem Client gespeichert sind</para>
</td>
</tr>
<tr>
<td><para>$HTTP_ENV_VARS ($_ENV)</para>
</td>
<td><para>Informationen aus dem Kontext des Skripts</para>
</td>
</tr>
<tr>
<td><para>$HTTP_SERVER_VARS ($_SERVER)</para>
</td>
<td><para>Informationen aus zum Server</para>
</td>
</tr>
<tr>
<td><para>$HTTP_SESSION_VARS ($_SESSION)</para>
</td>
<td><para>Als Session-Variablen registrierte Variablen</para>
</td>
</tr>
<tr>
<td><para>$_REQUEST</para>
</td>
<td><para>Post, Get und File-Variablen in einem Array zusammengefaßt</para>
</td>
</tr>
<label>Tabelle 21: Umgebungsvariablen in PHP</label>
</table>
<para>Die Inhalte dieser Variablen werden durch den Aufruf von phpinfo(); in einer Tabelle nebst weiterer Informationen zur PHP-Installation übersichtlich dargestellt.</para>
</section>
</section>
<section><section-header>Konstanten</section-header>
<para>Wie in anderen Programmiersprachen, bietet auch PHP die Möglichkeit Konstanten zu definieren. Konstanten können Zeichenketten, Fließkomma-, Integer-, NULL- und boolsche Werte zugewiesen werden; also ausschließlich skalare Werte.</para>
<para>Namen für Konstanten können nach den gleichen Regeln wie auch für die Benennung von Variablen gewählt werden. Im Unterschied zu Variablen, wird dem Namen allerdings kein Dollarzeichen vorangestellt und Konstanten müssen explizit definiert werden.</para>
<para>Ein weiterer Unterschied zu Variablen ist der, dass Konstanten global gültig sind. Außerdem kann sich der Wert einer Konstanten nach der Definition nicht mehr ändern. Auch das Löschen einer Konstanten ist nicht möglich.</para>
<code>
<label>Beispiel 99: Konstanten-Definition und Verwendung</label>
<codeline>define( &quot;MyHOST&quot;, &quot;localhost&quot; ); </codeline>
<codeline>define( &quot;MyLOGIN&quot;, &quot;root&quot; ); </codeline>
<codeline>define( &quot;MyPW&quot;, &quot;&quot; ); </codeline>
<codeline>if( defined( &quot;MyHOST&quot; ) ){ </codeline>
<codeline>	@mysql_connect( MyHOST, MyLOGIN, MyPW ) or </codeline>
<codeline>		die( &quot;failed to connect to db-server&quot; ); </codeline>
<codeline>} </codeline>
</code>
</section>
<section><section-header>Operatoren</section-header>
<section>
<section-header>Arithmetische Operatoren</section-header>
<table>
<tr>
<th><para>Beispiel</para>
</th>
<th><para>Name</para>
</th>
<th><para>Ergebnis</para>
</th>
</tr>
<tr>
<td><para>$a + $b</para>
</td>
<td><para>Addition</para>
</td>
<td><para>Summe von $a und $b.</para>
</td>
</tr>
<tr>
<td><para>$a - $b</para>
</td>
<td><para>Subtraktion</para>
</td>
<td><para>Differenz von $a und $b.</para>
</td>
</tr>
<tr>
<td><para>$a * $b</para>
</td>
<td><para>Multiplikation</para>
</td>
<td><para>Produkt von $a und $b.</para>
</td>
</tr>
<tr>
<td><para>$a / $b</para>
</td>
<td><para>Division</para>
</td>
<td><para>Quotient von $a und $b.</para>
</td>
</tr>
<tr>
<td><para>$a % $b</para>
</td>
<td><para>Modulus</para>
</td>
<td><para>Rest von $a geteilt durch $b.</para>
</td>
</tr>
<label>Tabelle 22: Arithmetische Operatoren</label>
</table>
</section>
<section><section-header>Zuweisungsoperatoren</section-header>
<para>Mittels dem Gleichheitszeichen wird dem linken Operanden der Wert des Ausdrucks auf der rechten Seite zugewiesen.</para>
<code>
<label>Beispiel 100: Zuweisungsoperator</label>
<codeline>$a = ($b = 4) + 5  </codeline>
<codeline>// $a ist nun gleich 9 und $b wurde auf den Wert 4 gesetzt. </codeline>
</code>
</section>
<section><section-header>Zeichenketten Operatoren</section-header>
<para>Als Zeichenkettenoperator existiert lediglich der Concatenator &quot;.&quot;.</para>
<code>
<label>Beispiel 101: Zeichenketten-Concatenator</label>
<codeline>$str = $str1.$str2.&quot; Telefon&quot;; </codeline>
</code>
</section>
<section><section-header>Kombinierte Operatoren</section-header>
<para>Ähnlich der C-Syntax lassen sich arithmetische Operatoren, Binäroperatoren und der Zeichenketten-Concatenator mit dem Zuweisungsoperator verbinden. Dies führt zu einer kompakteren Schreibweise und übersichtlichem Code. Außerdem erlaubt die Schreibweise eine etwas schnellere Ausführung, da intern keine zusätzliche Variable für die Operation verwendet werden muss.</para>
<code>
<label>Beispiel 102: Kombinierte Operatoren</label>
<codeline>$a = 3; </codeline>
<codeline>$a += 5; // entspricht: $a = $a + 5; </codeline>
<codeline>$b = &quot;Hallo &quot;; </codeline>
<codeline>$b .= &quot;Du!&quot;; // entspricht: $b = $b . &quot;Du!&quot;; </codeline>
</code>
</section>
<section><section-header>Vergleichs-Operatoren</section-header>
<table>
<tr>
<th><para>Beispiel</para>
</th>
<th><para>Name</para>
</th>
<th><para>Ergebnis</para>
</th>
</tr>
<tr>
<td><para>$a == $b</para>
</td>
<td><para>Gleich</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a gleich $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a === $b</para>
</td>
<td><para>Identisch</para>
</td>
<td><para>Gibt TRUE zurück wenn $a gleich $b ist und beide vom gleichen Typ sind</para>
</td>
</tr>
<tr>
<td><para>$a != $b</para>
</td>
<td><para>Ungleich</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a nicht gleich $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a &lt;&gt; $b</para>
</td>
<td><para>Ungleich</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a nicht gleich $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a !== $b</para>
</td>
<td><para>Nicht identisch</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a nicht gleich $b ist, oder wenn beide nicht vom gleichen Typ sind</para>
</td>
</tr>
<tr>
<td><para>$a &lt; $b</para>
</td>
<td><para>Kleiner Als</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a kleiner als $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a &gt; $b</para>
</td>
<td><para>Größer Als</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a größer als $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a &lt;= $b</para>
</td>
<td><para>Kleiner Gleich</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a kleiner oder gleich $b ist.</para>
</td>
</tr>
<tr>
<td><para>$a &gt;= $b</para>
</td>
<td><para>Größer Gleich</para>
</td>
<td><para>Gibt TRUE zurück, wenn $a größer oder gleich $b ist.</para>
</td>
</tr>
<label>Tabelle 23: Vergleichs-Operatoren</label>
</table>
<para>Ein weiter Vergleichsoperator ist der &quot;?:&quot;- oder Trinitäts-Operator. Er arbeitet genauso wie in C und vielen anderen Programmiersprachen.</para>
<code>
<label>Beispiel 103: Verwendung des Trinitäts-Operators</label>
<codeline>(ausdr1) ? (ausdr2) : (ausdr3); </codeline>
</code>
<para>Dieser Ausdruck gibt ausdr2 zurück, wenn ausdr1 TRUE zurückgibt und ausdr3, wenn ausdr1 FALSE zurückgibt.</para>
</section>
<section><section-header>Logische Operatoren</section-header>
<table>
<tr>
<th><para>Beispiel</para>
</th>
<th><para>Name</para>
</th>
<th><para>Ergebnis</para>
</th>
</tr>
<tr>
<td><para>$a and $b</para>
</td>
<td><para>Und</para>
</td>
<td><para>TRUE wenn sowohl $a als auch $b TRUE ist.</para>
</td>
</tr>
<tr>
<td><para>$a or $b</para>
</td>
<td><para>Oder</para>
</td>
<td><para>TRUE wenn $a oder $b TRUE ist.</para>
</td>
</tr>
<tr>
<td><para>$a xor $b</para>
</td>
<td><para>Entweder Oder</para>
</td>
<td><para>TRUE wenn entweder $a oder $b TRUE ist, aber nicht beide.</para>
</td>
</tr>
<tr>
<td><para>! $a</para>
</td>
<td><para>Nicht</para>
</td>
<td><para>TRUE wenn $a nicht TRUE ist.</para>
</td>
</tr>
<tr>
<td><para>$a &amp;&amp; $b</para>
</td>
<td><para>Und</para>
</td>
<td><para>TRUE wenn sowohl $a als auch $b TRUE ist.</para>
</td>
</tr>
<tr>
<td><para>$a || $b</para>
</td>
<td><para>Oder</para>
</td>
<td><para>TRUE wenn $a oder $b TRUE ist.</para>
</td>
</tr>
<label>Tabelle 24: Logische Operatoren</label>
</table>
<para>Die unterschiedlichen Operatoren für die UND- bzw. ODER-Verknüpfung haben eine unterschiedliche Priorität in der Auswertungsreihenfolge.</para>
</section>
<section><section-header>Inkrementierungs- bzw. Dekrementierungsoperatoren</section-header>
<table>
<tr>
<th><para>Beispiel</para>
</th>
<th><para>Name</para>
</th>
<th><para>Auswirkung</para>
</th>
</tr>
<tr>
<td><para>++$a</para>
</td>
<td><para>Prä-Inkrement</para>
</td>
<td><para>Erhöht den Wert von $a um eins (inkrementiert $a) und gibt anschliessend den neuen Wert von $a zurück.</para>
</td>
</tr>
<tr>
<td><para>$a++</para>
</td>
<td><para>Post-Inkrement</para>
</td>
<td><para>Gibt zuerst den aktuellen Wert von $a zurück und erhöht dann den Wert von $a um eins.</para>
</td>
</tr>
<tr>
<td><para>--$a</para>
</td>
<td><para>Prä-Dekrement</para>
</td>
<td><para>Vermindert den Wert von $a um eins (dekrementiert $a) und gibt anschliessend den neuen Wert von $a zurück.</para>
</td>
</tr>
<tr>
<td><para>$a--</para>
</td>
<td><para>Post-Dekrement</para>
</td>
<td><para>Gibt zuerst den aktuellen Wert von $a zurück und erniedrigt dann den Wert von $a um eins.</para>
</td>
</tr>
<label>Tabelle 25: Inkrement- und Dekrementoperatoren</label>
</table>
<code>
<label>Beispiel 104: Verwendung von Pre- bzw. Post-Inkerment- und Dekrementoperationen</label>
<codeline>// Post-Inkrement  </codeline>
<codeline>$a = 5; </codeline>
<codeline>echo &quot;Sollte 5 sein: &quot; . $a++ . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>echo &quot;Sollte 6 sein: &quot; .  $a  . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>// Pre-Inkrement </codeline>
<codeline>$a = 5; </codeline>
<codeline>echo &quot;Sollte 6 sein: &quot; . ++$a . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>echo &quot;Sollte 6 sein: &quot; .  $a  . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>// Post-Dekrement </codeline>
<codeline>$a = 5; </codeline>
<codeline>echo &quot;Sollte 5 sein: &quot; . $a-- . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>echo &quot;Sollte 4 sein: &quot; .  $a  . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>// Pre-Dekrement </codeline>
<codeline>$a = 5; </codeline>
<codeline>echo &quot;Sollte 4 sein: &quot; . --$a . &quot;&lt;br /&gt;\n&quot;; </codeline>
<codeline>echo &quot;Sollte 4 sein: &quot; .  $a  . &quot;&lt;br /&gt;\n&quot;; </codeline>
</code>
</section>
<section><section-header>Bit-Operatoren</section-header>
<table>
<tr>
<th><para>Beispiel</para>
</th>
<th><para>Name</para>
</th>
<th><para>Ergebnis</para>
</th>
</tr>
<tr>
<td><para>$a &amp; $b</para>
</td>
<td><para>Und</para>
</td>
<td><para>Bits, die in $a und $b gesetzt sind werden gesetzt.</para>
</td>
</tr>
<tr>
<td><para>$a | $b</para>
</td>
<td><para>Oder</para>
</td>
<td><para>Bits, die in $a oder $b gesetzt sind werden gesetzt.</para>
</td>
</tr>
<tr>
<td><para>$a ^ $b</para>
</td>
<td><para>Entweder oder (Xor)</para>
</td>
<td><para>Bits, die entweder in $a oder $b gesetzt sind, werden gesetzt aber nicht in beiden.</para>
</td>
</tr>
<tr>
<td><para>~ $a</para>
</td>
<td><para>Nicht</para>
</td>
<td><para>Die Bits, die in $a nicht gesetzt sind, werden gesetzt und umgekehrt.</para>
</td>
</tr>
<tr>
<td><para>$a &lt;&lt; $b</para>
</td>
<td><para>Nach links verschieben</para>
</td>
<td><para>Verschiebung der Bits von $a um $b Stellen nach links (jede Stelle entspricht einer Multiplikation mit zwei).</para>
</td>
</tr>
<tr>
<td><para>$a &gt;&gt; $b</para>
</td>
<td><para>Nach rechts verschieben</para>
</td>
<td><para>Verschiebt die Bits von $a um $b Stellen nach rechts (jede Stelle entspricht einer Division durch zwei).</para>
</td>
</tr>
<label>Tabelle 26: Bit-Operatoren</label>
</table>
</section>
<section><section-header>Array Operatoren</section-header>
<para>Der einzige Array Operator in PHP ist der + Operator. Das rechtsstehende Array wird an das linksstehende Array angehängt, wobei doppelte Schlüssel NICHT überschrieben werden.</para>
<code>
<label>Beispiel 105: Anwendung von + als Array-Operator</label>
<codeline>$a = array(&quot;a&quot; =&gt; &quot;Apfel&quot;, &quot;b&quot; =&gt; &quot;Banane&quot;); </codeline>
<codeline>$b = array(&quot;a&quot; =&gt;&quot;pear&quot;, &quot;b&quot; =&gt; &quot;Erdbeere&quot;, &quot;c&quot; =&gt; &quot;Kirsche&quot;); </codeline>
<codeline>$c = $a + $b; </codeline>
<codeline>var_dump($c); </codeline>
<codeline>/* Ausgabe: </codeline>
<codeline>array(3) { </codeline>
<codeline>  [&quot;a&quot;]=&gt; </codeline>
<codeline>  string(5) &quot;Apfel&quot; </codeline>
<codeline>  [&quot;b&quot;]=&gt; </codeline>
<codeline>  string(6) &quot;Banane&quot; </codeline>
<codeline>  [&quot;c&quot;]=&gt; </codeline>
<codeline>  string(7) &quot;Kirsche&quot; </codeline>
<codeline>} */ </codeline>
</code>
</section>
</section>
<section><section-header>Kontrollstrukturen</section-header>
<para>Wie jede andere Programmiersprache auch, wird die Ausführung von PHP-Skripten über eine Reihe von Kontrollmechanismen gesteuert.</para>
<para>In der Regel folgt auf eine solche Kontrollstruktur ein Block von Anweisungen und/oder Funktionsaufrufen. Solche Blöcke müssen in geschweifte Klammern eingeschlossen sein. Ist nur ein einzelnes Statement vorhanden, kann man auf die Klammern verzichten. Dies sollte man, angesichts der Übersichtlichkeit und in Hinblick auf mögliche spätere Ergänzungen aber besser nicht tun.</para>
<section>
<section-header>if, else, elseif</section-header>
<para>Die Möglichkeit der bedingten Ausführung von Codeteilen stellt die wohl wichtigste Möglichkeit der Programmflußkontrolle dar.</para>
<para>Bei der if-Struktur wird der in Klammern angegebene Ausdruck auf wahr geprüft. Trifft diese Bedingung zu, so wird der nachfolgende Codeteil ausgeführt, ansonsten übersprungen. Trifft die Bedingung nicht zu, so wird der (optional) in einem else-Block enthaltene Code ausgeführt, oder eine (ebenfalls optionale) elseif-Bedingung ausgewertet.</para>
<para>Die if-Strukturen können beliebig geschachtelt werden.</para>
<code>
<label>Beispiel 106: if, else, elseif</label>
<codeline>if( $a &lt; $b ){ </codeline>
<codeline>	print $b; </codeline>
<codeline>}elseif( $a &lt; $c ){ </codeline>
<codeline>	print $c; </codeline>
<codeline>}else{ </codeline>
<codeline>	print $a; </codeline>
<codeline>} </codeline>
<codeline>if( $a &gt; $b &amp;&amp; $a &lt; $c ) </codeline>
<codeline>	print &quot;a größer als b und kleiner als c&quot;; </codeline>
</code>
</section>
<section><section-header>while</section-header>
<para>Die einfachste Form einer Schleife stellt die while-Schleife dar, die genau wie in C funktioniert. Vor jedem Durchlaufen des Codeblocks wird ein Ausdruck auf wahr geprüft. Somit kommt die Schleife u.U. gar nicht zur Ausführung.</para>
<code>
<label>Beispiel 107: while-Schleife</label>
<codeline>while( $verbl_km &gt; 0 &amp;&amp; $sprit &gt; 0 ){ </codeline>
<codeline>	// gas geben </codeline>
<codeline>	$sprit -= $kilometerverbrauch; </codeline>
<codeline>	--$verbl_km; </codeline>
<codeline>	print &quot;&lt;br&gt;noch $verbl_km km...&quot;; </codeline>
<codeline>}; </codeline>
<codeline>$verbl_km == 0? </codeline>
<codeline>	print &quot;&lt;br&gt;Angekommen&quot;: </codeline>
<codeline>	print &quot;&lt;br&gt;Muss noch $verbl_km km zu fuss gehen...&quot;; </codeline>
</code>
</section>
<section><section-header>do ... while</section-header>
<para>Durch Verwendung einer do-while-Schleife wird sichergestellt, dass die Anweisungen in der Schleife zumindest einmal ausgeführt werden. Erst nach Durchlaufen der Anweisungen wird die Bedingung geprüft, und, insofern sie zutrifft, die Schleife erneut durchlaufen.</para>
<code>
<label>Beispiel 108: do-while-Schleife</label>
<codeline>$i=0; </codeline>
<codeline>do{ </codeline>
<codeline>	$i++; </codeline>
<codeline>}while( $i &lt; 10 ); </codeline>
</code>
</section>
<section><section-header>for</section-header>
<para>Die komplexeste Schleifenstruktur in PHP ist der for-Konstrukt. Er funktioniert genauso wie in C.</para>
<code>
<label>Beispiel 109: for-Schleife</label>
<codeline>for( $x=0; $x&lt;10; $x++ ){ </codeline>
<codeline>	print &quot;\$x = $x&lt;br&gt;\n&quot;; </codeline>
<codeline>} </codeline>
</code>
<para>Die Syntax für diese Struktur besteht aus dem Schlüsselwort und drei in Klammern, semikolon-getrennte Ausrücke. Der erste Ausdruck dient der Initialisierung und wird immer ausgeführt.</para>
<para>Anschliessend wird solange wie das Ergebnis der Prüfung des zweiten Ausdrucks wahr ergibt, der Codeblock, der auf die for-Anweisung folgt, ausgeführt und der dritte Ausdruck ausgewertet.</para>
<para>Alle drei Argumente sind optional anzugeben. Fehlt der zweite, so muss, um eine Endlosschleife zu verhindern, innerhalb des Anweisungsblocks, eine break-Anweisung vorhanden sein.</para>
</section>
<section><section-header>foreach</section-header>
<para>Ausschließlich für Schleifen über Arrays besteht die foreach-Schleife. Mit ihr kann sequentiell über alle Elemente eines Arrays integriert werden.</para>
<code>
<label>Beispiel 110: foreach-Schleifen</label>
<codeline>$a = array( 1, 2, 3, 4, 5 ); </codeline>
<codeline>foreach( $a as $value ) </codeline>
<codeline>	print $value; </codeline>
<codeline>$laender = array(  </codeline>
<codeline>	&quot;d&quot;=&gt;&quot;Deutschland&quot;,  </codeline>
<codeline>	&quot;f&quot;=&gt;&quot;Frankreich&quot;,  </codeline>
<codeline>	&quot;nl&quot;=&gt;&quot;Niederlande&quot;  </codeline>
<codeline>); </codeline>
<codeline>foreach( $laender as $key=&gt;$value ) </codeline>
<codeline>	print &quot;Länderkennung für $value ist $key&quot;; </codeline>
</code>
</section>
<section><section-header>switch</section-header>
<para>Mit switch ist es möglich, einen Ausdruck auf Übereinstimmung mit verschiedenen Werten zu testen.</para>
<para>Nach einer Übereinstimmung mit einem der case-Optionen, wird der angegebene Code solange ausgeführt, bis eine break-Anweisung auftritt.</para>
<para>Mit der default-Angabe, kann der Fall abgefangen werden, in der ausgewertete Ausdruck mit keinem der case-Ausdrücken erfaßt wurde.</para>
<code>
<label>Beispiel 111: switch-case-Anweisungen</label>
<codeline>switch ($i) {  </codeline>
<codeline>	case 0: 	print &quot;i ist gleich 0&quot;;  </codeline>
<codeline>				break;  </codeline>
<codeline>	case 1: 	print &quot;i ist gleich 1&quot;;  </codeline>
<codeline>	case 2: 	print &quot;i ist gleich 2&quot;;  </codeline>
<codeline>				break; </codeline>
<codeline>	default: 	print &quot;i ist weder 0, 1 noch 2&quot;;  </codeline>
<codeline>} </codeline>
</code>
</section>
<section><section-header>break, continue</section-header>
<para>break bricht die Ausführung der aktuellen for, foreach, while, do..while oder switch Anweisungssequenz ab. continue wird innerhalb von Schleifen gebraucht. Die Schleife wird an der aktuellen Stelle abgebrochen und es wird der nächste Durchlauf begonnen.</para>
<para>Einem break bzw. continue kann optional ein numerisches Argument angehängt werden, das die Anzahl der abzubrechenden Befehlssequenzen enthält bzw. angibt, wie viele Ebenen von enthaltenen Schleifen übersprungen werden sollen.</para>
<code>
<label>Beispiel 112: Schleifen mit break, continue</label>
<codeline>$arr = array (&apos;eins&apos;, &apos;zwei&apos;, &apos;drei&apos;, &apos;vier&apos;, &apos;stop&apos;, &apos;fünf&apos;); </codeline>
<codeline>foreach ($arr as $val){ </codeline>
<codeline>	if ($val == &apos;stop&apos;){ </codeline>
<codeline>		break;  /* Man kann hier auch &apos;break 1;&apos; schreiben. */ </codeline>
<codeline>	} </codeline>
<codeline>	echo &quot;$val&lt;br&gt;\n&quot;; </codeline>
<codeline>	$i = 0; </codeline>
<codeline>	while (++$i) { </codeline>
<codeline>		switch ($i) { </codeline>
<codeline>			case 5: 	echo &quot;Bei 5&lt;br&gt;\n&quot;; </codeline>
<codeline>						break 1;  /* Beendet nur switch. */ </codeline>
<codeline>			case 9: 	echo &quot;Bei 7; quitting&lt;br&gt;\n&quot;; </codeline>
<codeline>						continue 3; /* führt bei foreach fort */ </codeline>
<codeline>			case 10: 	echo &quot;Bei 10; quitting&lt;br&gt;\n&quot;; </codeline>
<codeline>						break 3; /* Beendet switch, while und foreach. */ </codeline>
<codeline>			default: 	break; </codeline>
<codeline>}}} </codeline>
<codeline>/* Ausgabe: </codeline>
<codeline>eins </codeline>
<codeline>Bei 5 </codeline>
<codeline>Bei 7; quitting </codeline>
<codeline>zwei </codeline>
<codeline>Bei 5 </codeline>
<codeline>Bei 7; quitting </codeline>
<codeline>drei </codeline>
<codeline>Bei 5 </codeline>
<codeline>Bei 7; quitting </codeline>
<codeline>vier </codeline>
<codeline>Bei 5 </codeline>
<codeline>Bei 7; quitting </codeline>
<codeline>*/ </codeline>
</code>
</section>
</section>
<section><section-header>Referenzierung</section-header>
<para>Bei der Zuweisung einer Variablen in eine andere Variable wird im Normalfall lediglich der aktuelle Inhalt der ersten Variablen in die zweite Variable kopiert - also eine Kopie des Inhalts einer Variablen einer zweiten Zugewiesen. Nach dem Vorgang agieren beide Variablen unabhängig von einander und dementsprechend wirkt sich eine Veränderung des Inhalts der einen Variablen nicht auf den der anderen Variablen aus.</para>
<para>Im Gegensatz dazu ist es möglich, eine Variablen als Referenzvariable zu nutzen. Dieser Vorgang unterscheidet sich von der Variablenreferenzierung in C, bei der Zeiger verwendet werden. Unter PHP stellt eine solche Zuweisung durch Referenzierung ein Verfahren dar, bei der die referenzierende Variable auf den gleichen Inhalt wie die ursprüngliche Variable verweist.</para>
<para>Durch eine Zuweisung auf eine der beiden verändert jeweils auch auf den Inhalt der anderen (es ist ja die selbe Stelle im Speicher, die manipuliert wird).</para>
<para>Eine Referenzvariable wird erzeugt, indem dem Namen Quellvariablen ein kaufmännisches Und-Zeichen vorangestellt wird.</para>
<code>
<label>Beispiel 113: Referenzvariablen erzeugen</label>
<codeline>$bob = &quot;Bob&quot;; </codeline>
<codeline>$alice = &quot;Alice&quot;; </codeline>
<codeline>$bob = &amp;$alice; </codeline>
<codeline>$alice = &quot;Bob&quot;; </codeline>
<codeline>print $alice; // Ausgabe: Bob </codeline>
<codeline>print $bob; // Ausgabe: Bob </codeline>
</code>
<para>Wird eine Referenzvariable mittels unset gelöscht, wird nur die Verbindung dieses Bezeichners zum Inhalt entfernt. Andere Variablen, die den gleichen Inhalt verwenden, verfügen also weiterhin über diesen.</para>
<code>
<label>Beispiel 114: Referenzvariablen löschen</label>
<codeline>unset( $alice ); </codeline>
<codeline>print $alice; // keine Ausgabe </codeline>
<codeline>print $bob; // Ausgabe: Bob </codeline>
</code>
<para>Um die unterschiedliche Funktionsweise zu C zu verdeutlichen, folgendes Beispiel:</para>
<code>
<label>Beispiel 115: Referenzvariablen ändern</label>
<codeline>$bar = &quot;inhalt von bar&quot;; </codeline>
<codeline>$var = &amp;$bar; </codeline>
<codeline>$var = &amp;$_GET; </codeline>
<codeline>print $bar; // Ausgabe: inhalt von bar </codeline>
<codeline>print $var; // Ausgabe: Array </codeline>
</code>
<para>Was in diesem Beispiel passiert, ist folgendes: $bar wird zunächst mit Inhalt in Form einer Zeichenkette versehen. Anschließen wird $var als Referenzvariable auf $bar eingeführt. Daher ist $var zunächst mit dem gleichen Inhalt verknüpft wie $bar. Durch die erneute Zuweisung an $var wird jedoch nicht der gemeinsame Inhalt von $bar und $var überschrieben, vielmehr wird der Variablenbezeichner $var an das $_GET-Array geknüpft. $bar behält also seinen Inhalt weiterhin bei - im Gegensatz zu C, wo in diesem Fall auch $bar ein Zeiger auf das $_GET-Array wäre.</para>
</section>
<section><section-header>Funktionen</section-header>
<para>Werden Programmteile häufiger benötigt, so bietet sich die Verwendung von Funktionen an. PHP unterscheidet nicht zwischen Prozeduren ohne und Funktionen mit Rückgabewert</para>
<para>Funktionen können an beliebiger Stelle im Quelltext definiert werden, unabhängig davon, an welcher Stelle sie aufgerufen werden. Die Definitionen können aber nicht überladen, überschrieben oder gelöscht werden.</para>
<para>Definiert werden Funktionen mit dem Schlüsselwort function gefolgt von einem Bezeichner, eine Parameterdeklaration eingeschlossen in Klammern und dem Anweisungsblock der Funktion eingeschlossen in geschweiften Klammern.</para>
<para>Innerhalb von Funktionen ist jeder gültige PHP-Code erlaubt, also bspw. auch die Definition weiterer Funktionen und sogar Klassen.</para>
<para>PHP-Funktionen können sich selbst rekursiv aufrufen.</para>
<section>
<section-header>Rückgabewerte</section-header>
<para>Eine Typisierung wird bei der Funktionsdeklaration nicht vorgenommen, da Funktionen per Default nicht über Rückgabewerte verfügen. Optional ist es möglich, einen beliebigen Wert mit dem Schlüsselwort return zurückzugeben. Eine return-Anweisung führt zum sofortigen Verlassen der Funktion.</para>
<code>
<label>Beispiel 116: Funktionsdefinition</label>
<codeline>function isnichtwahr(){ </codeline>
<codeline>	return false; </codeline>
<codeline>} </codeline>
</code>
</section>
<section><section-header>Aufruf-Parameter</section-header>
<para>Bei der Definition einer Funktion können erforderliche Parameter deklariert werden.</para>
<para>Für Parameter können Vorgabewerte gesetzt werden, die ihn als optional kennzeichnen. Dafür können ausschließlich Konstanten verwendet werden. Außerdem sollten, um Fehler zu vermeiden, die optionalen Parameter nach allen nicht-optionalen Parametern angegeben werden.</para>
<para>Deklarierte Parameter, die keinen Vorgabewert besitzen, müssen beim Aufruf der Funktion zwingend angegeben werden.</para>
<para>Die Parameter können nicht auf bestimmte Variablentypen festgelegt werden; auch bei solchen, die einen Vorgabewert besitzen, können Werten eines anderen Typs übergeben werden.</para>
<para>Des Weiteren ist es möglich, mehr Parameter als deklariert zu übergeben. Auf alle übergebenen Parameter können von der Hilfsfunktion func_get_args als (nicht-assoziatives) Array zurückgegeben werden. Über die Anzahl der Parameter gibt func_num_args Auskunft.</para>
<code>
<label>Beispiel 117: Funktionsparameter</label>
<codeline>function addition( $a, $b=0 ){ </codeline>
<codeline>   $result = $a; </codeline>
<codeline>   $add = func_get_args(); </codeline>
<codeline>   for( $i = 1; $i &lt; func_num_args(); $i++ ) </codeline>
<codeline>     $result += $add[$i]; </codeline>
<codeline>   return $result; </codeline>
<codeline>} </codeline>
<codeline>print addition ( 1, 2, 3 ); // ergibt 6 </codeline>
</code>
</section>
<section><section-header>Variablengültigkeit</section-header>
<para>Variablen, die im Skript definiert wurden, sind in Funktionen innerhalb des Skripts zunächst nicht direkt verfügbar.</para>
<para>Dies triff nicht auf Konstanten zu: Diese sind nach ihrer Definition sofort global verfügbar.</para>
<para>Um Variablen in Funktionen nutzbar zu machen, müssen sie explizit in diesen Kontext importiert werden.</para>
<para>Hierzu können sie über das global-Schlüsselwort direkt in den Kontext der Funktion verfügbar gemacht werden. Alternativ ist ein spezielles, globales assoziatives Array $GLOBALS verfügbar, welches alle Variablen des der Funktion umgebenden Kontextes enthält.</para>
<para>Über das Schlüsselwort static können Variablen innerhalb einer Funktion in der Form deklariert werden, dass sie zwischen zweier Aufrufe der Funktion den Wert nicht verlieren.</para>
<code>
<label>Beispiel 118: Import einer globalen Variablen, Verwendung einer static-Variablen in einer Funktion</label>
<codeline>$a = 100; </codeline>
<codeline>$b = 50; </codeline>
<codeline>$c = 25; </codeline>
<codeline>function Summe( $b ){ </codeline>
<codeline>    static $d; </codeline>
<codeline>    global $a; </codeline>
<codeline>    $d += $a + $b + $c; </codeline>
<codeline>    return $d; </codeline>
<codeline>    $d++; </codeline>
<codeline>}  </codeline>
<codeline>print Summe( $c ); </codeline>
<codeline>// Ausgabe: 125; </codeline>
<codeline>print Summe( $c ); </codeline>
<codeline>// Ausgabe: 250 (warum wohl?); </codeline>
</code>
</section>
<section><section-header>Referenzparameter und -Rückgabe</section-header>
<para>Neben der bereits erwähnten &quot;by value&quot; Methode der Parameterübergabe, unterstützt PHP die Verwendung von Parametern als &quot;by reference&quot;. Dabei wird nicht der Wert der als Parameter verwendeten Variablen übergeben, sondern eine Referenz auf die Variable selbst, so dass Änderungen am Parameter sich auch auf diese Variable auswirken.</para>
<para>Parameter, die Variablen per Referenz einbinden, müssen in der Funktionsdefinition deklariert werden und können nicht optional sein.</para>
<para>Ist ein Parameter als Referenz deklariert, dürfen beim Funktionsaufruf an seiner Stelle keine Konstanten verwendet werden.</para>
<code>
<label>Beispiel 119: Referenzparameter in einer Funktion</label>
<codeline>function addition( &amp;$a, $b=0 ){ </codeline>
<codeline>   $result = $a; </codeline>
<codeline>   $add = func_get_args(); </codeline>
<codeline>   for( $i=1; $i&lt;func_num_args(); $i++ ) </codeline>
<codeline>     $result += $add[$i]; </codeline>
<codeline>   $a = $result; </codeline>
<codeline>   return $result; </codeline>
<codeline>} </codeline>
<codeline>print addition ( addition($a=1, 5), 2, 3 ); // Ausgabe: 11 </codeline>
<codeline>print $a; // Ausgabe: 6 </codeline>
<codeline>define ( &quot;KONST&quot;, 1 ); </codeline>
<codeline>print addition ( KONST, 2, 3 );  // funktioniert nicht </codeline>
</code>
<para>Neben Verweise auf Parameter, läßt sich auch der Rückgabewert einer Funktion als Verweis deklarieren. Dabei wird die Variable, auf die der Rückgabewert zugewiesen wird, mit dem gleichen Inhalt verknüpft.</para>
<para>Referenzrückgaben von Funktionen bedürfen zweier Erweiterungen der bisherigen Syntax. Zum Einen muss dem Namen Funktion bei seiner Definition ein kaufmännisches Und vorangestellt werden. Zum Anderen muss dieses kaufmännische Und auch dem Funktionsnamen beim Aufruf der Funktion vorangestellt werden.</para>
<code>
<label>Beispiel 120: Referenz-Rückgabe einer Funktion</label>
<codeline>function &amp;addition1( &amp;$a ){ </codeline>
<codeline>	static $zaehler; </codeline>
<codeline>	$add = func_get_args(); </codeline>
<codeline>	for( $i=1; $i&lt;func_num_args(); $i++ ) </codeline>
<codeline>		$a += $add[$i]; </codeline>
<codeline>	$zaehler++; </codeline>
<codeline>	return $zaehler; </codeline>
<codeline>} </codeline>
<codeline>$a = 0; </codeline>
<codeline>$zaehler = &amp;addition1( $a, 5 ); </codeline>
<codeline>print $zaehler; // Ausgabe: 1 </codeline>
<codeline>addition1( $a, 5 ); </codeline>
<codeline>print $zaehler; // Ausgabe: 2 </codeline>
<codeline>print $a; // Ausgabe: 10 </codeline>
<codeline> </codeline>
<codeline>function &amp;addition2( &amp;$a ){ </codeline>
<codeline>	$add = func_get_args(); </codeline>
<codeline>	for( $i=1; $i&lt;func_num_args(); $i++ ) </codeline>
<codeline>		$a += $add[$i]; </codeline>
<codeline>	return $a; </codeline>
<codeline>} </codeline>
<codeline>$a = 0; </codeline>
<codeline>$zaehler = &amp;addition2( $a, 5 ); </codeline>
<codeline>print $zaehler; // Ausgabe: 5 </codeline>
<codeline>addition2( $a, 5 ); </codeline>
<codeline>print $zaehler; // Ausgabe: 10 </codeline>
<codeline>print $a; // Ausgabe: 10 </codeline>
</code>
</section>
<section><section-header>Variablenfunktionen</section-header>
<para>Wenn an das Ende einer Variablen Klammern angehängt werden, versucht PHP eine Funktion aufzurufen, die mit dem Namen gekennzeichnet ist, die dem Inhalt der Variablen entspricht.</para>
<code>
<label>Beispiel 121: Variablenfunktionen</label>
<codeline>function foo(){ </codeline>
<codeline>    echo &quot;In foo()&lt;br&gt;\n&quot;; </codeline>
<codeline>} </codeline>
<codeline>function bar($arg = &apos;&apos;){ </codeline>
<codeline>    echo &quot;In bar(); der Parameter ist &apos;$arg&apos;.&lt;br&gt;\n&quot;; </codeline>
<codeline>} </codeline>
<codeline>$func = &apos;foo&apos;; </codeline>
<codeline>$func();        // Dies ruft foo() auf </codeline>
<codeline>$func = &apos;bar&apos;; </codeline>
<codeline>$func(&apos;test&apos;);  // Dies ruft bar() mit Parameter &apos;test&apos; auf </codeline>
</code>
<para>Das gleiche funktioniert im Übrigen auch mit Klassenmethoden.</para>
</section>
</section>
<section><section-header>Code-Bibliotheken include/require</section-header>
<para>Damit Code wiederverwendet werden kann, und damit einzelne Skripte übersichtlich bleiben, müssen Teile der Skripte in Bibliotheken ausgelagert werden können. PHP bietet hierzu zwei Methoden, in jeweils zwei Variationen.</para>
<para>Durch Anwendung von include und require kann in externen Dateien ausgelagerter Code in den Kontext des Skripts importiert werden. Die Verwendung ist an jeder Stelle im Quelltext erlaubt, an der normale Anweisungen stehen können.</para>
<para>Die beiden Pendants require_once und include_once verhindern ein mehrfaches Einbinden der selben Datei.</para>
<para>Die Methoden include und require unterscheiden sich lediglich in einer Hinsicht: Wird versucht, eine fehlende Datei mittels require einzubinden, endet das Skript mit einem &quot;fatal error&quot;, während das selbe mittels include lediglich eine Warnung produziert; das Skript wird jedoch weiter ausgeführt.</para>
<para>Wird eine Datei mittels diesen Funktionen eingebunden, wird dessen Inhalt von PHP an die Stelle der Anweisung eingefügt. Für den PHP-Code der eingebundenen Datei gilt der Variablenkontext der Stelle im aufrufenden Skript, an der er eingebunden wurde.</para>
<para>Soll PHP-Quellcode eingebunden werden, so ist dieser, wie in einer normalen Skript-Datei, in PHP-Tags einzuschließen, da PHP vom parsenden in den HTML-Modus zurückschaltet.</para>
<code>
<label>Beispiel 122: Einfaches Inkludieren</label>
<codeline>vars.php &lt;?php </codeline>
<codeline>$color = &apos;green&apos;; </codeline>
<codeline>$fruit = &apos;appel&apos;; </codeline>
<codeline>?&gt; </codeline>
<codeline>test.php &lt;?php </codeline>
<codeline>echo &quot;A $color $fruit&quot;; // Ausgabe: A </codeline>
<codeline>include &apos;vars.php&apos;; </codeline>
<codeline>echo &quot;A $color $fruit&quot;; // Ausgabe: A green apple </codeline>
<codeline>?&gt; </codeline>
</code>
<code>
<label>Beispiel 123: Inludieren innerhalb einer Funktion</label>
<codeline>vars.php </codeline>
<codeline>&lt;?php </codeline>
<codeline>$color = &apos;green&apos;; </codeline>
<codeline>$fruit = &apos;appel&apos;; </codeline>
<codeline>?&gt; </codeline>
<codeline>test.php  </codeline>
<codeline>&lt;?php </codeline>
<codeline>function foo(){ </codeline>
<codeline>	global $color; </codeline>
<codeline>	include &apos;vars.php&apos;; </codeline>
<codeline>	echo &quot;A $color $fruit&quot;; </codeline>
<codeline>} </codeline>
<codeline>foo();                    // Ausgabe: A green apple </codeline>
<codeline>echo &quot;A $color $fruit&quot;;   // Ausgabe: A green </codeline>
<codeline>?&gt; </codeline>
</code>
</section>
<section><section-header>Datenübergabe mittels HTML-Formularen</section-header>
<para>Die gebräuchlichste Form, Eingaben von Benutzern abzufragen, ist die Verwendung von HTML-Formularen. Die Formulareingaben, die vom Client abgesendet wurden, stehen in PHP - je nach Einstellung des PHP-ini-Wertes register_globals - automatisch als globale Variablen zur Verfügung. Ist diese Direktive deaktiviert, sind die Informationen noch über die bereits bekannten $HTTP_ENV_VARS und den anderen Umgebungsarrays erreichbar (insofern die Direktive track_vars aktiviert ist).</para>
<section>
<section-header>Das Formular</section-header>
<para>Die Eingaben aus einem Formular sind unter dem Namen des Formularelements abgelegt. Je nach Submit-Methode des Formulars sind die Werte als POST- oder GET-Variablen abgelegt.</para>
<para>Die POST-Methode ist allerdings nicht wesentlich besser für die ungeschützte Übertragung sensibler Informationen geeignet. Beide Verfahren übermitteln die Daten im Klartext, bei der GET-Methode jedoch als Query-String in der URL, und somit direkt für den Benutzer sichtbar. Datensicherheit muss für beide Verfahren mittels Protokolle auf anderer Ebene umgesetzt werden (HTTPS bspw.).</para>
<para>Über den GET-Parameter als URL-Bestandteil können typischerweise nur 2048 Zeichen übertragen werden. Daher sollte man, wenn mehr Daten anfallen werden auf die POST-Methode ausweichen.</para>
<para>Die Verwendung von POST-Formularen ist zwingend erforderlich, wenn Daten als Datei übertragen werden sollen.</para>
<para>Für die Verwendung von Eingabeelementen innerhalb einer HTML-Seite, wird ein Formularkontainer mit dem HTML-Element form. Die wesentlichen Attribute action, method und enctype steuern, wohin die Informationen gesendet werden, in welcher Weise (POST/GET) und die Kodierung. enctype ist nur von Bedeutung, wenn über das Formular Dateien hochgeladen werden sollen.</para>
<para>Ein Formular kann auf verschiedene Weisen abgeschickt werden. Gebräuchlich ist die Verwendung einer entsprechenden submit-Schaltfläche, alternativ kann bspw. über JavaScript ein Submit ausgelöst werden. Häufig fügt man zusätzlich zum submit- auch ein reset-Button ein.</para>
<para>Sind mehrere Formulare auf einer HTML-Seite eingefügt worden, so werden lediglich die Daten aus dem Formular übermittelt, dessen submit-Methode aufgerufen wurde.</para>
<code>
<label>Beispiel 124: Einfachstes Formular</label>
<codeline>&lt;form action=&quot;&lt;?=$_SERVER[&quot;PHP_SELF&quot;];?&gt;&quot; method=&quot;post&quot;&gt; </codeline>
<codeline>	&lt;input type=&quot;text&quot; name=&quot;inputtext&quot;  </codeline>
<codeline>		value=&quot;&lt;?php </codeline>
<codeline>			if(isset($_POST[&quot;inputtext&quot;])) </codeline>
<codeline>				print $_POST[&quot;inputtext&quot;]; </codeline>
<codeline>		?&gt;&quot;&gt; </codeline>
<codeline>	&lt;input type=&quot;submit&quot; name=&quot;senddata&quot; value=&quot;Absenden&quot;&gt; </codeline>
<codeline>	&lt;input type=&quot;reset&quot; value=&quot;Zurücksetzen&quot;&gt; </codeline>
<codeline>&lt;/form&gt; </codeline>
</code>
<para>Nach Submit dieses Formulars sind im Skript die Elemente senddata und inputtext des $_POST-Arrays mit den entsprechenden Werten des Formulars belegt.</para>
<para>Die gebräuchlichste Methode ist wohl das Absenden der Formulardaten auf das gleiche Skript (Affenformular). Eine andere Möglichkeit als Ziel für das Formular stellt eine Email-Adresse dar. Diese wird im action-Attribut in der Form &quot;mailto:emailadresse@host.tld&quot; angegeben.</para>
</section>
<section><section-header>Eingabe-Elemente</section-header>
<section>
<section-header>text, textarea</section-header>
<para>Für die Eingabe von Textdaten eignen sich diese beiden Eingabeelemente.</para>
<code>
<label>Beispiel 125: text</label>
<codeline>&lt;input type=&quot;text&quot;	name=&quot;texteingabe&quot;  </codeline>
<codeline>						value=&quot;eingabe&quot; maxlength=&quot;30&quot; size=&quot;10&quot;&gt; </codeline>
</code>
<para>Das input-Element des Typs text erhält den Namen &quot;texteingabe&quot; und den Vorgabewert &quot;eingabe&quot;. Das Element wird als zehn Zeichen breites Textfeld dargestellt, das Eingaben bis zu einer Länge von 30 Zeichen fassen kann. Außer type sind alle Attribute optional anzugeben.</para>
<para>Soll dem Benutzer eine größere Eingabe ermöglicht werden, eignen sich textarea&apos;s besser als Eingabezeilen.</para>
<para>Die Verwendung eines input-Elements des Typs password erlaubt die Blindeingabe von Texten. Dies ist jedoch reine Kosmetik da sowohl die Vorgabewerte als auch die Eingaben in Klartext durchs Internet übertragen werden. Die Vorgabe steht außerdem im Klartext in der HTML-Seite. Ein Ausweg stellt eine JavaScript-Funktion dar, die einen verschlüsselten Wert erhält und in das Eingabeelement schreibt, sowie eines, das, sobald das Formular abgesendet wird, die Eingabe des Feldes wiederum verschlüsselt.</para>
<code>
<label>Beispiel 126: textarea</label>
<codeline>&lt;textarea name=&quot;texteingabe&quot; cols=&quot;100&quot; rows=&quot;5&quot;&gt;Vorgabe&lt;/textarea&gt; </codeline>
</code>
<para>Die Eingabelänge eines textarea-Elements ist nicht eingeschränkt. Im Beispiel wird die Textbox als fünfzeilige Fläche dargestellt, bei einer Breite von 100 Zeichen. Je nach Browser wird außerdem eine vertikale Laufleiste angezeigt. Über ein weiteres Attribut namens wrap läßt sich der Zeilenumbruch innerhalb des Eingabefeldes steuern. Ein Textfeld kann über das readonly-Attribut (readonly=&quot;readonly&quot;) als nur-lesen-Element dargestellt werden.</para>
</section>
<section><section-header>checkbox, radiobutton</section-header>
<para>Eine checkbox bietet die Möglichkeit, eine oder mehrere verschiedene angebotenen Optionen auszuwählen (siehe auch: select multiple). Der radiobutton wird in Gruppen von Optionen verwendet, von denen genau eine auszuwählen ist (siehe auch: select).</para>
<code>
<label>Beispiel 127: checkbox</label>
<codeline>&lt;input type=&quot;checkbox&quot; name=&quot;Option[]&quot;  </codeline>
<codeline>				checked=&quot;checked&quot; value=&quot;1&quot;&gt; Option 1 </codeline>
<codeline>&lt;input type=&quot;checkbox&quot; name=&quot;Option[]&quot; value=&quot;2&quot;&gt; Option 2 </codeline>
<codeline>&lt;input type=&quot;checkbox&quot; name=&quot;Option2&quot; value=&quot;2&quot;&gt; Option 2 </codeline>
</code>
<para>Die Rückgabewerte werden aufgrund der eckigen Klammern im Namen in ein Array zusammengefaßt. Dies entspricht dem Hinzufügen von Elementen durch $a[]=$wert.</para>
<para>Ist eine checkbox nicht ausgewählt, wird auch keine Variable mit diesem Namen erzeugt.</para>
<para>Um die Gruppierung von radiobutton&apos;s vorzunehmen, bekommen alle, die zur Gruppe gehören sollen den gleichen Namen.</para>
<code>
<label>Beispiel 128: radiobutton</label>
<codeline>&lt;input type=&quot;radiobutton&quot; name=&quot;Option&quot; checked=&quot;checked&quot;&gt; Option 1 </codeline>
<codeline>&lt;input type=&quot;radiobutton&quot; name=&quot;Option&quot;&gt; Option 2 </codeline>
</code>
</section>
<section><section-header>select, select multiple</section-header>
<para>Mit diesen Elementen ist es möglich, Auswahl- und Dropdownlisten zu erstellen. Durch die Verwendung von multiple erlaubt man eine Mehrfachauswahl der Einträge in der Liste. Das Attribut size entscheidet, ob eine Dropdownliste angezeigt wird, oder ob ein Listenfeld mit den Auswahloptionen erscheint.</para>
<code>
<label>Beispiel 129: dropdown-liste</label>
<codeline>&lt;select name=&quot;zahlungsart&quot; size=&quot;1&quot;&gt; </codeline>
<codeline>	&lt;option value=&quot;Mastercard&quot;&gt;Mastercard&lt;/option&gt; </codeline>
<codeline>	&lt;option value=&quot;Visa&quot;&gt;Visa&lt;/option&gt; </codeline>
<codeline>	&lt;option value=&quot;AmericanExpress&quot;&gt;American Express&lt;/option&gt; </codeline>
<codeline>&lt;/select&gt; </codeline>
</code>
<code>
<label>Beispiel 130: dropdown-liste</label>
<codeline>&lt;select name=&quot;sprachen[]&quot; size=&quot;3&quot; multiple=&quot;multiple&quot;&gt; </codeline>
<codeline>	&lt;option value=&quot;deutsch&quot;&gt;Deutsch&lt;/option&gt; </codeline>
<codeline>	&lt;option value=&quot;englisch&quot;&gt;Englisch&lt;/option&gt; </codeline>
<codeline>	&lt;option value=&quot;niederländisch&quot;&gt;Niederländisch&lt;/option&gt; </codeline>
<codeline>	&lt;option value=&quot;französisch&quot;&gt;Französisch&lt;/option&gt; </codeline>
<codeline>&lt;/select&gt; </codeline>
</code>
</section>
<section><section-header>file-upload</section-header>
<para>Mit Formularen lassen sich bequem Dateien zum Server schicken. Dort angekommen, landen die Dateien zunächst im Verzeichnis, welches in der PHP-ini als uploadtemp angegeben wurde.</para>
<para>Ein Formular, welches Dateien hochladen soll, muss im enctype-Attribut den Wert multipart/form-data haben. Außerdem muss ein input-Element mit dem Namen MAX_FILE_SIZE vorhanden sein. Der Wert dieses Elements stellt die maximale Größe der Datei in Bytes dar, die hochgeladen werden kann. In diesem Zusammenhang sei darauf hingewiesen, dass eine Datei zwar hochgeladen werden kann, aber trotzdem von PHP nicht angenommen wird; nämlich dann, wenn in der PHP-ini der Wert für die maximale Dateigröße kleiner ist, als die im Formular angegebene.</para>
<para>Es ist nicht möglich, mit einem file-Element mehrere Dateien gleichzeitig hochzuladen. Für jede Datei muss also ein file-Element vorhanden sein.</para>
<code>
<label>Beispiel 131: file</label>
<codeline>&lt;form action=&quot;&lt;?=$_SERVER[&quot;PHP_SELF&quot;];?&gt;&quot; method=&quot;post&quot;  </codeline>
<codeline>	enctype=&quot;multipart/form-data&quot;&gt; </codeline>
<codeline>&lt;input type=&quot;hidden&quot; name=&quot;MAX_FILE_SIZE&quot; value=&quot;4096&quot;&gt; </codeline>
<codeline>&lt;input type=&quot;file&quot; name=&quot;A&quot;&gt; </codeline>
<codeline>&lt;input type=&quot;file&quot; name=&quot;B&quot;&gt; </codeline>
<codeline>&lt;input type=&quot;submit&quot;&gt; </codeline>
<codeline>&lt;/form&gt; </codeline>
<codeline>/* Inhalt von  </codeline>
<codeline>$_FILES: </codeline>
<codeline>Array( </codeline>
<codeline>    [A] =&gt; Array </codeline>
<codeline>        ( </codeline>
<codeline>            [name] =&gt; AUTOEXEC.BAK </codeline>
<codeline>            [type] =&gt; text/plain </codeline>
<codeline>            [tmp_name] =&gt; D:\WEBSERVER\php\php2154.TMP </codeline>
<codeline>            [error] =&gt; 0 </codeline>
<codeline>            [size] =&gt; 329 </codeline>
<codeline>        ) </codeline>
<codeline> </codeline>
<codeline>    [B] =&gt; Array </codeline>
<codeline>        ( </codeline>
<codeline>            [name] =&gt; AUTOEXEC.BAT </codeline>
<codeline>            [type] =&gt; application/octet-stream </codeline>
<codeline>            [tmp_name] =&gt; D:\WEBSERVER\php\php2155.TMP </codeline>
<codeline>            [error] =&gt; 0 </codeline>
<codeline>            [size] =&gt; 331 </codeline>
<codeline>        ) </codeline>
<codeline>) </codeline>
<codeline>*/ </codeline>
</code>
<para>Im assoziativen Array $_FILES bzw. $HTTP_POST_FILES sind nach Absenden eines entsprechenden Formulars einige Informationen zu der hochgeladenen Datei gespeichert.</para>
<para>Das Arrayelement name enthält den ursprünglichen Dateinamen, type die Übertragungsart, size die Dateigröße, tmp_name den Namen unter dem die Datei auf dem Server vorliegt und error einen Hinweis auf Übertragungsfehler.</para>
<para>Die temporären Dateien sind im übrigen derart temporär, als dass sie bereits nach Ablauf des target-Skripts des sendenden Formulars von PHP wieder gelöscht werden. Daher müssen sie an eine andere Stelle kopiert werden. Dazu können die beiden Methoden is_uploaded_file und move_uploaded_file verwendet werden.</para>
<code>
<label>Beispiel 132: is_uploaded_file, move_uploaded_file</label>
<codeline>foreach($_FILES as $ufile ) </codeline>
<codeline>if( $ufile[&quot;error&quot;]==0){ </codeline>
<codeline>	if( is_uploaded_file( $ufile[&quot;tmp_name&quot;] ) ) </codeline>
<codeline>		move_uploaded_file( $ufile[&quot;tmp_name&quot;], $ufile[&quot;name&quot;] ); </codeline>
<codeline>} </codeline>
</code>
<para>Das Beispiel durchläuft das Array der hochgeladenen Dateien und kopiert die temporären Versionen unter dem Originalnamen in das Skriptverzeichnis. Zuvor wird mittels is_uploaded_file nochmals explizit geprüft, ob es sich tatsächlich um eine hochgeladene Datei handelt. Eigentlich überflüssig in diesem Zusammenhang, da move_uploaded_file keine Dateien kopiert, die nicht hochgeladen wurden.</para>
</section>
</section>
</section>
<section><section-header>Sessions</section-header>
<para>Da HTTP zunächst ein zustandsloses Protokoll ist, ist es nicht möglich, zu erkennen, ob zwei Seitenabrufe zusammenhängen oder nicht. Jeder Request wird für autonom behandelt.</para>
<para>Da es aber sinnvoll sein kann, bestimmte Informationen zwischen zu speichern, die ein Benutzer bereits mitgeteilt hat (oder die sich aus Benutzereingaben ergeben haben).</para>
<para>Das Problem dabei ist, dass das HTTP-Protokoll für die eindeutige Identifizierung eines Requests keine zuverlässigen Methoden zur Verfügung stellt.</para>
<section>
<section-header>Eindeutige Sitzungen</section-header>
<para>Den Clients werden dynamische IP zugewiesen, wenn sie nicht über eine Standleitung mit dem Internet verbunden sind. Diese IP&apos;s wechseln durch einen Reconnect des Clients. Die IP ist nicht eindeutig wenn die Kommunikation über ein Loadbalancer-Proxy erfolgt, der die Anfragen von Clients auf mehrere Server verteilt (im Grunde sieht der Webserver nur die IP&apos;s der Proxys).</para>
<para>Außerdem können auf dem der IP zugehörigen Gerät mehrere Clients (Browser-Instanzen) aktiv sein.</para>
<para>Aus diesen Gründen muss dem Client eine eindeutige ID zugeordnet und auch übermittelt werden, der diese anschliessend jeweils dem Server mitteilt, wenn ein Request erfolgt.</para>
<para>PHP kann automatisch Session-ID&apos;s erzeugen und dem Client übermitteln. Für die Übermittlung von und zum Client bieten sich zwei Methoden an: Per Cookie oder per GET-Parameter.</para>
<para>Der Nachteil der URL-Kodierung liegt in der Sichtbarkeit. Wenn eine URL mit Session-ID gebookmarkt wird, und später auf diesen Bookmark zurückgegriffen wird, ist die Sitzung ungültig, und der Benutzer gelangt nicht dahin, wo der Bookmark ihn hätte hinbringen sollen.</para>
<para>Für beide Methoden gilt: Sie sind im Netz sichtbar und können abgehört werden (wenn nicht HTTPS eingesetzt wird). Somit ist es möglich die Session-ID zu stehlen und gleichfalls auf diese Sitzung und den darin enthaltenen Daten und Optionen zu zu greifen.</para>
</section>
<section><section-header>Datenspeicherung</section-header>
<para>Nach Beendigung eines Skripts, das eine Session benutzt, werden die als Sessionvariablen gekennzeichneten Variablen von PHP serialisiert und gespeichert. Bei einem folgenden Request mit der gleichen Session-ID wird zunächst geprüft, ob die Session noch gültig ist und anschliessend die serialisierten Informationen wieder in Variablen umgewandelt (je nach PHP-ini-Einstellung).</para>
<para>Zudem sind sämtliche Variablen immer im assoziativen Array $_SESSION verfügbar. Prinzipiell sollte man, wenn man mit Sitzungsvariablen arbeitet, dieses Array verwenden.</para>
<para>Eine Garbagecollection sorgt dafür, dass abgelaufene Sitzungen ordnungsgemäß entsorgt werden.</para>
<para>Die Daten einer Sitzung werden standardmäßig im Dateisystem hinterlegt. Dazu wird für jede Sitzung eine Datei erzeugt, der die serialisierten Variablen enthält.</para>
<para>Die Verwaltung der Sitzungen kann aber auch vom Skript selbst übernommen werden. Damit wird es möglich, die Serialisierung und Speicherung der Daten selbst umzusetzen. Das macht insbesondere dann Sinn, wenn Loadbalancing-Systeme eingesetzt werden (also mehrere Webserver), die Requests einer einzelnen Sitzung bedienen können müssen. Werden in dieser Konstellation die Sitzungsdaten in einer für beide Webserver verfügbare Datenbank abgelegt, ist die Sache zudem performanter als wenn die Daten im Dateisystem abgelegt werden.</para>
</section>
<section><section-header>Anwendung von Sitzungen</section-header>
<para>Über die Methode session_start wird die Sitzung initialisiert. Diese Methode muss aufgerufen werden, bevor irgendwelche Ausgaben an den Client geschickt werden, da die Möglichkeit gegeben sein muss, ein Cookie zu zu stellen.</para>
<para>Mittels session_register werden Variablen als Sitzungsvariablen registriert, die von PHP in der Sitzung gespeichert und beim nächsten Sitzungsstart wiederhergestellt werden. session_unregister entfernt die übergebenen Variablen aus der Liste. Diese Liste ist im assoziativen Array $_SESSION verfügbar.</para>
<para>Über die Funktion session_id bekommt man die Session-ID ausgegeben.</para>
<para>session_destroy zerstört alle in der Sitzung registrierten Variablen und die Sitzung wird ungültig. Mittels session_unset (besser ist unset($_SESSION)) werden alle Sitzungsvariablen gelöscht.</para>
<para>Durch die restriktive Einstellungen von PHP ist jedoch die ausschließliche Verwendung von $_SESSION-Array zu bevorzugen, und sich nicht darauf zu verlassen, dass Variablen, die an session_register übergeben wurden tatsächlich verfügbar sind.</para>
</section>
</section>
<section><section-header>Permanente Datensicherung</section-header>
<para>Die bisherige Betrachtung von PHP beschränkte sich auf Informationen, die lediglich während der Laufzeit eines Skriptes oder höchstens während des Verlaufs einer Sitzung vorgehalten werden mussten.</para>
<para>Jedoch kommt es häufig vor, Informationen so zu speichern, dass sie (selektiv) wieder zugänglich gemacht werden können. Zunächst muss unterschieden werden, ob die Daten beim Benutzer oder auf dem Server gespeichert werden sollen.</para>
<para>Für die Speicherung der Informationen beim Benutzer bieten sich zwei Methoden an: Die Speicherung von Cookies und der explizite Download von Datendateien durch den Benutzer, die zu einem anderen Zeitpunkt (in veränderter Form) auf den Server hochgeladen werden.</para>
<section>
<section-header>Cookies</section-header>
<para>Die Verwendung von Cookies wird, mitunter nicht zu unrecht, im Bewußtsein des Anwenders mit dem Begriff Ausspionieren assoziiert. Doch tatsächlich lassen sich Cookies nur mit sehr großem Aufwand dazu verwenden, die Wege des Benutzers durch das Internet nachvollziehen. Um dies zu verstehen, muss man sich zunächst mit dem Mechanismus der Cookies vertraut machen.</para>
<para>Ein Cookie ist ein, in seiner Größe limitierte, Datenpaket, welches vom Server an den Client gesendet werden kann. Der Client ist in der Lage, dieses Cookie zu speichern oder zu verwerfen. Wird eine Adresse im Internet erneut besucht, sendet der Client bei seinem Request automatisch die Informationen des Cookies, welches er von diesem Server erhalten und gespeichert hatte, mit an den Server. Verschiedene Clients auf einem Rechner teilen sich im Übrigen die Cookies nicht; jeder Client verwaltet eine eigene Cookie-Sammlung.</para>
<para>Dies bedeutet, dass ein Server jeweils nur diejenigen Cookies (bzw. deren Inhalte) zu Gesicht bekommt, die er selbst an den spezifischen Client gesendet hatte.</para>
<para>Der Benutzer ist jederzeit in der Lage, den Inhalt eines Cookies zu überprüfen (selten jedoch die Bedeutung der Informationen), und die Cookies zu entfernen.</para>
<para>Wenn Cookies im Rahmen einer Internetpräsenz eingesetzt werden sollen, so sollte man sich also dessen Bewußt sein, dass Cookies abgelehnt werden, zwischen zwei Besuchen gelöscht werden und ein Benutzer mit verschiedenen Clients arbeiten könnte. Daher ist es wichtig, dass entsprechende Fallback-Methoden implementiert werden, die solche Situationen abfangen.</para>
<section>
<section-header>Setzen und Löschen von Cookies</section-header>
<para>Zur Speicherung von Cookies wird die Funktion setcookie verwendet. Da Cookies teil des HTTP-Headers sind, muss diese Funktion entsprechend aufgerufen werden, bevor irgendwelche anderen Ausgaben erzeugt werden.</para>
<code>
<label>Beispiel 133: setcookie</label>
<codeline>setcookie (&quot;TestCookie1&quot;, &quot;Test Value&quot;); </codeline>
<codeline>setcookie (&quot;TestCookie2&quot;, $value, time()+3600); </codeline>
<codeline>setcookie (&quot;TestCookie3&quot;, $value, time()+3600, </codeline>
<codeline>		&quot;/~rasmus/&quot;, &quot;.utoronto.ca&quot;,1); </codeline>
</code>
<para>Das erste im Beispiel gesetzte Cookie enthält, gekoppelt an dem Bezeichner &quot;TestCookie1&quot; den wert &quot;Test Value&quot;. Weitere Informationen sind optional und werden beispielhaft in den beiden Cookies &quot;TestCookie2&quot; und &quot;TestCookie3&quot; verdeutlicht.</para>
<para>Über den dritten Parameter läßt sich die Gültigkeitsdauer eines Cookies festlegen. Dabei wird ein Integerzahl eines UNIX-Zeitstempels übergeben, zu welcher das Cookie gelöscht werden soll. Das Setzen eines UNIX-Timestamps in der Vergangenheit führt zu einem sofortigen Löschen des Cookies durch den Client.</para>
<para>Über die zwei nächsten Parameter läßt sich das Cookie an ein bestimmtes Verzeichnis bzw. eine bestimmte Domain binden. Der letzte Parameter bestimmt, ob ein Cookie nur über sichere Verbindungen gesendet werden darf. In diesem Fall wird die Zahl 1 angegeben.</para>
<para>Es können beliebig viele Cookies durch den Server gesetzt werden.</para>
</section>
<section><section-header>Lesen von Cookieinformationen</section-header>
<para>Je nach Einstellung der PHP-ini werden in Cookies gespeicherte Informationen automatisch in Variablen mit dem Namen des Cookies umgewandelt. Ist diese Funktionalität deaktiviert, sind die Informationen noch im $HTTP_COOKIE_VARS- und dem $_COOKIE-Array gespeichert.</para>
</section>
</section>
<section><section-header>Dateien</section-header>
<para>Von PHP-Skripten aus ist es möglich, auf das Dateisystem von Servern zu zu greifen, entsprechende Berechtigungen für die PHP-Instanz vorausgesetzt. Das heißt in aller Regel, dass Lese- und Schreibberechtigungen auf dem lokalen Server vorliegen, allerdings nicht unbedingt in allen Verzeichnissen. Auch der lesende Zugriff auf entfernte Verzeichnisse ist entsprechend möglich (solange dies der entsprechende Server gestattet).</para>
<para>In PHP sind eine ganze Reihe von Funktionen implementiert, die auf den Umgang mit Dateien ausgelegt sind. An dieser Stelle soll nur das grundlegende Lesen und Schreiben von Inhalten näher beleuchtet werden.</para>
<section>
<section-header>Grundlegender Dateizugriff</section-header>
<para>Dateizugriffe werden i.A. über Streams ermöglicht. Ein Stream auf eine Datei wird erzeugt, indem man die Datei in einem bestimmten Modus öffnet. Dazu wird die Funktion fopen verwendet, die eine Ressourcen-ID zurückgibt, welche in einer Variablen gespeichert werden sollte, um nachfolgend Operationen auf die geöffnete Datei ausführen zu können.</para>
<code>
<label>Beispiel 134: Dateien lesen</label>
<codeline>$fp = fopen ( &quot;datei.dat&quot;, &quot;rb&quot; ); </codeline>
<codeline>$dateiinhalt = fread( $fp, file_size( &quot;datei.dat&quot; ) ); </codeline>
<codeline>fclose( $fp ); </codeline>
</code>
<para>Der angegebene Dateiname kann entweder einen relativen oder absoluten Pfad oder eine URL enthalten. Der zweite Parameter von fopen beschreibt den Modus, in dem die Datei geöffnet werden soll.</para>
<table>
<tr>
<th><para>Modus</para>
</th>
<th><para>Effekt</para>
</th>
</tr>
<tr>
<td><para>&apos;r&apos;</para>
</td>
<td><para>Öffnet die Datei nur zum Lesen und positioniert den Dateizeiger auf den Anfang der Datei.</para>
</td>
</tr>
<tr>
<td><para>&apos;r+&apos;</para>
</td>
<td><para>Öffnet die Datei zum Lesen und Schreiben und setzt den Dateizeiger auf den Anfang der Datei.</para>
</td>
</tr>
<tr>
<td><para>&apos;w&apos;</para>
</td>
<td><para>Öffnet die Datei nur zum Schreiben und setzt den Dateizeiger auf den Anfang der Datei sowie die Länge der Datei auf 0 Byte. Wenn die Datei nicht existiert wird versucht sie anzulegen.</para>
</td>
</tr>
<tr>
<td><para>&apos;w+&apos;</para>
</td>
<td><para>Öffnet die Datei zum Lesen und Schreiben und setzt den Dateizeiger auf den Anfang der Datei sowie die Länge der Datei auf 0 Byte. Wenn die Datei nicht existiert, wird versucht sie anzulegen.</para>
</td>
</tr>
<tr>
<td><para>&apos;a&apos;</para>
</td>
<td><para>Öffnet die Datei nur zum Schreiben. Positioniert den Dateizeiger auf das Ende der Datei. Wenn die Datei nicht existiert, wird versucht sie anzulegen.</para>
</td>
</tr>
<tr>
<td><para>&apos;a+&apos;</para>
</td>
<td><para>Öffnet die Datei zum Lesen und Schreiben. Positioniert den Dateizeiger auf das Ende der Datei. Wenn die Datei nicht existiert, wird versucht sie anzulegen.</para>
</td>
</tr>
<label>Tabelle 27: Datei-Stream-Modi</label>
</table>
<para>Der Modusbezeichner kann um den Buchstaben b ergänzt werden, um anzuzeigen, dass es sich bei der zu öffnenden Datei um eine Binärdatei handelt. Dies ist allerdings nur von Nutzen auf Systemen, die zwischen Text- und Binärdateien unterscheiden.</para>
<para>Die zum Lesen der Datei verwendete Funktion fread eignet sich zum Lesen von Binärdaten aus einer Datei. Sie ließt so viele Bytes wie im zweiten Parameter angegeben bzw. bis zum Ende der Datei (je nach dem, was zuerst auftritt).</para>
<para>Analog der Vorgehensweise zum Lesen von Dateien werden Dateien geschrieben. Auch bei fwrite kann ein Längenparameter angegeben werden, welcher allerdings optional ist.</para>
<code>
<label>Beispiel 135: Dateien schreiben</label>
<codeline>$fp = fopen ( &quot;datei.dat&quot;, &quot;wb&quot; ); </codeline>
<codeline>fwrite( $fp, $dateiinhalt ); </codeline>
<codeline>fclose( $fp ); </codeline>
</code>
</section>
<section><section-header>Schneller Zugriff</section-header>
<para>Neben der Zugriffsmöglichkeit über Streams zum Lesen von Dateien gibt es die Funktionen file, file_get_contents und readfile, die jeweils eine Datei ohne weiteres Zutun einlesen. Dabei gibt file den Inhalt der Datei als Array zurück, wobei jedes Array-Element eine Zeile in der Datei repräsentiert. file_get_contents funktioniert gibt den Inhalt als String zurück. Die Funktion readfile gibt den Inhalt der Datei auf der Standardausgabe aus und als Ergebnis die Anzahl der ausgegebenen Bytes.</para>
</section>
<section><section-header>Weitere Dateisystem-Funktionen</section-header>
<para>Weitere, oft benötigte, Funktionen zum Umgang mit dem Dateisystem sind folgende:</para>
<table>
<tr>
<th><para>Funktion</para>
</th>
<th><para>Zweck</para>
</th>
</tr>
<tr>
<td><para>int copy ( string source, string dest )</para>
</td>
<td><para>Kopiert eine Datei</para>
</td>
</tr>
<tr>
<td><para>int unlink ( string filename )</para>
</td>
<td><para>Löscht eine Datei (Synonym: delete)</para>
</td>
</tr>
<tr>
<td><para>string dirname ( string path )</para>
</td>
<td><para>Extrahiert den Verzeichnisnamen</para>
</td>
</tr>
<tr>
<td><para>string basename ( string path [, string suffix] )</para>
</td>
<td><para>Extrahiert den Dateinamen</para>
</td>
</tr>
<tr>
<td><para>bool file_exists ( string filename )</para>
</td>
<td><para>Prüft, ob eine Datei vorhanden ist</para>
</td>
</tr>
<tr>
<td><para>array glob ( string pattern [, int flags] )</para>
</td>
<td><para>Findet Pfadnamen nach angegebenem Muster</para>
</td>
</tr>
<tr>
<td><para>bool rename ( string oldname, string newname )</para>
</td>
<td><para>Benennt eine Datei um</para>
</td>
</tr>
<tr>
<td><para>int filesize ( string filename )</para>
</td>
<td><para>Gibt die Größe der Datei in Byte zurück</para>
</td>
</tr>
<label>Tabelle 28: Dateisystem-Funktionen</label>
</table>
</section>
<section><section-header>Verzeichnis-Funktionen</section-header>
<para>Zum Navigieren durch Verzeichnissen stellt PHP ein kleine Auswahl an Funktionen zur Verfügung. Im Grunde sind die von Bedeutung im folgenden Beispiel dargestellt.</para>
<code>
<label>Beispiel 136: Verzeichnis-Funktionen</label>
<codeline>$dh = opendir (&apos;.&apos;); </codeline>
<codeline>echo &quot;Dateien:\n&quot;; </codeline>
<codeline>while( $file = readdir($handle) ){ </codeline>
<codeline>	echo &quot;$file\n&quot;; </codeline>
<codeline>} </codeline>
<codeline>closedir($handle); </codeline>
</code>
<para>Dieser Algorithmus läßt sich allerdings komplett durch die Verwendung der Funktion glob ersetzen.</para>
<code>
<label>Beispiel 137: glob</label>
<codeline>foreach( glob(&quot;*.txt&quot;) as $filename ){ </codeline>
<codeline>	echo $filename.&quot; size &quot; . filesize($filename) . &quot;\n&quot;; </codeline>
<codeline>} </codeline>
</code>
</section>
</section>
<section><section-header>Datenbanken</section-header>
<para>Die Unterstützung von Datenbanken sind wohl ein wesentlicher Aspekt in der Erfolgsgeschichte von PHP. Es werden sehr viele Datenbanken unterstützt, einige davon auch ohne Zutun von Erweiterungen am PHP-Modul.</para>
<para>Folgende Datenbanken werden unterstützt:</para>
<para>Adabas D, Ingres, Oracle (OCI7 und OCI8), dBase, InterBase, Ovrimos, Empress, FrontBase, PostgreSQL, FilePro (nur Lesezugriff), mSQL, Solid, Hyperwave, Direct MS-SQL, Sybase, IBM DB2, MySQL, Velocis, Informix, ODBC, Unix dbm.</para>
<para>Die meisten Datenbanken werden über Erweiterungen von PHP implementiert. Die MySQL-Implementierung gilt als am Besten gepflegteste Datenbankschnittstelle und entsprechend als Referenz. Dies ist eine der Gründe, warum das Gespann aus PHP und MySQL einen solch hohen Verbreitungsgrad gefunden haben.</para>
<para>Die Zugriffe auf Datenbanken funktionieren unabhängig der Schnittstelle ähnlich. Daher sei an dieser Stelle der Zugriff auf eine MySQL-Datenbank kurz umrissen.</para>
<para>Um auf eine Datenbank zugreifen zu können, ist es zunächst erforderlich, dass eine Verbindung zu dieser Datenbank aufgenommen wird. Dabei ist es egal, auf welchem Rechner die Datenbank läuft, solange er über seinen Namen bzw. seine IP-Adresse erreichbar ist.</para>
<para>Das Skript meldet sich beim Datenbank-Host mit einem Login und einem Passwort an. Die entsprechende PHP-Funktion gibt eine Ressourcen-ID zurück, die in einer Variablen gespeichert wird. Das Speichern und Verwenden der Verbindungskennung ist allerdings nur bei parallel-Zugriffen auf eine oder mehrere Datenbanken notwendig, da sie als optionaler Parameter beim Aufruf der weiteren Funktionen verwendet angegeben werden kann. Wird sie nicht angegeben, so wird die zuletzt benutzte oder geöffnete Verbindung in der Funktion verwendet.</para>
<para>Das explizite Freigeben einer Datenbankverbindung erübrigt sich, da PHP die Verbindung standardmäßig nach Ablauf des Skripts selbständig abbricht. Es kann u.U. jedoch sinnvoll sein, eine Verbindung frei zu geben, wenn sehr viele Verbindungen aufgebaut werden müssen (was wohl eher selten der Fall sein dürfte).</para>
<code>
<label>Beispiel 138: MySQL-Datenbank verwenden</label>
<codeline>$mysql_link = mysql_connect( $db_host, $db_user, $db_pw ); </codeline>
<codeline>mysql_select_db( $databasename, $mysql_link ); </codeline>
<codeline>$mysql_result = mysql_query( &quot;select * from &quot;.$tablename ); </codeline>
<codeline>print &quot;&lt;table&gt;\n&quot;; </codeline>
<codeline>print &quot;&lt;tr&gt;&quot;; </codeline>
<codeline>for( $i=0; $i&lt;mysql_num_fields( $mysql_result ); $i++ ){ </codeline>
<codeline>	print &quot;&lt;th&gt;&quot;.mysql_field_name( $mysql_result, $i ).&quot;&lt;/th&gt;\n&quot;; </codeline>
<codeline>} </codeline>
<codeline>print &quot;&lt;/tr&gt;\n&quot;; </codeline>
<codeline>while( $result_row = @mysql_fetch_row( $mysql_result ) ){ </codeline>
<codeline>	print &quot;&lt;tr&gt;\n&quot;; </codeline>
<codeline>	foreach( $result_row as $result_field ) </codeline>
<codeline>		print &quot;\t&lt;td&gt;$result_field&lt;/td&gt;\n&quot;; </codeline>
<codeline>	print &quot;&lt;/tr&gt;\n&quot;; </codeline>
<codeline>} </codeline>
<codeline>print &quot;&lt;/table&gt;&quot;; </codeline>
<codeline>mysql_close( $mysql_link );   </codeline>
</code>
<para>Wird die Funktion mysql_connect mehrfach mit den gleichen Parametern aufgerufen, gibt sie jeweils die selbe Verbindungskennung zurück und benutzt die bereits vorhandene Verbindung. Ein vierter, optionaler, Parameter weist die Funktion an, eine neue Verbindung herzustellen, auch wenn bereits eine besteht.</para>
<para>Nachdem eine Verbindung aufgebaut ist, kann eine Datenbank auf dem Server ausgewählt werden, die anschliessend als Standard verwendet wird. Andererseits ist es möglich, die zu verwendende Datenbank beim Absendenden einer Query an den Server zu übermitteln.</para>
<para>Die Funktionen mysql_query und mysql_db_query setzen eine Query auf den Datenbankserver ab und geben eine Ergebniskennung zurück, die bei der weiteren Arbeit mit dem Ergebnis Verwendung findet.</para>
<para>Mittels mysql_num_rows lässt sich ermitteln, wie viele Datensätze in der Ergebnismenge der Abfrage vorhanden sind, mit mysql_num_fields die Anzahl der Felder. mysql_affected_rows gibt die Anzahl der durch die Anfrage veränderten Datensätze zurück.</para>
<para>Die Ergebnis-Datensätze lassen sich durch verschiedene Funktionen als indizierte und/oder assoziatives Arrays oder als Objekt zurückgeben. mysql_fetch_row gibt ein indiziertes, mysql_fetch_assoc ein assoziatives Array zurück. mysql_fetch_array gibt ein gemischtes Array zurück, in dem die Ergebnisfelder sowohl assoziativ als auch indiziert vorhanden sind (oder nur eines von beiden, je nach zweitem Parameter).</para>
<para>Bei jedem Aufruf dieser Funktionen wird ein Datensatz zurückgegeben, bis alle aus der Ergenbismenge zurückgegeben worden sind. Dann liefern die Funktionen false als Ergebnis.</para>
<para>Über die Funktion mysql_data_seek kann der interne Zeiger auf die Ergebnismenge bewegt werden, und damit bestimmt werden, welcher Datensatz als nächster von den mysql_fetch-Funktionen zurückgegeben werden soll.</para>
<para>Die Funktion mysql_insert_id gibt als Ergebnis den Inhalt des als Autoincrement definierten Feldes zurück, welcher ein zuvor eingefügter Datensatz zugeordnet wurde.</para>
<para>Bei der Fehlerbehandlung können die Funktionen mysql_error und mysql_errno von Nutzen sein. Wenn bei der Abarbeitung einer Abfrage auf dem Host ein Fehler auftritt, gibt der Datenbankserver einen Fehlercode aus, der über diese beiden Funktionen abgefangen und für die weitere Fehlerbehandlung verwendet werden kann. Dabei gibt mysql_errno den numerischen Fehlercode zurück, mysql_error eine Textzeile mit Hinweisen auf die Fehlerquelle in der Query.</para>
</section>
</section>
<section><section-header>Klassen und Objekte</section-header>
<para>Der objektorientierte Ansatz in der Softwareentwicklung hat auch in PHP Einzug gehalten. Allerdings ist dieses Konzept erst nachträglich in den Sprachumfang aufgenommen worden. Daher fehlen ihm noch Fähigkeiten, die aus anderen Programmiersprachen bekannt sein dürften. In dieser Hinsicht wird die angekündigte Version 5 von PHP einen grossen Schritt nach vorne machen.</para>
<para>Die Umsetzung in PHP ist beslang eher als halbherzig zu bezeichnen. So lassen sich Attirbute und Funktionen einer Klasse nicht als privat, public oder protected deklarieren. Variablen, die Objekte aufnehmen, speichern ausserdem grundsätzlich das Objekt selbst, und nicht, wie in anderen Programmiersprachen, einen Zeiger auf ein Objekt im Speicher. Dies hat zur Folge, dass, wenn innerhalb einer Funktion mit einer Instanz gearbeitet werden soll, das Objekt explizit per Referenzparameter übergeben werden muss; ansonsten würde für die Funktion eine komplette Kopie des Objekts instanziiert werden.</para>
<section>
<section-header>Definition von Klassen, Erzeugen von Objekten</section-header>
<para>Das folgende Beispiel zeigt, wie eine Klasse definiert wird.</para>
<code>
<label>Beispiel 139: Klassensdefinition</label>
<codeline>class Cart { </codeline>
<codeline>	var $items=array(); </codeline>
<codeline>	function add_item ($artnr, $num) { </codeline>
<codeline>		$this-&gt;items[$artnr] += $num; </codeline>
<codeline>	} </codeline>
<codeline>	function remove_item ($artnr, $num) { </codeline>
<codeline>		if ($this-&gt;items[$artnr] &gt; $num) { </codeline>
<codeline>			$this-&gt;items[$artnr] -= $num; </codeline>
<codeline>			return true; </codeline>
<codeline>		} else { </codeline>
<codeline>			return false; </codeline>
<codeline>}}} </codeline>
</code>
<para>Im Beispiel wird eine Klasse mit dem Namen Cart definiert, die über eine eigene Variable und zwei Funktionen verfügt.</para>
<para>Instanzen einer Klasse, die Objekte, werden nach der Definition erzeugt und einer Variablen zugewiesen. Das erzeugen einer Instanz geschieht mit dem new-Operator.</para>
<code>
<label>Beispiel 140: Erzeugen eines Objekts einer Klasse</label>
<codeline>$korb = new Cart(); </codeline>
</code>
<para>Jede Instanz einer Klasse verfügt über den selben Aufbau. In jedem Objekt sind alle in der Klassendefinition festgelegten Funktionen verfügbar. Auch verfügt jedes Objekt über die definierten Variablen, und zwar jedes Objekt über seine eigenen. Objekte einer Klasse agieren also vollständig unabhängig von einander.</para>
</section>
<section><section-header>Objektattribute</section-header>
<para>Wie erwähnt, verfügen Instanzen einer Klasse über eigene Attribute. Das Variablenkonzept in PHP sieht keine explizite Deklaration von Variablen vor, sodass auch innerhalb der Klassendefinition darauf verzichtet werden kann; zu empfehlen ist dies jedoch nicht.</para>
<para>Klassenvariablen werden durch die Verwendung des var Schlüsselwortes initialisiert. Diese Initialisierung in der Klassendefinition muss vor der erster Funktionsdeklaration geschehen. Klassenvariablen können ausschliesslich mit konstanten Werten initialisiert werden; das Initialisieren mit nicht-konstanten Ausdrücken oder Funktionsergebnissen ist nicht möglich.</para>
<para>Im Grunde wird empfohlen, lediglich die Namen der Klassenvariablen anzugeben, und ihre Initialisierung innerhalb einer Funktion vorzunehmen. Dazu eignet sich die Konstruktorfunktion.</para>
<para>Wie erwähnt sind sämtliche Objektvariablen auch von ausserhalb sicht- und manipulierbar. Man erreicht sie, indem ein Separator zwischen Variablenbezeichner des Objekts und Bezeichner der Variablen innerhalb des Objekts notiert wird. Der Bezeichner der Variablen innerhalb des Objekts wird im übrigen nicht mit dem Dollarzeichen angegeben, da PHP für eine Variable nur ein einziges Dollarzeichen erwartet. Verwendet man es doch, wird der Ausdruck als variable Variable gehandhabt.</para>
<para>Innerhalb eines Objekts werden die Objektvariablen über das auf sich selbst zeigende this erreicht. Dieses Schlüsselwort ermöglicht den Zugriff auf die eigenschaften des Objekts selbst, der Zugriff auf die Eigenschaften einer anderen Instanz der Klasse ist naturgemäß darüber nicht möglich.</para>
<code>
<label>Beispiel 141: Objektvariablenzugriff</label>
<codeline>$korb-&gt;items[$artnr] += sum; </codeline>
<codeline>$i = &quot;items&quot;; </codeline>
<codeline>$korb-&gt;$i[$artnr] += sum; </codeline>
</code>
</section>
<section><section-header>Konstruktor und Destruktor</section-header>
<para>Verfügt die Klassendefinition über eine Funktion mit dem selben Namen wie die Klasse (in der sie definiert wird) selbst, so wird diese Funktion als Kontruktor der Klasse interpretiert und beim Erzeugen einer Instanz über das Schlüsselwort new automatisch aufgerufen. Damit eignet sich eine solche Funktion dazu, Variablen des Objekts zu initialisieren. Die Funktionsdeklaration kann mit Parametern ausgestattet werden, die für die Initialisierung nützlich sein könnten.</para>
<code>
<label>Beispiel 142: Erzeugung eines Objekts mit Konstruktor</label>
<codeline>class xmldoc{ </codeline>
<codeline>	var filename; </codeline>
<codeline>	function xmldoc( $filename=&quot;&quot; ){ </codeline>
<codeline>		$this-&gt;loadfile( $filename ); </codeline>
<codeline>	} </codeline>
<codeline>	/*...*/ </codeline>
<codeline>} </codeline>
<codeline>$xml_doc = new xmldoc( $filename ); </codeline>
</code>
<para>Es gibt keine Destruktoren in PHP, die wie der Konstruktor angewendet werden können.</para>
</section>
<section><section-header>Vererbung</section-header>
<para>Basierend auf bereits definierte Klassen, lassen sich weitere Klassen definieren. Eine in der Form definierte Klasse erhält automatisch alle Funktionen und Variablen der Oberklasse. Innerhalb der Unterklasse lassen sich weitere Variablen und Funktionen definieren. Funktionen und Variablen der Oberklasse lassen sich zwar überschreiben, aber nicht auslöschen. Eine Funktion der Oberklasse ist also immer auch in den Instanzen der Unterklassen enthalten.</para>
<para>Mehrfachvererbung ist in PHP nicht möglich. Eine Unterklasse kann dementsprechend nur eine direkte Oberklasse haben und nicht als Basis für weitere Unterklassen dienen.</para>
<code>
<label>Beispiel 143: Vererbung</label>
<codeline>class xmldoc{ </codeline>
<codeline>	var xmlfilename; </codeline>
<codeline>	function xmldoc( $filename=&quot;&quot; ){ </codeline>
<codeline>		$this-&gt;loadxml( $filename ); </codeline>
<codeline>	} </codeline>
<codeline>	/*...*/ </codeline>
<codeline>} </codeline>
<codeline>class transformer extends xmldoc{ </codeline>
<codeline>	var xsltfilename; </codeline>
<codeline>	function transformer( $xmlfilename=&quot;&quot;, $xslfilename=&quot;&quot; ){ </codeline>
<codeline>		$this-&gt;loadxml( $xmlfilename ); </codeline>
<codeline>		$this-&gt;loadxsl( $xslfilename ); </codeline>
<codeline>	} </codeline>
<codeline>	/*...*/ </codeline>
<codeline>} </codeline>
<codeline>$trans = new transformer( $xml, $xsl ); </codeline>
</code>
<para>Der Konstruktor einer Unterklasse ist wiederum diejenige Funktion, die so heisst, wie die Unterklasse selbst. Sie muss in der Unterklassendefinition definiert worden sein. Ist in der Unterklasse kein Konstruktor definiert, wird der Konstruktor der Oberklasse verwendet. Im Beispiel wäre also, gäbe es die Funktion transformer in der erbenden Klasse nicht, die Funktion xmldoc der vererbenden Klasse gleichzeitig Konstruktor der transformer-Klasse.</para>
</section>
<section><section-header>Verwendung von Klassenfunktionen ohne Klasseninstanzen</section-header>
<para>Es ist manchmal nützlich, eine Funktion einer Klasse zu verwenden, ohne jedoch über eine Instanz der Klasse zu verfügung oder erstellen zu wollen.</para>
<para>Über den ::-Operator lassen sich die Funktionen einer Klasse aufrufen, ohne dass tatsächlich ein Objekt der Klasse existiert. Da dabei nicht auf ein Objekt der Klasse zugegriffen wird, sind tatsächlich die Variablen der Klasse nicht verfügbar.</para>
<para>Dem zweifachen Doppelpunkt vorangehen muss der Name der Klasse; auf ihn folgend wird der Funktionsname notiert.</para>
<code>
<label>Beispiel 144: Klassenfunktionen ohne Klasseninstanz aufrufen</label>
<codeline>class A{ </codeline>
<codeline>	function example(){ </codeline>
<codeline>		echo &quot;Function example in A&quot;; </codeline>
<codeline>	} </codeline>
<codeline>} </codeline>
<codeline>A::example(); </codeline>
</code>
<para>Innerhalb einer Unterklasse wird damit der zugriff auf überschriebene Funktionen der Oberklasse möglich. Zu dem ::-Operator gesellt sich in diesem Fall der spezielle Namen parent, der den Bezug zur Ursprungsklasse herstellt. Dies macht den Vorgang transparenter als die Verwendung der Klassennamen.</para>
<code>
<label>Beispiel 145: Parent-Funktionen in Klassen</label>
<codeline>class A{ </codeline>
<codeline>	function example(){ </codeline>
<codeline>		echo &quot;Function example in A&quot;; </codeline>
<codeline>	} </codeline>
<codeline>} </codeline>
<codeline>class B extends A{ </codeline>
<codeline>	function example(){ </codeline>
<codeline>		parent::example(); </codeline>
<codeline>	} </codeline>
<codeline>} </codeline>
</code>
</section>
<section><section-header>Objekte speichern und wiederherstellen, Objekte in Sessions</section-header>
<para>Beliebige Variableninhalte lassen sich mit den Funktionen serialize und unserialize in eine Zeichenkettenrepräsentation und zurück verwandeln. Dementsprechend bieten sie sich auch an, wenn Objekte gesichert werden müssen.</para>
<para>Zu beachten bei der Wiederherstellung eines Objekts aus einer Zeichenkette ist, dass vor diesem Vorgang die Klassendefinition bekannt sein muss. Ansonsten verliert das Objekt seine Methoden und verfügt nunmehr nur noch über die Variablenwerte, und stellt somit lediglich ein assoziatives Array dar.</para>
<para>Werden Objekte in der Session registriert, so übernimmen die Sessionhandlingmethoden die automatisch die serialisierung und unserialisierung von Objekten. Dabei ist jedoch weiterhin zu beachten, dass die Klassendefinition bekannt sein muss bevor die Objekte unserialisiert werden. Dies bedeutet, dass entsprechende Klassenbibliotheken geladen werden müssen, bevor die Funktion session_start aufgerufen wird. Da das Objekt in jeder Skript unserialisiert wird, muss in jedem Skript, welches die Sitzung startet, die klassendefinition bekannt sein, auch wenn das Objekt nicht benutzt wird.</para>
</section>
</section>
</section>
<section><section-header>XML / XSLT mit PHP</section-header>
<para>Die Integration von XML und XSLT in PHP ist bereits seit einiger Zeit verfolgt worden. Leider befinden sich die Implementierungen der einzelnen Module auf sehr unterschiedlichen Niveaus. So ist die Verwendung von XML kein Problem. Die Anwendung von XSLT ist aber noch nicht vollständig integriert, geschweige denn Dokumentiert. Trotzdem lässt sich mit den Modulen produktiv arbeiten, jedoch sollte man dabei beachten, dass an den einzelnen Schnittstellen noch Änderungen vorgenommen werden könnten.</para>
<section>
<section-header>XML Programmierschnittstellen</section-header>
<para>Eine sog. API (application programming interface) für XML ermöglicht den Zugriff auf die Daten eines XML-Instanzdokuments. Dabei beschränken sich die grundlegenden Anforderungen an eine API auf die interpretation der Dateien (oder Datenströme), ihre Strukturelle konformität zu den Wohlgeformtheitsregeln und Gütligkeit gegenüber einer gelieferten Dokumentendefinition in Form eines Schemas oder einer DTD.</para>
<para>Für den Umgang mit XML-Daten, unabhängig von PHP, haben sich bisher zwei von Grund auf verschiedene Ansätze etalierent: Das Simple API for XML und das Document Object Model. Beide Ansätze sind im Funktionsumfang von PHP enthalten.</para>
<ul><para><li>
SAX</li>
</para>
</ul><para>Das Simple Api for XML arbeitet ein XML-Dokument sequenzell ab, und meldet dem aufrufenden Programm einzelne Ereignisse, die durch die Dokumentenstruktur bedingt werden. Zu diesen Ereignissen gehören bspw. der Anfang eines Elements sowie dessen Ende, die Übernahme der Inhalte eines Elements.</para>
<ul><para><li>
DOM</li>
</para>
</ul><para>Das Document Object Model wird vom w3c als Schnittstellendefinition gepflegt und ist vergleichbar mit dem Objektmodell von DHTML. Das bedeutet, dass ein Dokument vollständig geladen wird und in einer baumartigen Struktur von Objekten der Programmumgebung zur Verfügung gestellt wird. Es lassen sich anschliessen die einzelnen Knoten ansprechen, manipulieren löschen oder auch erzeugen. Häufig basiert eine DOM-Implementierung auf SAX-Mechanismen, die dazu verwendet werden, den Objektbaum zu erzeugen.</para>
<para>Während der Umgang mit SAX die Implementierung entsprechender Behandlungalgorithmen zu entwerfen, genügt beim Einsatz vom DOM das Erzeugen eines Objekts. Generell lässt sich sagen, dass die Verarbeitung von XML-Dokumenten über die SAX-Schnittstelle sehr viel schneller von Statten geht und einen nur geringen Speicherbedarf hat. Andererseits spielt das DOM seine  Mächtigkeit aus, wenn es darum geht, XML-Dokumente zu bearbeiten, da dies direkt im DOM möglich ist.</para>
<section>
<section-header>DOM in PHP</section-header>
<para>Die Implementierung des DOM level 2 ist in der PHP aktuell als experimentell gekennzeichnet und soll hier nicht ausführlicher behandelt werden. Als Beispiel zur Funktionalität sei lediglich das folgende (funktionierende) Beispiel dargestellt.</para>
<code>
<label>Beispiel 146: XMLDOM in PHP</label>
<codeline>$xmlstr = &lt;&lt;&lt;EOD </codeline>
<codeline>&lt;?xml version=&apos;1.0&apos; standalone=&apos;yes&apos;?&gt; </codeline>
<codeline>&lt;body language=&apos;en&apos;&gt; </codeline>
<codeline> &lt;para language=&apos;ge&apos;&gt; </codeline>
<codeline>	&lt;tgroup cols=&apos;3&apos; align=&quot;center&quot;&gt; </codeline>
<codeline>    &lt;row&gt; </codeline>
<codeline>	 	&lt;entry&gt;a1&lt;/entry&gt; </codeline>
<codeline>		&lt;entry&gt;b1&lt;/entry&gt; </codeline>
<codeline>		&lt;entry&gt;c1&lt;/entry&gt; </codeline>
<codeline>	&lt;/row&gt; </codeline>
<codeline>	&lt;row&gt; </codeline>
<codeline>		&lt;entry&gt;a2&lt;/entry&gt; </codeline>
<codeline>		&lt;entry&gt;c2&lt;/entry&gt; </codeline>
<codeline>	&lt;/row&gt; </codeline>
<codeline>   &lt;/tgroup&gt; </codeline>
<codeline> &lt;/para&gt; </codeline>
<codeline>&lt;/body&gt; </codeline>
<codeline>EOD; </codeline>
<codeline>$dom = domxml_open_mem($xmlstr); </codeline>
<codeline>$row_elements = $dom-&gt;get_elements_by_tagname(&quot;row&quot;); </codeline>
<codeline>$parent = $row_elements[1]; </codeline>
<codeline>$sibling=$parent-&gt;child_nodes(); </codeline>
<codeline>$element = new domelement( &quot;entry&quot; ); </codeline>
<codeline>$element-&gt;set_content(&quot;b2&quot;); </codeline>
<codeline>$parent-&gt;insert_before( $element, $sibling[2] ); </codeline>
<codeline>echo &quot;&lt;PRE&gt;&quot;; </codeline>
<codeline>$xmlfile = $dom-&gt;dump_mem(); </codeline>
<codeline>echo htmlentities($xmlfile); </codeline>
<codeline>echo &quot;&lt;/PRE&gt;&quot;; </codeline>
</code>
<para>Im Beispiel wird eine XML-Quelle definiert. In diesem Fall wird eine festcodierte Zeichenkette verwendet, es lassen sich logischerweise auch Dateien oder Datenbankeinträge als Quelle verwenden. Es wird eine DOM-Instanz erzeugt durch den Aufruf der Funktion domxml_open_mem, die als Parameter eine Zeichenkette entgegennimmt. Die zurückgegebene ResourcenID wird in der Variablen $dom gespeichert. Aus dem Dokument wird anschliessend eine Liste aller row-Elemente abgefragt, und das zweite Element in der Variablen $parent übernommen. Der Variablen $sibling wird eine Liste aller Kinder des zweiten row-Elements zugewiesen. Ein neues Element wird erzeugt und in der Variablen $element abgelegt. Der Inalt des Elements wird gesetzt, und das Element als Kindelement des zweiten row-Elements eingefügt. Schliesslich wird das überarbeitete Dokument ausgegeben, wobei nun beide row-Elemente über drei Einträge verfügen.</para>
</section>
<section><section-header>SAX in PHP</section-header>
<para>In Hinblick auf die Arbeit mit Klassen und Objekten, ist es oftmals sinnvoller, ein eigenes Inhaltsmodell aufzubauen. Meist werden nur wenige Methoden gebraucht und ist eine Prüfung der Inhalte erforderlich. In diesen Fällen ist es ratsam, die SAX-Funktionen von PHP zu verwenden, die zudem nicht als zusätzliche Bibliothek geladen werden müssen, sondern bereits in PHP selbst integriert sind. Der Status dieser Funktionen kann als stabil und entgültig betrachtet werden. Der größte Nachteil von SAX als Schnittstelle ist, das es, prinzipbedingt, keine direkte Manipulation am XML-Dokument zulässt. Diese Funktionalität muss also manuell bereitgestellt werden.</para>
<para>Für die Verwendung von SAX, wird eine Parserinstanz erzeugt der an verschiedene, benutzerdefinierte Methoden gebunden wird, die die eigentliche Verarbeitung des Dokuments bewerkstelligen. Im Beispiel vorausgesetzt sei, dass die Inhalte des XML-Dokuments in der Variablen $dat vorliegen.</para>
<code>
<label>Beispiel 147: Ereignisortientierte Verwendung des SAX-Parsers</label>
<codeline>$xmlp =xml_parser_create(); </codeline>
<codeline>xml_set_element_handler($xmlp,&quot;XMLstartElement&quot;,&quot;XMLendElement&quot;); </codeline>
<codeline>xml_set_character_data_handler($xmlp,&quot;XMLcbDataHandler&quot;); </codeline>
<codeline>xml_parser_set_option($xmlp,XML_OPTION_CASE_FOLDING,0); </codeline>
<codeline>if(!xml_parse($xmlp,$dat)) </codeline>
<codeline>	sprintf(&quot;XML error: %s at line %d&quot;, </codeline>
<codeline>				xml_error_string(xml_get_error_code($xmlp)), </codeline>
<codeline>				xml_get_current_line_number($xmlp) </codeline>
<codeline>); </codeline>
<codeline>xml_parser_free($xmlp); </codeline>
<codeline>function XMLstartElement($xml,$name,$attr){ </codeline>
<codeline>	global $depth; </codeline>
<codeline>	print &quot;\n&quot;.str_repeat(&quot;\t&quot;,$depth).&quot;START ELEMENT &quot;.$name; </codeline>
<codeline>	print &quot; Attribute: &quot;; </codeline>
<codeline>	$a=array(); </codeline>
<codeline>	foreach( $attr as $k=&gt;$v )	$a[]=$k.&quot;=\&quot;&quot;.$v.&quot;\&quot;&quot;; </codeline>
<codeline>	print implode( &quot;, &quot;, $a ); </codeline>
<codeline>	$depth++; </codeline>
<codeline>} </codeline>
<codeline>function XMLendElement($xml,$name){ </codeline>
<codeline>	global $depth; </codeline>
<codeline>	print &quot;\n&quot;.str_repeat(&quot;\t&quot;,$depth).&quot;END ELEMENT &quot;.$name; </codeline>
<codeline>	$depth--; </codeline>
<codeline>} </codeline>
<codeline>function XMLcbDataHandler($xml,$data){ </codeline>
<codeline>	global $depth; </codeline>
<codeline>	print &quot;\n&quot;.str_repeat(&quot;\t&quot;,$depth).&quot;CHAR_DATA &quot;.serialize($data); </codeline>
<codeline>} </codeline>
</code>
<para>Die hier gezeigte Methode empfiehlt sich, wenn direkt auf das Inhaltsmodell des Dokuments reagiert werden soll. Geht es eher darum, die Inhalte als baumartige Struktur einzulesen, kann man auch den im folgenden Beispiel dargelegte Methode anwenden.</para>
<code>
<label>Beispiel 148: Verwendung des SAX-Parser zur Erstellung einer XML-Struktur</label>
<codeline>$dat = &lt;&lt;&lt;EOD </codeline>
<codeline>&lt;?xml version=&quot;1.0&quot;?&gt; </codeline>
<codeline>&lt;moldb&gt; </codeline>
<codeline>    &lt;molecule&gt; </codeline>
<codeline>        &lt;name&gt;Alanine&lt;/name&gt; </codeline>
<codeline>        &lt;symbol&gt;ala&lt;/symbol&gt; </codeline>
<codeline>        &lt;code&gt;A&lt;/code&gt; </codeline>
<codeline>        &lt;type&gt;hydrophobic&lt;/type&gt; </codeline>
<codeline>    &lt;/molecule&gt; </codeline>
<codeline>    &lt;molecule&gt; </codeline>
<codeline>        &lt;name&gt;Lysine&lt;/name&gt; </codeline>
<codeline>        &lt;symbol&gt;lys&lt;/symbol&gt; </codeline>
<codeline>        &lt;code&gt;K&lt;/code&gt; </codeline>
<codeline>        &lt;type&gt;charged&lt;/type&gt; </codeline>
<codeline>    &lt;/molecule&gt; </codeline>
<codeline>&lt;/moldb&gt; </codeline>
<codeline>EOD; </codeline>
<codeline>$values=array(); </codeline>
<codeline>$index=array(); </codeline>
<codeline>$xmlp = xml_parser_create(); </codeline>
<codeline>xml_parser_set_option($xmlp,XML_OPTION_CASE_FOLDING,0); </codeline>
<codeline>xml_parse_into_struct($xmlp,$dat,$values,$index); </codeline>
<codeline>xml_parser_free($xmlp); </codeline>
<codeline>echo &quot;&lt;pre&gt;Index array\n&quot;; </codeline>
<codeline>var_dump($index); </codeline>
<codeline>echo &quot;\nValues array\n&quot;; </codeline>
<codeline>var_dump($values); </codeline>
<codeline>echo &quot;&lt;/pre&gt;&quot;; </codeline>
</code>
<para>Die Funktion xml_parse_into_struct() nimmt, neben der ResourcenID des Parsers und der Zeichenkette eines XML-Dokuments, zwei Array-Parameter per Referenz entgegen. In diese beiden Arrays wird der Inhalt des XML-Dokuments abgebildet.</para>
<para>Im hier verwendeten $values-Array werden alle Tags und Inhalte in der Folge des Auftretens im Dokument abgelegt. Das Array ist zweidimensional und in der ersten Ebene numerisch indiziert. Jedes Element des Arrays besteht wiederum aus einem, diesmal assoziativen, Array, in dem Informationen zum XML-Element abgelegt sind. Die Informationen sind der Tagname, die Attribute, der Textinhalt des Elements und als type wird angegeben, ob es sich um ein sich öffnendes (open), schliessendes (close) Tag, Tag ohne Kindelemente (complete), oder ein Textinhaltsabschnitt eines Tags (cdata) handelt. Ausserdem wird die Verschachtelungsebene angegeben.</para>
<para>Das Index-Array ist ebenso ein zweidimensionales Array, wobei jedoch die erste Ebene assoziativ aufgebaut ist. Jeder im XML-Dokument aufgetretener Tag bekommt einen über den Namen ansprechbaren Eintrag jeweils in Form eines numerisch indizierten Arrays mit den Indizes des Tags, an deren Stellen im Values-Array ein Tag dieses namens anzutreffen ist.</para>
<para>Basierend auf diese beiden Arrays lässt sich mit ein wenig Aufwand eine objektorientierte Representation des XML-Dokuments generieren, wie das folgende Beispiel, unter Verwendung der selben $dat-Variablen des vorhergenden Beispiels, verdeutlichen soll.</para>
<code>
<label>Beispiel 149: Erstellung eines Inhaltsmodels nach XML-Struktur</label>
<codeline>$values=array(); </codeline>
<codeline>$index=array(); </codeline>
<codeline>$result=array(); </codeline>
<codeline>$xmlp = xml_parser_create(); </codeline>
<codeline>xml_parser_set_option($xmlp,XML_OPTION_CASE_FOLDING,0); </codeline>
<codeline>xml_parser_set_option($xmlp,XML_OPTION_SKIP_WHITE,1); </codeline>
<codeline>xml_parse_into_struct($xmlp,$dat,$values,$index); </codeline>
<codeline>xml_parser_free($xmlp); </codeline>
<codeline>foreach ($index as $k=&gt;$v) { </codeline>
<codeline>	if ($k == &quot;molecule&quot;) { </codeline>
<codeline>		$molranges = $v; </codeline>
<codeline>		for ($i=0; $i &lt; count($molranges); $i+=2) { </codeline>
<codeline>			$offset = $molranges[$i] + 1; </codeline>
<codeline>			$len = $molranges[$i + 1] - $offset; </codeline>
<codeline>			$result[] = parseMol(array_slice($values, $offset, $len)); </codeline>
<codeline>		} </codeline>
<codeline>	} </codeline>
<codeline>} </codeline>
<codeline>function parseMol($mvalues) { </codeline>
<codeline>    for ($i=0; $i &lt; count($mvalues); $i++) </codeline>
<codeline>        $mol[$mvalues[$i][&quot;tag&quot;]] = $mvalues[$i][&quot;value&quot;]; </codeline>
<codeline>    return new AminoAcid($mol); </codeline>
<codeline>} </codeline>
<codeline>class AminoAcid { </codeline>
<codeline>    var $name; </codeline>
<codeline>    var $symbol; </codeline>
<codeline>    var $code; </codeline>
<codeline>    var $type; </codeline>
<codeline>    function AminoAcid ($aa) { </codeline>
<codeline>        foreach ($aa as $k=&gt;$v) </codeline>
<codeline>            $this-&gt;$k = $aa[$k]; </codeline>
<codeline>    } </codeline>
<codeline>} </codeline>
<codeline>echo &quot;** Database of AminoAcid objects:\n&quot;; </codeline>
<codeline>var_dump($result); </codeline>
<codeline>/* Ausgabe: </codeline>
<codeline>** Database of AminoAcid objects: </codeline>
<codeline>array(2) { </codeline>
<codeline>  [0]=&gt; </codeline>
<codeline>  object(aminoacid)(4) { </codeline>
<codeline>    [&quot;name&quot;]=&gt; </codeline>
<codeline>    string(7) &quot;Alanine&quot; </codeline>
<codeline>    [&quot;symbol&quot;]=&gt; </codeline>
<codeline>    string(3) &quot;ala&quot; </codeline>
<codeline>    [&quot;code&quot;]=&gt; </codeline>
<codeline>    string(1) &quot;A&quot; </codeline>
<codeline>    [&quot;type&quot;]=&gt; </codeline>
<codeline>    string(11) &quot;hydrophobic&quot; </codeline>
<codeline>  } </codeline>
<codeline>  [1]=&gt; </codeline>
<codeline>  object(aminoacid)(4) { </codeline>
<codeline>    [&quot;name&quot;]=&gt; </codeline>
<codeline>    string(6) &quot;Lysine&quot; </codeline>
<codeline>    [&quot;symbol&quot;]=&gt; </codeline>
<codeline>    string(3) &quot;lys&quot; </codeline>
<codeline>    [&quot;code&quot;]=&gt; </codeline>
<codeline>    string(1) &quot;K&quot; </codeline>
<codeline>    [&quot;type&quot;]=&gt; </codeline>
<codeline>    string(7) &quot;charged&quot; </codeline>
<codeline>  } </codeline>
<codeline>} </codeline>
<codeline>*/ </codeline>
</code>
</section>
</section>
<section><section-header>XSL-Transformationen mit PHP</section-header>
<para>Die XSLT-Funktionen sind bislang noch nicht in PHP integriert und müssen als Erweiterungsbibliothek eingebunden werden. Die Funktionen nutzen die Sablotron Bibliothek von Ginger Alliance. Ist diese Erweiterung in PHP einmal integriert, so zeigt sich die Verwendung ihrer als sehr einfach. Leider ist die Dokumentation von PHP in Bezug auf die XSLT-Funktionen nicht vollständig und irreführend formuliert. Folgendes Beispiel zeigt jedoch, wie eine XSL-Transformation auf ein XML-Dokument durchgeführt werden kann.</para>
<code>
<label>Beispiel 150: Eine Klasse für die Transformation mit XSL-Stylesheets</label>
<codeline>function xslTransform( $xmlFile, $xslFile ){ </codeline>
<codeline>	$xml = implode( &quot;\n&quot;, file( $xmlFile ) ); </codeline>
<codeline>	$xsl = implode( &quot;\n&quot;, file( $xslFile ) ); </codeline>
<codeline>	$xslTransformator = xslt_create(); </codeline>
<codeline>	$args = array ( &apos;/_xml&apos; =&gt; $xml, &apos;/_xsl&apos; =&gt; $xsl ); </codeline>
<codeline>	$params = array(); </codeline>
<codeline>	$result = xslt_process( </codeline>
<codeline>								$xslTransformator,  </codeline>
<codeline>								&apos;arg:/_xml&apos;,  </codeline>
<codeline>								&apos;arg:/_xsl&apos;,  </codeline>
<codeline>								NULL, </codeline>
<codeline>								$args, </codeline>
<codeline>								$params </codeline>
<codeline>	); </codeline>
<codeline>	xslt_free( $xslTransformator ); </codeline>
<codeline>	return $result; </codeline>
<codeline>} </codeline>
</code>
<para>Die Funktion xslt_process() ist in der PHP-Dokumentation nicht verzeichnet, funktioniert aber zuverlässig und prüft die verwendeten Dokumente auf wohlgeformtheit und gültigkeit. Scheinbar ist es möglich, weitere Parameter zu übergeben; welche akzeptiert werden ist mir bislang nicht bekannt. Die Benutzung der Funktion als Black-Box mag ist aber durchaus möglich.</para>
</section>
</section>
</section>
<section><section-header>Quellenverzeichnis</section-header>
<table>
<tr>
<th><para>Anmerkungen</para>
</th>
<th><para>Quelle</para>
</th>
</tr>
<tr>
<td><para>Das World Wide Web Konsortium als Ausgangspunkt mit den Recommendations und dem umfangreichen Link-Verzeichnis zu weiteren Quellen</para>
</td>
<td><para>http://www.w3.org/</para>
<para>http://www.w3.org/TR/1998/REC-xml-19980210/</para>
<para>http://www.w3.org/TR/1999/REC-xml-names-19990114/</para>
<para>http://www.w3.org/TR/1999/REC-xslt-19991116/</para>
<para>http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/</para>
<para>http://www.w3.org/TR/2001/REC-xmlschema-1-20010502/</para>
<para>http://www.w3.org/TR/2001/REC-xmlschema-2-20010502/</para>
<para>http://www.edition-w3c.de/TR/1999/REC-xslt-19991116</para>
<para>http://www.w3.org/TR/2002/WD-xslt20-20021115/</para>
<para>http://www.w3.org/TR/2003/WD-xpath20-20030502</para>
<para>http://www.w3.org/TR/2003/WD-xpath-functions-20030502</para>
<para>http://www.w3.org/TR/2001/REC-xsl-20011015/</para>
<para>http://www.w3.org/TR/2003/WD-xhtml2-20030506</para>
</td>
</tr>
<tr>
<td><para>Ein durchaus umfassendes Scriptum, leider in den weiterführenden Teilen nicht vollständig ausgearbeitet</para>
</td>
<td><para>http://www.jeckle.de/vorlesung/xml/script.html</para>
</td>
</tr>
<tr>
<td><para>Leider ein wenig überholt, aber durchaus ansprechend</para>
</td>
<td><para>Lutz Wegner: Einführung in XML, Folienvorlage zur Vorlesung im Sommersemester 2000</para>
</td>
</tr>
<tr>
<td><para>Schnelleinstieg mittels eines Workshops in drei Teilen</para>
</td>
<td><para>http://www.infoweek.ch/</para>
<para>Teil 1: Magazin/Strategie &amp; Know-How/InfoWeek 12/2001</para>
<para>Teil 2: Magazin/Strategie &amp; Know-How/InfoWeek 13/2001</para>
<para>Teil 3: Magazin/Strategie &amp; Know-How/InfoWeek 20/2001</para>
</td>
</tr>
<tr>
<td><para>Vielleicht optisch nicht schön geraten, und ein wenig technisch; trotzdem empfehlenswert</para>
</td>
<td><para>Handout zur Vorlesung &quot;Objektorientierte Entwicklung von Internet-Anwendungen (002)&quot;, o.Univ.-Prof. Dr. Gustaf Neumann, Sommersemester 2002</para>
<para>http://nm.wu-wien.ac.at/</para>
</td>
</tr>
<tr>
<td><para>Erschlägt einiges an Begrifflichkeiten die mit Internettechnologien einhergehen.</para>
</td>
<td><para>http://krum.rz.uni-mannheim.de/web-tech/</para>
<para>Internet-Seiten zur Veranstaltung &quot;Webtechnologien&quot;, Dr. Heinz Kredel, Universität Mannheim, Wintersemester 2001/02</para>
</td>
</tr>
<tr>
<td><para>Newsgroup de.comp.lang.php mit einer Umfangreiche Frage- und Antwortliste zu PHP</para>
</td>
<td><para>http://www.dclp-faq.de/</para>
</td>
</tr>
<tr>
<td><para>Umfangreiche Wissensbestand zu Internettechnologien in HTML-World von Jan Winkler</para>
</td>
<td><para>http://www.html-world.de/</para>
</td>
</tr>
<tr>
<td><para>Einführung in HTML und verwandte Internettechnologien von teamone</para>
</td>
<td><para>http://selfhtml.teamone.de/</para>
</td>
</tr>
<tr>
<td><para>Eine nicht-kommerzielle Initiative, die der konsequente Verwendung von bestehenden Standards Vorschub leisten will.</para>
</td>
<td><para>http://www.webstandards.org</para>
</td>
</tr>
<tr>
<td></td>
<td><para>PC Magazin Kreativ 8: &quot;Webprogrammierung&quot;; WEKA Computerzeitschriftenverlag, 2001</para>
</td>
</tr>
<tr>
<td><para>Die php-Website</para>
</td>
<td><para>http://www.php.net/</para>
</td>
</tr>
<tr>
<td><para>Zend Technologies</para>
</td>
<td><para>http://www.zend.com/</para>
</td>
</tr>
<tr>
<td><para>Einige, zum Thema passende, Artikel</para>
</td>
<td><para>http://www.php-mag.de/</para>
<para>Eingespieltes Triumvirat; PHP, XML und XSLT</para>
<para>PHP Magazin 2/2003, S. 75ff.</para>
<para>Verwandlungen; XML-Transformationen mit patXMLRenderer</para>
<para>PHP Magazin 4/2002 S. 73ff.</para>
<para>Ein starkes Gespann? XSL-Transformationen mit PHP</para>
<para>PHP Magazin 4/2002 S. 77ff.</para>
</td>
</tr>
<tr>
<td><para>Einführung in die Anwendung von XSL-Transformationen unter PHP bei &lt;fase4/&gt;</para>
</td>
<td><para>http://www.fase4.com/de/tutorials/page,1,xslt.xml</para>
</td>
</tr>
<tr>
<td><para>Die iX lohnt sich immer mal wieder</para>
</td>
<td><para>iX, 1,2,3/2001 - Dreiteiliges XSLT- Tutorial</para>
<para>http://www.heise.de/ix/artikel/2001/01/167/</para>
<para>http://www.heise.de/ix/artikel/2001/02/142/</para>
<para>http://www.heise.de/ix/artikel/2001/03/167/</para>
</td>
</tr>
<tr>
<td></td>
<td><para>iX, 6/2003 - PHP objektorientiert</para>
</td>
</tr>
<tr>
<td><para>Seybold Report (Volume 2, Number 17; 9.12. 2002): What Is XSL-FO and When Should I Use It</para>
</td>
<td><para>http://www.seyboldreports.com/TSR/0217page1.html</para>
</td>
</tr>
<tr>
<td><para>Einführung in PHP, in Kooperation mit teamone</para>
</td>
<td><para>http://www.selfphp.info</para>
</td>
</tr>
</table>
</section>

</mydoc>
