Design Patterns für XML

Motivation

Mit der zunehmenden Verbreitung von XML-Datenaustauschformaten haben viele Autoren von immer neuen XML DTDs und Schemata die gleichen Probleme immer wieder neu gelöst. Daraus ist der Ansatz geboren, die Quintessenz daraus - Design Patterns - ähnlich wie Gamma et al. in Design Patterns: Elements of Reusable Object-Oriented Software, zusammenzutragen.

Überblick

Anders als bei den objekt-orientierten Design Patterns, die alle etwa den gleichen Abstraktionsgrad haben, gibt es bei den XML Design Patterns unterschiedliche Kategorien:

Im folgenden werde ich diese Gruppen etwas genauer vorstellen und charakteristische Beispiele herausgreifen und diese mit bereits existierenden Ideen vergleichen.

Anleitungen zum XML Dokumentenentwurf

Kyle Downey stellt in Architectural Design Patterns for XML Documents dazu einige Ideen vor. Die wichtigsten sind:

Dynamic Document

Wenn man ein XML Format braucht, ohne sich vorher Gedanken darüber machen zu müssen oder man weiß, dass sich die Anforderungen garantiert ändern werden und man nicht die volle Kontrolle über das Datenformat behalten kann, kann man sich das XML Format durch automatische Serialsierung erzeugen lassen.
Aus

  public Person {
     public String getName() { ... }
     public void setName(String name) { ... }
     public Address getAddress() { ... }
     public void setAddress(Address address) { ... }
  }

  public Address {
     public String getCity() { ... }
     public void setCity(String city) { ... }
     public String getState() { ... }
     public void setState(String state) { ... }
  }

wird dann...

 <person>
     <name>Kyle Downey</name>
     <address>
         <city>Forest Hills</city>
         <state>Queens</state>
     </address>
 </person>

Dieses Verfahren wird im Zusammenhang mit OO Systemen, wie .NET und Java bereits standardmäßig eingesetzt.

Compostion

Da viele Elemente schon in der einen oder anderen Ontologie definiert sind, besteht nicht immer die Notwendigkeit, z.B. das <author>-Element neu zu definieren. Stattdessen kann man auch das <creator>-Element vom Dublin Core nehmen. Dies ist eine weit verbreitete Praxis z.B. im Web Service Bereich.

Multipart Files

Ähnlich wie das C++ #include oder Java import kann man sich ein entsprechendes Element definieren, um XML-Dokumente beliebig klein zu stückeln. Bei der XML-Programmiersprache XSLT wird das ebenso wie in XML Schemas, WSDL und SOAP (Attachments) eingesetzt.

Spezifische Design Patterns

www.xmlpatterns.com ist eine Website, die sich speziell diesem Thema widmet und XML Design Patterns kategorisiert sammelt.

Universal Root

Wenn man XML für Transaktionen einsetzen möchte, die prinzipiell unabhängig voneinander sind, kann man diese in einem Trankaktions-Element Kapseln.

<Transaction>
  <AddAddress>
    <AddressBookEntry> ... </AddressBookEntry>
  </AddAddress>
</Transaction>

und

<Transaction>
  <RemoveAddress>
    <AddressBookEntry> ... </AddressBookEntry>
  </RemoveAddress>
</Transaction>

wären dann zwei unterschiedliche Tranksationen.

Head-Body

Vielleicht ist dies das bekannteste Design Pattern in XML. Es kommt dann zum Einsatz, wenn man viele Metadaten zu einem Dokument hat und diese strukturieren möchte. Es wird z.B. in (X)HTML und SOAP verwendet.

<Document>
  <Head>
    <Author>John Doe</Author>
    <Author>Frank Black</Author>
    <CreationDate>June 16, 1999</CreationDate>
  </Head>
  <Body>
    This is a document.
  </Body>
</Document>

Container Element

Verwandt dem Composite-Pattern der Gang of Four ist die Idee, Daten eher hierarchisch statt flach zu speichern, um die Handhabbarkeit bzw. Übersicht zu erhöhen. Aus

<ComputerConfiguration>
  <RAM>128 MB</RAM>
  <WordProcessor>WordPerfect</WordProcessor>
  <HardDriveSize>8GB</HardDriveSize>
  <XMLParser>Xerces</XMLParser>
</ComputerConfiguration>

wird dann

<ComputerConfiguration>
  <Software>
    <Wordprocessor>Wordperfect</Wordprocessor>
    <XMLParser>Xerces</XMLParser>
  </Software>
  <Hardware>
    <RAM>128 MB<RAM>
    <HardDriveSize>8 GB</HardDriveSize>
  </Hardware>
</ComputerConfiguration>

Marketplace

Genauso wie man sich beim Design von Tabellen für relationalen Datenbanken nicht entscheiden kann, ob ein Manager nun ein Manager oder ein Angestellter der Firma ist, ist es unmöglich zu entscheiden, ob das <Manager>-Element in <Managers> oder in <Employees> sein sollte.

<Employees>
  <Managers>
    <Person type="salaried">
      Riff Raff
    </Person>
    <Person type="contractor">
      Frank Furter
    </Person>
  </Managers>
  <Workers>
    <Person type="salaried">
      Brad Majors
    </Person>
    <Person type="contractor">
      Janet Weiss
    </Person>
  </Workers>
</Employees>

Dementsprechend gibt es in XML auch die gleichen Lösungsansätze für dieses Problem. Die einfachste ist eine flache Liste, in alle Angestellten eingetragen sind, mit ihrem Beschäftigungsstatus als Attribut.

<Employees>
  <Person type="salaried" level="manager">
    Riff Raff
  </Person>
  <Person type="contractor" level="manager">
    Frank Furter
  </Person>
  <Person type="salaried" level="worker">
    Brad
  </Person>
  <Person type="contractor" level="worker">
    Janet
  </Person>
</Employees>

Referenced Note

Bei genauer Betrachtung handelt es sich wie auch bei Marketplace um das Problem, Redundanz zu vermeiden. Der Klassische Ansatz in der relationalen Modellierung ist die Benutzung von Fremdschlüsseln. Das ist auch in XML-Dokumenten möglich, wird aber bei weitem nicht so häufig eingesetzt. Für Fußnoten ist es aber durchaus üblich:

<Paragraph>
  This paragraph refers to a note.
  <NoteReference ref="1"/>
</Paragraph>
<Note id="1">This is the note.</Note>

Use XML

Schon so selbstverständlich, dass man es fast vergessen könnte: Immer dann, wenn man sich nicht in einer homogenen Umgebung befindet und man nicht um jedes gesparte Byte kämpfen muss, sollte man XML zur Datenspeicherung in betracht ziehen, weil dann die bekannten Vorteile von XML zur Geltung kommen:

Offensichtlich handelt es sich hier nicht um ein XML- sondern um ein Software Develoment-Pattern, also ein Bisschen Eigenwerbung... :)

Domain-spezifische Tipps

Wohl am meisten Anleitungen gibt es für die unzähligen speziellen XML-Anwendungen. Z.B. für XML als Textbeschreibung.

Running Text Pattern

In Texten wie (X)HTML will man erstmal alles zulassen. Um doch noch ein Bisschen Struktur zu formalisieren, kann man ein Element RunningText einführen:

    <!ENTITY % RunningText
    '
    #PCDATA|Quote|Emphasis|MathML|Phrase|BibRef|
    FootNoteReference
    '
    >
 

überall, wo man dann generelle Beschreibungen zulassen will, kann man dann RunningText erlauben, wie zum Beispiel in einem FootnoteBody der eine Fußnote beschreibt.

Zusammenfassung

Es gibt bereits eine Fülle an Empfehlungen für das Design von XML-Dokumenten, von denen ich nur einige vorgestellt habe, die einen guten Eindruck vermitteln sollten. Einige dieser Ideen kommen vom objekt-orientierten Entwurf, einige aus der relationalen Welt. Viele sind aber neu, weil sie sich vorher noch nicht so gestellt haben.

Nicht eingegangen bin ich auf spezielle Detailfragen, wie die Grundsatzfrage, ob man Informationen lieber in Attributen oder Elementen speichern sollte, weil sich da keine einheitliche Meinung durchgesetzt hat. Eine Linksammlung mit weiterführenden Themen befindet sich hier.