Home
Über mich
Blog
Veröffentlichungen
IT-Trainings
Impressum


XML: Die Sache mit den Namespaces

Zusammenfassung:

Die enorme Gestaltungsflexibilität der XML Dokumente zwingt zu systematischer Strukturierung, damit die XML-Dokumente systematisch ausgewertet werden können. Aber auch eine klare Festlegung von Element- und Attributnamen sowie deren Datentypen (etwa durch XML Schema) reicht nicht immer aus, Mehrdeutigkeiten und begriffliche Kollisionen zu vermeiden.

XML: Die Sache mit den Namespaces

Ein einfaches Beispiel ist das Wort "Bruch", hinter dem sich eine ganze Anzahl möglicher Bedeutungen verbergen kann: Knochenbruch, Steinbruch, mathematischer Bruch. Namespaces können hier Klarheit schaffen, auch hinsichtlich etwaiger Versionsunterschiede, die sich für dieselbe Begrifflichkeit ergeben können (etwa "Umbruch/2017" oder "Aufbruch/2018").

Mehrdeutigkeiten gibt es auch im XML-Kontext. Hier hat beispielsweise das Wort "Element" unterschiedliche Bedeutungen, hinter denen sich diverse zulässige Attribute und Childnodes verbergen. In XSLT dient xsl:element als Element-Konstruktor. In XML Schema stellt xs:element eine Definition dar, die es erlaubt, XML-Elemente zu definieren, referenzieren und ggf. zu validieren.

Versionsbezogene Namespace-Deklarationen kommen nicht selten aus der objektorientierten Programmierung, speziell aus der XML-basierten Objektserialisierung. Beachten Sie hierzu meine Anmerkungen über "Datenaustausch" sowie "XML und JAXB".

Grundsätzlich ist ein Namespace eine Zeichenkette, die weltweit einmalig sein sollte. Diese weltweite Einmaligkeit läßt sich am einfachsten durch Webadressen herstellen, zumal damit die Chance besteht, in der Linkadresse Informationen über die Problemstellung, Versionsunterschiede etc. bereitzustellen. Für den XML-Namespace ist jedoch nicht entscheidend, ob hinter der Namespace-Zeichenkette auch eine reale Webadresse liegt.

Ein Beispiel für einen Default-Namespace ist:

<?xml version="1.0" encoding="UTF-8"?>
<Bruch 
   xmlns="www.diese-Webadresse-existiert-nicht.de/math-Bruch">
   <Zaehler>57</Zaehler>
   <Nenner>95</Nenner>
</Bruch>

Neben Default-Namespaces können auch Namespace-Prefixe definiert werden; einzelne Elemente / Attribute können dann leichter zugeordnet werden.

<?xml version="1.0" encoding="UTF-8"?>
<abc:Bruch xmlns:abc="http://www.math.de" 
      xmlns:s="http://www.Steinbruch.de" 
      xmlns:w="http://www.Wortbruch.de" 
      xmlns:k="http://www.Knochenbruch.de">
   <abc:Zaehler>57</abc:Zaehler>
   <abc:Nenner>95</abc:Nenner>
</abc:Bruch>

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>

Diesen Ansatz erhalten wir aus unserem bekannten Standard - XML Dokument durch folgendes XSL-Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:o="Ort" xmlns:m="Mensch">
  <xsl:output method="xml" indent="yes" />
  <xsl:template name="generateTree">
    <xsl:for-each select="//Mensch[Gehalt &amp;gt; 1000]">
      <element>
        <xsl:for-each select="../child::*[name()!='Mensch']">
          <xsl:attribute name="o:{local-name()}">
          <xsl:value-of select="." />
        </xsl:attribute>
        </xsl:for-each>
        <xsl:for-each select="./child::*[name()!='Kauf']">
          <xsl:attribute name="m:{local-name()}">
          <xsl:value-of select="." />
        </xsl:attribute>
        </xsl:for-each>
      </element>
    </xsl:for-each>
  </xsl:template>
  <xsl:template match="/">
    <ROOT>
      <xsl:call-template name="generateTree" />
    </ROOT>
  </xsl:template>
</xsl:stylesheet>

Umgekehrt läßt sich dieses Namespace-lastige XML Dokument wieder auswerten und dabei aus Namespaces wieder Elemente zaubern:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:o="Ort" xmlns:m="Mensch">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/">
 <ROOT>
  <xsl:for-each select="$vtmp/element">
   <xsl:variable name="vcurelement" select="." />
   <INFO>
    <xsl:for-each
     select="namespace::*[. != 'http://www.w3.org/XML/1998/namespace']">
      <xsl:variable name="vtmpns">
        <xsl:value-of select="." />
      </xsl:variable>
      <xsl:element name="{$vtmpns}">
       <xsl:for-each
        select="$vcurelement/attribute::*[namespace-uri() = $vtmpns]">
         <xsl:element name="{local-name()}">
          <xsl:value-of select="." />
         </xsl:element>
       </xsl:for-each>
      </xsl:element>
    </xsl:for-each>
   </INFO>
  </xsl:for-each>      
 </ROOT>
</xsl:template>
</xsl:stylesheet>

Das Ergebnis sieht dann wie folgt aus:

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

Als segensreich erweisen sich Namespaces bei der Programmierung, wenn Funktionaliäten unterschiedlicher Bereiche zusammenkommen. Stellen wir uns vor, in einem XML Input-Dokument stehen Informationen, die mittels xsl:for-each-group zunächst gruppiert werden müssen, um die Ergebnisse bildlich in einer svg-Datei (Skalierbare Vektorgrafik) darzustellen, die schließlich als fo:instream-foreign-object in ein PDF-Dokument eingebettet werden soll. Obendrein sollen die Datentypen der Input-Informationen mittels XML Schema gecastet werden. In einem solchen Ansatz kommen schnell mehrere Namespaces zusammen, und da ist ein klarer Überblick über die Zusammenhänge außerordentlich hilfreich:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fo="http://www.w3.org/1999/XSL/Format"
  xmlns:svg="http://www.w3.org/2000/svg">
</xsl:stylesheet>

qrpic/namespaces.jpg

wg / 14. Oktober 2017




Fragen? Anmerkungen? Tips?

Bitte nehmen Sie Kontakt zu mir auf (info10@wilfried-grupe.de).



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: info10@wilfried-grupe.de