XML Basics / XML-Datenstruktur - Typen

XML-Datenstruktur - Typen

XML-Datenstruktur - Typen

Das Datenformat XML ist außerordentlich gestaltungsflexibel. Das hat Konsequenzen für die Art der automatischen Verarbeitung.

XML-Datenstruktur - Typen

Grundsätzlich lassen sich XML Dokumente unterteilen in

Jede dieser Strukturierungsalternativen erfordert andere Vorgehensweisen bei der systematischen Verarbeitung. Die vorliegende Arbeit legt ihren Schwerpunkt auf starke, datenzentrierte Strukturierung der XML Dokumente. Daher möchte ich hier nur kurz auf schwach strukturierte Dokumente oder auf Dokumente mit mixed Content eingehen.

XML: Schwach strukturierte Dokumente


<?xml version="1.0" encoding="iso-8859-1"?>
<root>Die enorme Gestaltungsflexibilität 
zwingt zu systematischer Strukturierung, 
damit die XML Dokumente systematisch 
ausgewertet werden können.</root>

Abgesehen vom XML Prolog und dem "<root>"-Element, ist das vorstehende XML Dokument zwar wohlgeformt, aber im Übrigen unstrukturiert. Das wird auch nicht besser, wenn einige Tausend Sätze hinzu kommen, die ebenfalls keine strukturierenden Elemente beinhalten. Es bleibt unserer Fantasie oder unserer Bereitschaft zur Spekulation überlassen, hier eine klare Struktur erraten zu wollen, die sich systematisch auswerten ließe. Gerade der völlige Mangel an systematischer Strukturierung zeigt, wie eingeschränkt die anschließende Auswertbarkeit ist.

Eine schwache Strukturierung kann beispielsweise entstehen, wenn einzelne Textteile hervorgehoben werden, etwa durch "... damit die <hervorheben>XML</hervorheben> Dokumente systematisch ...". Dann haben wir es mit einer gemischten Abfolge aus Textinhalt und Formatierungsanweisungen zu tun, deren Abfolge kaum vorhersehbar ist und die eine hohe Flexibilität bei der Programmierung erfordert.

Das wiederum läßt vermuten, daß wir in diesem Umfeld mit der Anwendung von "xsl:for-each" Mühe haben werden. Sinnvoller scheint die Arbeit mit "xsl:template match" bzw. "xsl:apply-templates", die eine Aufsplittung der Programmierlogik in mehrere Templates mit sich bringt.

Solange der Überblick über die ggf. sehr zahlreichen (Hunderte, Tausende) Templates gewährleistet ist (optimalerweise durch eine effiziente Koordination der Teamarbeit), sind keine Probleme für die flexible Anpassung der Programmlogik zu erwarten. Eine weniger qualitätsbewußte Teamarbeit birgt jedoch Gefahren der Unübersichtlichkeit und hoher Wartungskosten.

XML-Struktur: Mixed Content

Das folgende Beispiel zeigt einen Mix aus klarer Basisstruktur, die mit XPath gezielt adressiert werden kann ("Abschnitt/para") und einer gemischten Abfolge aus Textinhalt und Formatierungsanweisungen (innerhalb para: text(), kursiv, fett, link), für deren systematische Auswertbarkeit eine hohe Flexibilität erforderlich ist.

Während es sich anbietet, die "Abschnitt/para"-Struktur durch zu verarbeiten, bleibt für die Formatierungsanweisungen innerhalb "para" vorrangig die Arbeit mit "xsl:template match" bzw. . So vielfältig wie die Input-Struktur dürfte auch die Programmierlogik bei deren Auswertung gestaltet werden. Auch hier empfiehlt sich eine effiziente, qualitätsbewußte Koordination der Teamarbeit, um die langfristigen Wartungskosten unter Kontrolle zu behalten.


<?xml version="1.0" encoding="iso-8859-1"?>
<Abschnitt>
  <title>Namespaces</title>
  <para>Die enorme Gestaltungsflexibilität der 
<kursiv>XML Dokumente</kursiv> zwingt zu 
<fett>systematischer Strukturierung</fett>, 
damit die <kursiv>XML Dokumente</kursiv> 
systematisch ausgewertet werden können.</para>
<para>Aber auch eine klare systematische 
Strukturierung von <kursiv><fett>Element- und 
Attributnamen</fett></kursiv> sowie deren 
<fett><kursiv>Datentypen</kursiv></fett> 
(etwa durch <link 
l="http://www.w3.org/2001/XMLSchema">XML Schema</link>) 
reicht nicht immer aus, begriffliche 
Kollisionen zu vermeiden. </para>
</Abschnitt>

XML: Stark strukturierte Dokumente

Stark strukturierte XML Dokumente (das Kernthema der vorliegenden Arbeit) haben häufig einen klaren, hierarchischen Aufbau, der sich entsprechend systematisch auswerten läßt.

Das ist aber keine Selbstverständlichkeit. Es kann schnell passieren, daß die Datenstruktur des XML-Input-Dokuments auf verschiedene Ebenen verteilt ist und gegenseitige Abhängigkeiten aufweist, die in der Programmierlogik mittels XPath mehr oder weniger aufwändig nachvollzogen werden müssen. Das wird spätestens dann ein Problem, wenn die internen Abhängigkeiten nicht im Input - XML Schema (und auch sonst nirgendwo) dokumentiert sind, so daß die automatisierte Kontrolle erschwert ist.

Ebenso kann es vorkommen, daß der strukturelle Aufbau des XML Dokuments sich nur aus der sequenziellen Abfolge der einzelnen Elemente ergibt, ohne daß eine hierarchische Strukturierung vorliegt. Abhängig von diesen unterschiedlichen Datenstrukturen müssen auch unterschiedliche Verarbeitungskonzepte bereit stehen.

XML: Hierarchischer Aufbau

Der einfachste Ansatz ist das folgende XML Dokument: ein Rootelement Orte hat mehrere Childelemente Ort (jeweils mit id und name); jeder Ort hat mehrere Child-Elemente Mensch (mit id, name, vorname, Gehalt und idOrt), und jeder Mensch kann darüberhinaus noch mehrere Childelemente Kauf haben (mit den Childelementen idMensch, anzahl, bez, preis und Gesamt, die jeweils nur einmal auftreten können).


<?xml version="1.0" standalone="yes"?>
<Orte>
  <Ort>
    <id>1</id>
    <name>Neustadt</name>
    <Mensch>
      <id>1</id>
      <name>Holzflos</name>
      <vorname>Hugo</vorname>
      <Gehalt>234.56</Gehalt>
      <idOrt>1</idOrt>
      <Kauf>
        <idMensch>1</idMensch>
        <anzahl>3</anzahl>
        <bez>Hemd</bez>
        <preis>12.99</preis>
        <Gesamt>38.97</Gesamt>
      </Kauf>
    </Mensch>
  </Ort>
</Orte>

Diese komfortable hierarchische Struktur läßt sich gut mit XPath auswerten. Sie verdeutlicht das Zusammenspiel von XPath mit XSLT und deren jeweiligen Funktionen sehr gut. In diesem Beispiel lassen sich XPath-Statements wie


   /Orte/Ort[name='Neustadt']/Mensch/Kauf[bez='Hemd']/Gesamt 

auf einfache Weise nachvollziehen. Sie erbringt eine Elementliste sämtlicher Gesamt-Felder von Menschen, die in Neustadt wohnen und sich ein oder mehrere Hemden gekauft haben.

Das XML Dokument entspricht einem XML Schema, das Constraints (Beziehungen von Primär- und Fremdschlüsseln) sichtbar macht.

pic/Datenbank_ADONET_Schema.png


<?xml version="1.0" standalone="yes"?>
<xs:schema id="Orte" xmlns="" 
 xmlns:xs="http://www.w3.org/2001/XMLSchema" 
 xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
 <xs:element name="Orte" 
   msdata:IsDataSet="true" msdata:Locale="de-DE">
  <xs:complexType>
   <xs:choice maxOccurs="unbounded">
    <xs:element name="Ort">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="id" type="xs:int" minOccurs="0" />
       <xs:element name="name" type="xs:string" minOccurs="0" />
       <xs:element name="Mensch" minOccurs="0" maxOccurs="unbounded">
        <xs:complexType>
         <xs:sequence>
          <xs:element name="id" type="xs:int" minOccurs="0" />
          <xs:element name="name" type="xs:string" minOccurs="0" />
          <xs:element name="vorname" type="xs:string" minOccurs="0" />
          <xs:element name="Gehalt" type="xs:string" minOccurs="0" />
          <xs:element name="idOrt" type="xs:int" minOccurs="0" />
          <xs:element name="Kauf" minOccurs="0" maxOccurs="unbounded">
           <xs:complexType>
            <xs:sequence>
             <xs:element name="idMensch" type="xs:int" minOccurs="0" />
             <xs:element name="anzahl" type="xs:int" minOccurs="0" />
             <xs:element name="bez" type="xs:string" minOccurs="0" />
             <xs:element name="preis" type="xs:double" minOccurs="0" />
             <xs:element name="Gesamt" type="xs:double" minOccurs="0" />
            </xs:sequence>
           </xs:complexType>
          </xs:element>
         </xs:sequence>
        </xs:complexType>
       </xs:element>
      </xs:sequence>
     </xs:complexType>
    </xs:element>
   </xs:choice>
  </xs:complexType>
  <xs:unique name="Mensch_Constraint1" 
   msdata:ConstraintName="Constraint1">
   <xs:selector xpath=".//Mensch" />
   <xs:field xpath="id" />
  </xs:unique>
  <xs:unique name="Constraint1">
   <xs:selector xpath=".//Ort" />
   <xs:field xpath="id" />
  </xs:unique>
  <xs:keyref name="relationOrtMensch" 
   refer="Constraint1" msdata:IsNested="true">
   <xs:selector xpath=".//Mensch" />
   <xs:field xpath="idOrt" />
  </xs:keyref>
  <xs:keyref name="relationMenschKauf" 
   refer="Mensch_Constraint1" msdata:IsNested="true">
   <xs:selector xpath=".//Kauf" />
   <xs:field xpath="idMensch" />
  </xs:keyref>
 </xs:element>
</xs:schema>

XML: Aufbau entspricht der SQL-Datenbankstruktur

Obwohl die Inhalte des folgenden XML Dokuments sachlich identisch sind mit dem vorher dargestellten Beispiel, ist doch deren struktureller Aufbau ein völlig anderer, was auch eine aufwändigere Programmierlogik der XPath-Statements erfordert, die die XML Input Dokumente auswertbar machen sollen.

Im folgenden Beispiel bringt das vorhin erwähnte XPath-Statement "/ROOT/Ort[name='Neustadt']/Mensch/Kauf[bez='Hemd']/Gesamt" kein Ergebnis. Ganz abgesehen davon, daß die Felder "Kauf/bez" und "Kauf/Gesamt" hier nicht existieren, muß die Verknüpfung zum Ort "Neustadt" ziemlich aufwändig durch zusätzliche temporäre Variablen hergestellt werden. Dazu später mehr.


<ROOT>
  <Ort>
    <id>1</id>
    <name>Neustadt</name>
  </Ort>
  <Mensch>
    <id>1</id>
    <name>Holzflos</name>
    <vorname>Hugo</vorname>
    <Gehalt>234.56</Gehalt>
    <idOrt>1</idOrt>
  </Mensch>
  <Ware>
    <id>1</id>
    <bez>Hemd</bez>
    <preis>12.99</preis>
  </Ware>
  <Kauf>
    <id>1</id>
    <anzahl>3</anzahl>
    <idMensch>1</idMensch>
    <idWare>1</idWare>
  </Kauf>
</ROOT>

Eine veränderte Situation liegt vor, wenn die Struktur des XML-Input-Dokuments dem Ergebnis der Datenbankabfragen entspricht, wenn also die komplexen XML Elemente im Grunde genommen Datensätze darstellen. Solchermaßen veränderte Strukturen machen die Formulierung der XPath-Statements (und deren Pflege) nicht unbedingt einfacher.

pic/Datenbank_ADONET_Schema_2.png


<xs:schema id="ROOT" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" 
  xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
 <xs:element name="ROOT" 
  msdata:IsDataSet="true" 
  msdata:UseCurrentLocale="true">
  <xs:complexType>
   <xs:choice maxOccurs="unbounded">
    <xs:element name="Ort">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="id" type="xs:int" />
       <xs:element name="name" type="xs:string" />
      </xs:sequence>
     </xs:complexType>
    </xs:element>
    <xs:element name="Mensch">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="id" type="xs:int" />
       <xs:element name="name" type="xs:string" />
       <xs:element name="vorname" type="xs:string" />
       <xs:element name="Gehalt" type="xs:string" />
       <xs:element name="idOrt" type="xs:int" />
      </xs:sequence>
     </xs:complexType>
    </xs:element>
    <xs:element name="Ware">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="id" type="xs:int" />
       <xs:element name="bez" type="xs:string" />
       <xs:element name="preis" type="xs:double" />
      </xs:sequence>
     </xs:complexType>
    </xs:element>
    <xs:element name="Kauf">
     <xs:complexType>
      <xs:sequence>
       <xs:element name="id" type="xs:int" />
       <xs:element name="anzahl" type="xs:int" />
       <xs:element name="idMensch" type="xs:int" />
       <xs:element name="idWare" type="xs:int" />
      </xs:sequence>
     </xs:complexType>
    </xs:element>
   </xs:choice>
  </xs:complexType>
 </xs:element>
</xs:schema>

XML: Namespace-definierte Struktur

Es ist auch möglich, Namespaces zu verwenden, um alternative Datenstrukturen zu definieren - beispielsweise mit der Folge, daß es innerhalb eines Elementes identische Attributnamen geben kann, wenn man die Attributschreibweise wählt.


<ROOT xmlns:o="Ort" xmlns:m="Mensch">
  <element o:id="1" o:name="Neustadt" m:id="4" 
    m:name="Nixlos" m:vorname="Nicole" 
    m:Gehalt="1234.56" m:idOrt="1" />
  <element o:id="1" o:name="Neustadt" m:id="9" 
    m:name="Sprachlos" m:vorname="Stefan" 
    m:Gehalt="5430" m:idOrt="1" />
  <element o:id="3" o:name="Kapstadt" m:id="5" 
    m:name="Witzlos" m:vorname="Willi" 
    m:Gehalt="6789" m:idOrt="3" />
  <element o:id="3" o:name="Kapstadt" m:id="6" 
    m:name="Bodenlos" m:vorname="Betty" 
    m:Gehalt="3450" m:idOrt="3" />
</ROOT>

XML: Sequenzielle Dokument-Struktur

Stellen Sie sich einmal vor, die hierarchische Struktur würde weitestgehend fehlen, und wir hätten es mit einer rein sequenziellen XML Struktur zu tun, deren inhaltliche Abhängigkeiten durch die Anschlußprogrammierung erst einmal abgebildet werden müßten, um sie auswerten zu können.


<ROOT>
  <id>1</id>
  <name>Neustadt</name>
  <id>1</id>
  <name>Holzflos</name>
  <vorname>Hugo</vorname>
  <Gehalt>234.56</Gehalt>
  <idOrt>1</idOrt>
  <idMensch>1</idMensch>
  <anzahl>3</anzahl>
  <bez>Hemd</bez>
  <preis>12.99</preis>
  <Gesamt>38.97</Gesamt>
</ROOT>

Inhaltlich ist das XML Dokument identisch zu dem erstgenannten Beispiele - lediglich mit einem komplett veränderten strukturellen Aufbau. (Streng genommen, hätte man hier ohne Informationsverlust sogar noch auf die "Fremdschlüssel" idOrt und idMensch sowie auf das Gesamt-Feld verzichten können, da sie sich aus dem Kontext der Sequenz ergeben.) Auch so etwas kommt in der Praxis vor, und es stellt sich die Frage, wie in diesem Fall vorgegangen werden kann.

wg / 6. November 2017



Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf:

Vorname
Nachname
Mailadresse







Vielen Dank für Ihr Interesse an meiner Arbeit.


V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

Mobil: 0151. 750 360 61 * eMail: info2018@wilfried-grupe.de

www.wilfried-grupe.de/XML_Strukturalternativen.html