Fallbeispiel


... [ Seminar XML (DTD) ] ... [ Einleitung ] ... [ Fallbeispiel ] ...

Fallbeispiel: Entwurf einer DTD


Mehrzweck DTD

Ob Sie eine fremde DTD verwenden sollten, hängt von verschiedenen Faktoren ab. Wenn Sie Texte für eine Firma oder eine andere Institution schreiben, so kann es sein, daß Ihnen einfach eine DTD vorgegeben wird, an die Sie sich halten müssen. In diesem Fall haben Sie keine Wahl.

Wenn Sie jedoch daran denken, für Ihre eigenen Zwecke eine DTD zu übernehmen, so gibt es einige Dinge zu beachten. Zuerst sollten Sie natürlich bedenken, welche Absicht Sie mit Ihrem XML-System verfolgen. Die Maßstäbe, die Sie an eine selbstentwickelte DTD anlegen, sollten auch für eine fremde DTD gelten. Ein wesentlicher Unterschied besteht darin, daß eine fremde DTD niemals so gut an Ihre Wünsche angepaßt sein kann, wie Ihre eigene. Es wird sich also um eine Mehrzweck-DTD handeln.

Mehrzweck-DTDs erleichtern die Verarbeitung, da beispielsweise ein Style Sheet auch nur einmal geschrieben werden muß. Momentan ist die Auswahl für XML noch nicht besonders groß. Aufgrund der Unterschiede zwischen XML und SGML können Sie in der Regel auch nicht direkt eine SGML-DTD verwenden. Für SGML gibt es bereits eine Reihe guter Mehrzweck-DTDs, wie zum Beispiel Docbook, Linuxdoc, Qwertz u.v.a. Vermutlich wird es auch für XML bald eine größere Auswahl geben.

Wenn Sie sich daran machen, eine DTD auszusuchen, achten Sie auf folgende Punkte:
Wie Sie diese Fragen und deren Antworten bewerten, sei Ihnen überlassen. Dies kann von Fall zu Fall unterschiedlich sein. Auf eine tiefere Diskussion verzichten wir hier, da ich in diesem Seminar zeigen möchte, wie man XML »selbst macht« und nicht nur »nachmacht«

Dokument-Analyse

Der Entwurf einer eigenen DTD ist keine ganz leichte Aufgabe. Wie der vorhergehende Abschnitt angedeutet hat, ist aber die Verwendung einer allgemeinen Dokumenttyp-Definition oft nur eine unzulängliche Lösung. Um das volle Potential von XML auszuschöpfen, ist eine »maßgeschneiderte« Kreation der »DTD von der Stange« vorzuziehen.

Der erste Schritt auf dem Weg zur eigenen DTD besteht in der genauen Analyse der zu beschreibenden Dokumentklasse. Welche Vorgehensweise Sie hierbei wählen sollten, hängt stark von dem speziellen Einsatzgebiet ab. Sprechen Sie mit allen beteiligten Personen. Dazu gehören in jedem Fall die Endbenutzer (also die Autoren). Den Benutzern fällt es oft leichter, Mängel in einer DTD festzustellen, als den Dokumenttyp konstruktiv zu beschreiben. Es ist also hilfreich, den Anwendern einen ersten Entwurf der DTD zum Experimentieren zu geben. Sollen die XML-Instanzen später in eine Datenbank integriert werden? Dann ziehen Sie auch Ihren Datenbankfachmann zu Rate. Sprechen Sie mit Ihrem Setzer oder dem Programmierer, der vielleicht einen Konverter schreiben soll. Jede einzelne der beteiligten Personen kann eine andere Sichtweise haben, die es zu berücksichtigen gilt.

Neben diesen allgemeinen Hinweisen versuchen wir, durch die folgende Diskussion eine Art Anleitung zu geben. Als Einstieg soll die Frage dienen, was eine DTD und der Entwurf einer solchen eigentlich ist. Nach den vorangegangenen Kapiteln wissen Sie natürlich schon, wozu eine DTD dient. Sie beschreibt eine Klasse von gleichartigen Dokumenten. Demnach besteht der erste Ansatz beim DTD-Entwurf darin, eine Beschreibung zu finden. Dies ist sicherlich auch eine gute Vorgehensweise, aber wir wollen Ihnen einmal einen alternativen Blickwinkel vorstellen.

Dazu nehmen wir an, daß es in der Menge aller möglichen DTDs die eine gibt, die genau auf Ihre Bedürfnisse zugeschnitten ist. Die Aufgabe lautet dann nicht mehr, eine Klasse von Dokumenten zu beschreiben, um eine DTD zu entwerfen; jetzt geht es darum, jene eine optimale DTD zu finden. Nun wollen wir Ihnen nicht vorschlagen, alle möglichen DTDs herzunehmen und wie nach der Nadel im Heuhaufen »Ihre« zu suchen. Es geht nur um den Gedankengang.

Wo soll man mit der Suche beginnen und wie soll man vorgehen? -- Es ist immer hilfreich, ein konkretes Dokument, vielleicht auch in Form einer wohlgeformten XML-Instanz, als Ausgangspunkt zu betrachten. Dazu eine DTD zu finden ist leicht: Man nimmt einfach die Elemente in genau der Verschachtelung, wie sie in der Instanz stehen, als Dokumenttyp-Definition. Das folgende Beispiel veranschaulicht das.

<?xml version="1.0"?>
<buch>
  <kapitel>
     <ueberschrift>Einleitung</ueberschrift>
     <absatz>...</absatz>
  </kapitel>
  <kapitel>
     <ueberschrift>Beschreibung</ueberschrift>
     <absatz>...</absatz>
  </kapitel>
  <kapitel>
     <ueberschrift>Schlußfolgerung</ueberschrift>
     <absatz>...</absatz>
  </kapitel>
</buch>
Die obige wohlgeformte XML-Instanz soll ein konkretes Buch sein. Wenn man von diesem Beispiel ausgeht, erhält man unmittelbar die folgende DTD.
<!ELEMENT buch         (kapitel, kapitel, kapitel) >
<!ELEMENT kapitel      (ueberschrift, absatz)      >
<!ELEMENT ueberschrift (#PCDATA)                   >
<!ELEMENT absatz       (#PCDATA)                   >
Zugegeben, die DTD ist nicht besonders gut. Man könnte sagen, sie paßt zu gut. Ihr zufolge besteht ein Buch immer aus genau drei Kapiteln. Pessimistisch formuliert heißt das: Sie haben nun eine schlechte DTD. Optimistisch betrachtet bedeutet dies: Sie haben eine DTD! Sie ist nur ein wenig zu speziell.
Versuchen wir es von der anderen Seite: mit einer generellen DTD. Was ist das generellste, das man über ein Dokument sagen kann? Eben daß es ein Dokument ist. -- Auch dafür findet man leicht eine DTD. Wir zeigen sie gleich mit einer Instanz:

<?xml version="1.0"?>
<!DOCTYPE dokument [
  <!ELEMENT dokument (#PCDATA)>
]>
<dokument>
Dies ist ein Beispiel für eine DTD, die
nur einen einzigen Elementtyp kennt.
Keine sehr große Hilfe :-(
</dokument>
Auch hier müssen wir eingestehen, daß die DTD nicht überzeugt. Ein eher absurdes Beispiel. Diese DTD kann man ohne Übertreibung als »etwas« zu generell bezeichnen. Aber wir haben Ihnen damit die beiden Extreme gezeigt. Irgendwo dazwischen liegt die »passende« DTD.

Welchen Startpunkt soll man wählen, eine zu spezielle oder eine zu generelle DTD? Beginnen Sie mit einer zu generellen DTD, taucht schnell ein Problem auf: Sie werden feststellen, daß Sie gern noch das eine oder andere Element hinzufügen möchten. Zum Beispiel soll ein dokument aus einer Folge von Absätzen bestehen. Erst darin darf Text stehen.

<?xml version="1.0"?>
<!DOCTYPE dokument [
  <!ELEMENT dokument (absatz+)>
  <!ELEMENT absatz   (#PCDATA)>
]>
<dokument>
Dies ist ein Beispiel für eine DTD, die
nur einen einzigen Elementtyp kennt.
Keine sehr große Hilfe :-(
</dokument>
Mit obigem Beispiel stehen wir schlecht da: Die vorhandenen Instanzen passen nun nicht mehr zu der geänderten DTD (weil innerhalb von dokument jetzt kein Text mehr erlaubt ist). Also müßten alle Instanzen geändert werden. Wenn Sie bereits viele Texte geschrieben haben, ist das nahezu unmöglich.
Was passiert aber im Fall der zu speziellen DTD? Stellen Sie sich vor, Sie schreiben ein weiteres Buch mit vier Kapiteln. Auch hier ist eine Änderung der DTD nötig, die etwa folgendermaßen aussehen kann:
<!ELEMENT buch         (kapitel, kapitel, 
                        kapitel, kapitel?)         >
<!ELEMENT kapitel      (ueberschrift, absatz)      >
<!ELEMENT ueberschrift (#PCDATA)                   >
<!ELEMENT absatz       (#PCDATA)                   >

Jetzt hat der Verfasser die Wahl zwischen drei und vier Kapiteln. Spätestens an dieser Stelle sollte man etwas gesunden Menschenverstand einsetzten und die Kapitelzahl offen gestalten.
<!ELEMENT buch         (kapitel+)                  >
<!ELEMENT kapitel      (ueberschrift, absatz)      >
<!ELEMENT ueberschrift (#PCDATA)                   >
<!ELEMENT absatz       (#PCDATA)                   >
Hier ist nun schließlich gestattet, daß ein Buch ein oder mehr Kapitel besitzt. Der große Vorteil: Die erste Instanz mit drei Kapiteln paßt immer noch! Was will man mehr? Wir fassen die Ergebnisse in folgenden Tipps zusammen:



Benennung von Elementtypen

Es mag auf den ersten Blick seltsam erscheinen, daß wir hier die Namen der Elementtypen diskutieren. Wie das Sprichtwort sagt, »Namen sind Schall und Rauch«. Aus Sicht des Computers ist das sicherlich richtig; ihm ist es egal, welchen Namen ein Elementtyp besitzt. Aber da immer noch Menschen die Texte schreiben, ist es sinnvoll, »sprechende« Namen zu verwenden. Dies ist letzlich auch die Idee des Generic Markup, die wir am Anfang des Seminars als eine Motivation genannt haben.

Für einfache, konkrete Faustregeln zur Bildung von Elementnamen machen wir folgende Vorschläge:

Diese Regeln sind nicht für alle Anwendungen geeignet. Insbesondere bei Gliederungselementen befindet man sich häufig in einem Zwiespalt. Wir wollen dies an folgenden Alternativen für die Benennung des ersten Kapitels eines Buches demonstrieren. Die erste Variante sieht so aus:
<buch>
  <einfuehrung>
    ...
  </einfuehrung>
  ...
</buch>
Und hier folgt die zweite Fassung:
<buch>
  <kapitel>
    ...
  </kapitel>
  ...
</buch>
Selbstverständlich enthält die erste Version mehr Informationen. Hier ist ganz klar, daß das erste Element im Buch die Einführung ist. Im zweiten Beispiel kann man nicht mehr darüber aussagen, als daß es sich um das erste Kapitel handelt, aber nicht welche Funktion es erfüllt.

Welche Lösung Sie in einem solchen Fall wählen sollten, hängt von Ihrer konkreten Anwendung ab. Können Sie auf die zusätzliche Information verzichten? Falls Sie aus all Ihren Texten die einführenden Worte extrahieren möchten, bekommen Sie im zweiten Beispiel Probleme. Denn dann muß ein menschlicher Leser nachsehen, ob das erste Kapitel wirklich eine Einleitung ist oder ob der Autor eine Einführung wegläßt und sofort in medias res geht.

Auf der anderen Seite ist es natürlich leichter, in der DTD nicht auf alle Besonderheiten Rücksicht zu nehmen. In diesem Beispiel kann man noch einen Kompromiß eingehen. Dazu versehen wir den Elementtyp kapitel mit einem Attribut namens inhalt. Als mögliche Werte erlauben wir in der DTD einfuehrung und normal. Das obige Beispiel schreiben wir nun folgendermaßen:
<!-- In der DTD: -->
<!ELEMENT kapitel ...>
<!ATTLIST kapitel inhalt (normal|einfuehrung) normal>
<!-- In der Instanz: -->
<buch>
  <kapitel inhalt="einfuehrung">
    ...
  </kapitel>
  <kapitel>
    ...
  </kapitel>
  ...
</buch>
Auf diese Weise haben wir sowohl die Gliederungsinformation als auch die Information über den Inhalt. Der Aufzählungstyp des Attributs verhindert, daß ein Autor unvorhergesehene Begriffe eingibt (nur einfuehrung und normal sind erlaubt). Er läßt sich aber bei Bedarf leicht erweitern.

Wir sind damit schon bei der nächsten philosophischen Frage angelangt: »Soll ich Elemente oder Attribute verwenden?«

Meistens lassen sich -- mit mehr oder weniger großem Aufwand -- Elemente und Attribute ineinander umwandeln. Wir zeigen dies an einigen Beispielen. Zuerst zwei Möglichkeiten, die Überschrift eines Kapitels in einem Dokument unterzubringen.

<kapitel ueberschrift="Entwicklung einer DTD">
  ...
</kapitel>
 
<kapitel>
  <ueberschrift>Entwicklung einer DTD</ueberschrift>
  ...
</kapitel>
Die gewünschte Information ist in beiden Fällen vorhanden, wo liegen also die Unterschiede? -- Attribute erlauben die Definition einer eingeschränkten Menge von erlaubten Werten. Dies ist hier sicherlich nicht sinnvoll. Andererseits können Sie für Elemente das Inhaltsmodell angeben; es können also eingebettete Elemente existieren. Dies geht bei Attributen nicht. Möchten Sie in Überschriften Auszeichnungen zulassen, so müssen Sie sich für das Element und gegen das Attribut entscheiden. In der folgenden Anwendung ist beispielsweise die DTD als acro ausgezeichnet, um den Inhalt als Akronym zu identifizeren.
<kapitel>
  <ueberschrift>Entwicklung einer <acro>DTD</acro></ueberschrift>
  ...
</kapitel>
Als weiteren Grund für die Verwendung der Element-Variante in diesem Fall möchten wir anführen, daß die Überschrift ein Teil des Inhalts des Dokuments ist und als solcher in einem Element stehen sollte. Den anderen Fall zeigen wir mit einem weiteren Beispiel.
Hier geht es darum, eine Liste Ihrer Musiksammlung zu verwalten. Neben den Informationen wie Musiker, Band, Titel, Erscheinungsjahr und so weiter, möchten Sie auch noch abgespeichern, auf welchem Aufnahmemedium, also Vinyl, CD oder MC, Sie die Aufnahme vorliegen haben. Wir zeigen auch hier wieder zwei Varianten, zunächst ausschließlich mit Elementen, dann mit einem Attribut.
<album>
 <medium>Vinyl</medium>
 <musiker>Jackson Browne</musiker>
 <titel>For Everyman</titel>
 <jahr>1973</jahr>
 <label>Asylum Records</label>
 ...
</album>
<album>
 <medium>CD</medium>
 <musiker>Jackson Browne</musiker>
 <titel>Running on Empty</titel>
 <jahr>1977</jahr>
 <label>Elektra/Asylum Records</label>
 ...
</album>

Es folgt die Attribut-Alternative:

<album medium="Vinyl">
 <musiker>Jackson Browne</musiker>
 <titel>For Everyman</titel>
 <jahr>1973</jahr>
 <label>Asylum Records</label>
 ...
</album>
<album medium="CD">
 <musiker>Jackson Browne</musiker>
 <titel>Running on Empty</titel>
 <jahr>1977</jahr>
 <label>Elektra/Asylum Records</label>
 ...
</album>

Hier ist die Information »Vinyl« beziehungsweise »CD« kein eigentlicher Bestandteil des Dokumentinhalts. Es handelt sich vielmehr um eine Information über den Inhalt; es ist eine Klassifizierung. In gleicher Weise könnten Sie auch festhalten, ob es sich bei der Aufnahme um eine reguläre Veröffentlichung oder um einen halboffiziellen Konzertmitschnitt handelt. Auch dies ist eine Metainformation. Die Attributvariante erscheint deshalb in diesen beiden Fällen angebracht. Ein weiteres Argument dafür ist, daß hier nur eine begrenzte Anzahl von Möglichkeiten existiert. Das Attribut sollten Sie daher folgendermaßen in der DTD definieren.
<!--      Element     Attributname   Werte            Vorgabe -->
<!ATTLIST album       medium         (Vinyl, CD, MC)  Vinyl     >
Eine Einschränkung auf diese drei Werte ist bei einem Element nicht möglich. Bisher haben wir einen Weg verschwiegen. Wir haben die Elemente, zuletzt medium, den anderen Elementen stets gleichgesetzt. XML erlaubt bekanntlich aber auch die Verschachtelung. Sie könnten Ihre Musiksammlung also auch so speichern:
<album>
 <vinyl>
    <musiker>Jackson Browne</musiker>
    <titel>For Everyman</titel>
    <jahr>1973</jahr>
    <label>Asylum Records</label>
    ...
 </vinyl>
</album>
<album>
 <cd>
    <musiker>Jackson Browne</musiker>
    <titel>Running on Empty</titel>
    <jahr>1977</jahr>
    <label>Elektra/Asylum Records</label>
    ...
 </cd>
</album>
Hier ist die fragliche Information nun nicht mehr im Inhalt des Elements medium enthalten, sondern befindet sich im Namen der neuen Elemente vinyl, cd und mc. Dieser Ansatz bietet ähnliche Vorteile wie das Attribut: Zusammen mit folgender Definition des übergeordneten Elements album stehen auch hier nur die drei Wahlmöglichkeiten zur Verfügung.
<!ELEMENT album  (vinyl | cd | mc) >
Wir favorisieren hier dennoch die Attribut-Variante, allerdings aus einem eher pragmatischen Grund heraus. Das Inhaltsmodell von vinyl, cd und mc ist identisch. Selbst wenn noch weitere Alternativen hinzukommen, etwa DVD oder Tonband, wird sich daran nichts ändern. Es besteht daher keine Notwendigkeit, drei Elementtypen zu verwenden, da sie alle gleich aufgebaut sind. Anders ist das, wenn die Elementtypen unterschiedliche Inhaltsmodelle besitzen. Dies wollen wir noch kurz erläutern, ohne jedoch ein Beispieldokument zu zeigen.
Eine Liste von Büchern, wie in der Bibliographie zu diesem Buch, ist sehr ähnlich zu obiger Musiksammlung. An die Stelle des Musikers tritt der Autor, das Label entspricht dem Verlag und so weiter. Das Aufnahmemedium entspricht ungefähr der Publikationsform, also Buch, Artikel, technischer Report, Doktorarbeit, Handbuch usw. Auch diese Information kann nun in der zuvor diskutierten Weise gespeichert werden. Im Gegensatz zu den Musikdaten empfiehlt sich hier jedoch nicht die Attributlösung, sondern die Verwendung des zuletzt gezeigten Ansatzes, der hier etwa so aussieht:
<!ELEMENT publikation    ( buch | artikel | techreport | 
                           dokarbeit | handbuch ) >
Wir entscheiden uns für Elemente statt Attribute, weil jede dieser Alternativen jeweils ein anderes Inhaltsmodell besitzt. Zum Beispiel gehört zur bibliographischen Information eines Artikels die Angabe, in welcher Zeitschrift er erschienen ist. Bei einem Buch kommt diese Information nicht vor.
Wenn man nun eine Bibliographie aus einer Folge von Publikationen der obigen Form zusammensetzt, sieht das in der DTD wie folgt aus.
<!ELEMENT bibliographie (publikation+)>
Es ist naheliegend, den Elementtyp publikation einzusparen und ein Parameter-Entity daraus zu machen.
<!ENTITY % publikation    "buch | artikel | techreport | 
                           dokarbeit | handbuch ">
<!ELEMENT bibliographie  (%publikation;)+>
Um die Diskussion zu beenden, fassen wir unsere Ausführungen in folgenden Tips zusammen:


... [ Seminar XML (DTD) ] ... [ Einleitung ] ... [ Fallbeispiel ] ...