Sql-und-Xml - Home

Xml lernen

Deklaration von Element-Typen in einer DTD

Vorbemerkungen

  • Charakteristisch für die Element-Typ-Definition und wohl für manche Leser gewöhnungsbedürftig ist die Vorwärts-Deklaration. Bei der Definition eines Element-Typs werden bereits andere Elementnamen verwendet, die zu diesem Zeitpunkt noch unbekannt sind und deren Definition erst später folgt. Beispiel:
    <!ELEMENT myDocument (title, body)>
    <!ELEMENT title (#PCDATA)>
    <!ELEMENT body (#PCDATA)>
    Die erste Zeile definiert das Element 'myDocument' mit den Unterelementen 'title' und 'body'. Beide Elemente werden erst nachfolgend genauer beschrieben.
  • Anstelle der Element- und Content-Spezifikationen können in einer externen DTD auch Parameter-Entities verwendet werden. So wird das obige Element 'myDocument' auch durch die folgenden Zeilen deklariert:
    <!ENTITY % myDocument.global "myDocument">
    <!ENTITY % myDocument.Content "title, body">
    
    <!ELEMENT %myDocument.global; (%myDocument.Content;)>
    Zunächst werden zwei Parameter-Entities deklariert, diese werden anschließend sofort verwendet. Mit solchen Techniken, die erst bei größeren Projekten sinnvoll sind, können bsp. Wiederholungen im Content eines Elements oder Standardattribute (= Attribute, die für viele Elementtypen gelten sollen), erzeugt werden. Da Elementnamen und Entity-Namen zu verschiedenen Namensräumen gehören, hätte man die erste Entity auch wie folgt definieren können:
    <!ENTITY % myDocument "myDocument">
    Aufgrund der Verwendung in der externen DTD, in einer Elementdefinition oder als Element im eigentlichen Xml-Dokument ist die Eindeutigkeit garantiert. Bei einer größeren DTD werden zu Beginn zunächst einmal sehr viele dieser Parameter-Entities definiert, erst anschließend folgen die Elementdeklarationen. Die Darstellung dieses Textes in der umgekehrten Reihenfolge erfolgt aus Verständnisgründen.

Definition von Elementen

  • Elemente werden definiert durch
    <!ELEMENT QNAME CONTENT-SPECIFICATION>
    QNAME (= qualified Name) ist ein selbst festgelegter Name für das Element. Es kann sich um einen 'einfachen Namen' oder um einen Namen, bestehend aus dem namespace prefix und dem local part, verbunden durch den Doppelpunkt als Trenner. Die Xml-Spezifikation von 1998 berücksichtigt das Namespace-Konzept noch nicht. Der Doppelpunkt sollte jedoch ausschließlich zur Trennung von Prefix und lokalem Namen verwendet werden, da alle Parser den Doppelpunkt in diesem Sinne interpretieren.

    Der Content eines Elements kann entweder durch die Schlüsselwörter EMPTY / ANY, also leer bzw. beliebig, oder durch eine Contentangabe in Klammern, also Unterelemente und / oder Text, festgelegt werden.
  • Sind in einem Element nur andere Elemente als Content erlaubt, so wird durch Ausdrücke der Form (Element-1, Element-2) sowohl die Anzahl als auch die Reihenfolge festgelegt - erst genau einmal Element-1, dann genau einmal Element-2. Anstelle der atomaren Elemente können ebenfalls Klammern stehen, die weitere Element-Listen enthalten.
  • Elementnamen können durch die folgenden Zeichen verbunden werden:
    	,		strikte Reihenfolge
    	|		genau eines der beiden Elemente (ausschließend)
  • Erlaubte Quantifikatoren sind
    	?			kein- oder einmal
    	+			ein- oder mehrmals
    	*			kein-, einmal oder mehrmals
    Wird nichts notiert, so bedeutet dies 'genau einmal'. Jeder dieser Blöcke kann geklammert, der Klammerausdruck mit Quantifikatoren versehen und mit weiteren Blöcken kombiniert werden.
  • Ist in einem Element Text erlaubt, so wird dies mit #PCDATA - Parsed Character Data - festgelegt. Dieser Text wird nach eventuell enthaltenen Entities (beginnend mit & und endend mit ;) geparst und diese aufgelöst. Bei einer Definition, die für die Content-Specification nur den Ausdruck '(#PCDATA)' enthält, darf das Element zusätzlich zu den Zeichendaten keine weiteren Unterelemente mehr enthalten. Enthält der Text Entities, so muß auch der Entity-Ersetzungstext elementfrei sein.
  • Sobald ein Element #PCDATA enthält, spricht man von gemischtem Content (= mixed Content). Zusätzlich kann eine Kombination aus #PCDATA und Unterelementen erlaubt sein, diese können selbst wieder gemischten Content enthalten. Die übliche Textdarstellung von Html-Seiten im body-Element, bei welcher Text zusätzliche Auszeichnungen enthält, stellt diesen Typ dar. Bei jedem gemischten Content kann bei der Erstellung der DTD nicht bekannt sein, ob es Text und / oder Unterelemente gibt, da dies vom darzustellenden Inhalt abhängt. So muß Text bsp. keine fett/kursiv auszugebenden Wörter enthalten oder ein Element mit mixed Content kann leer sein. Deshalb kann #PCDATA nicht mit den Quantifikatoren '+' oder '?' ausgezeichnet werden. Wird eine Kombination aus #PCDATA und Unterelementen angegeben, so müssen diese durch | verbunden werden und die umgebende Klammer muß mit '*' ausgezeichnet sein. Auch die Unterelemente dürfen nicht mit '+' oder '?' quantifiziert sein. Deshalb gibt es für mixed Content nur zwei erlaubte Darstellungen:
    <!ELEMENT body (#PCDATA)>
    <!ELEMENT body (#PCDATA | b | i)*>
    Bei der ersten Darstellung kann auf die schließende Klammer auch '*' folgen, die zweite Darstellung kann weitere Elemente enthalten. Die zweite Darstellung darf jedoch keine geklammerte Liste enthalten. Sämtliche der folgenden Darstellungen sind syntaktisch fehlerhaft:
    <!ELEMENT body (#PCDATA?)>
    <!ELEMENT body (#PCDATA)+>
    <!ELEMENT body (#PCDATA, b)>
    <!ELEMENT body (#PCDATA | b*)>
    <!ELEMENT body (#PCDATA | b*)*>
    <!ELEMENT body (#PCDATA | b+)>
    <!ELEMENT body (#PCDATA | b)+>
    <!ELEMENT body (#PCDATA | b | b)*>
    <!ELEMENT body (#PCDATA | b | (c | d))>
    Man kann also nicht fordern, daß Text höchstens / mindestens ein Zeichen enthält, daß auf Text ein abschließendes Element folgt, das eventuell sogar weggelassen werden kann (b*) oder daß mindestens Text oder ein Element folgt. Auch der Ausdruck '(#PCDATA | b*)*', der eigentlich mehr erlaubt als der Ausdruck '(#PCDATA | b)*', ist wegen des inneren '*' nicht erlaubt. Ferner ist bei gemischtem Content eine Verdoppelung 'b | b' nicht zulässig, auch dürfen keine zusätzlichen Klammern gesetzt werden.

Beispiele für Element-Definitionen

  • <!ELEMENT my-hr EMPTY>
    Dies ist die Html-Definition des html:hr-Elements - dieses enthält keine Unterelemente. Statt EMPTY könnte für ein eigenes Element auch ANY stehen - dann wären sowohl Unterelemente als auch Text zulässig. Beachten Sie, daß EMPTY hier tatsächlich strikt EMPTY heißt - weder Leerzeichen noch ein Zeilenumbruch. Um bei einer solchen Definition Fehler zu vermeiden, empfiehlt sich die Verwendung der speziellen Form für leere Elemente:
    <my-hr/>
  • <!ELEMENT notice (#PCDATA)>
    Das Element 'notice' darf nur Text und Entities enthalten, deren Ersetzungstext elementfrei ist. Unterelemente sind ausgeschlossen.
  • <!ELEMENT notice-formatted (#PCDATA | b | u | i)*>
    Hier sind zusätzlich zum Text auch die Unterelemente b, u und i erlaubt. Dies bedeutet nicht, daß eines dieser Elemente Unterelement von einem der anderen Elemente sein darf oder daß eines dieser Elemente Text enthält. All diese Dinge müssen bei der Definition von b, u und i festgelegt werden.
  • <!ELEMENT html (head, body)>
    Dies ist die Definition des Html-Elements html. In diesem sind genau zwei Unterelemente - head und body - erlaubt, die Reihenfolge ist strikt vorgegeben. Implizit ist damit ausgedrückt, daß jedes Element genau einmal auftreten darf, es darf weder fehlen noch darf es mehrfach auftreten.
  • <!ELEMENT head (title, meta*)>
    Damit wird festgelegt, daß im head-Element genau ein title-Element, gefolgt von 0, einem oder mehreren meta-Elementen gefordert wird.
  • <!ELEMENT head ((title, meta*) | (meta*, title))>
    Eine solche Definition heißt: {Entweder title und 0 oder mehrere meta} oder {0 oder mehrere meta und ein title-Element}. Anders ausgedrückt: title muß genau einmal im head vorkommen, ein Block von meta-Elementen kann vor oder nach dem title-Element eingefügt werden, der meta-Block muß jedoch zusammenhängend sein.
  • <!ELEMENT head (meta*, title, meta*)>
    Hier ist ebenfalls ein title-Element zwingend, die meta können jedoch sowohl vor als auch nach title folgen, sie müssen nicht aufeinander folgen.
  • <!ELEMENT tr (th+ | td+)>
    Das Element tr hat entweder mehrere Unterelemente th oder mehrere Unterelemente td, es ist jedoch weder Text noch ein leeres tr erlaubt. Ferner dürfen nicht beide Unterelemente gleichzeitig auftreten. Dies entspricht der Situation in Html, in der bei einer Zeile tr entweder Tabellenheader th oder Tabellenzellen td sinnvoll sind. Ersetzt man eines der '+' durch ein '*', so erfüllt auch ein leeres tr-Element diese Definition.
  • <!ELEMENT tr (td, td, td)>
    <!ELEMENT tr (td, td, td?, td?, td)>
    <!ELEMENT tr (td, td+, td)>
    
    Mit solchen, offenbar zwar möglichen, aber nicht mehr sehr intuitiven Konstruktionen lassen sich gewisse Unterstrukturen festlegen. Die erste Definition verlangt strikt drei Elemente, die zweite Definition fordert drei und ermöglicht zweimal 0 oder 1, maximal also fünf Elemente. Die dritte Definition wünscht zwei Elemente fixiert sowie eine Folge von td, bestehend aus mindestens einem Element. Also entspricht dies der Bedingung 'mindestens drei td-Unterelemente'.


© 2003-2016 Jürgen Auer, Berlin.