Namespaces für komplexere XML-Dokumente definieren
https://bildung.social/@oerinformatik/111986750551090101
https://oer-informatik.de/xml-namespaces
tl/dr; (ca. 5 min Lesezeit): XML-Namensräume bieten eine Möglichkeit, dass Elemente gleichen Namens für unterschiedliche Inhalte stehen können. Das kann vor allem bei allgemeinen Bezeichnern wie
<name/>
relevant sein, die dann mit Präfix notiert werden:<person:name />
,<firma:name />
. (Zuletzt geändert am 10.03.2024)
Dieser Artikel ist Bestandteil einer Serie zu den XML-Grundlagen:
Teil 1: XML-Grundlagen und Wohlgeformtheit: Hierarchische Daten mit XML speichern mit zugehörigen Übungsaufgaben
Teil 2: XML-Dokumente gegen eine Document-Type-Definition validieren mit zugehörigen Übungsaufgaben
Teil 4: Die Struktur von XML-Dokumente gegen ein XSD-Schema validieren
Teil 5: Datentypen-Definitionen eines XML-Schema zur Validierung nutzen
Nach Durchlesen des Artikels kann ich…
… Namespaces für XML-Elemente und Attribute an eine URI binden und deklarieren,
… Namespaces an XML-Elemente und Attribute über Präfixe notieren,
… default Namespaces festlegen,
… zuordnen, zu welchen Namespaces Elemente und Attribute gehören,
… beurteilen, welche Attribute nach Berücksichtigung der Namespaces einzigartig (und damit wohlgeformt) sind.
Wenn bei diesen Erläuterungen zu XML-Namespaces Fragen offen bleiben oder tiefer in das Thema eingestiegen werden will, so ist der Standard zu Namespaces in XML neben dem XML-Standard 1.0 die erste Adresse für weitere Recherchen.
Die Ausgangsproblematik mit doppelten Elementnamen
Komplexere XML-Dokumente können aus unterschiedlichen Dateien kombiniert werden. Hierbei kann es bei großen XML-Dokumenten vorkommen, dass in unterschiedlichen Bereichen Elemente gleichen Namens existieren. Das wird problematisch, wenn diese einen unterschiedlichen Aufbau haben müssen.
Diese Problematik will ich am Beispiel eines Telefon-Einzelverbindungnachweises (Anhang einer Telefonrechnung) zeigen. Darin befinden sich Daten aus unterschiedlichen Quellen:
die Unternehmenskontaktdaten aus der Support-Datenbank,
die Anschlussnummer aus der Kundedatenbank
und die Verbindungsdaten aus dem Abrechnungssystem.
Alle verarbeiten Telefonnummern in unterschiedlichen Kontexten. Es kann also gefordert sein, dass ein <telefonummer />
-Element in einem Dokument für die Einzelabrechnung von Verbindungsdaten in verschiedenen Bereichen unterschiedlich aufgebaut sein muss:
Im Absender-Abschnitt soll die Telefonnummer die Kontaktdaten des Supports übergeben, also eine einfache Nummer als Elementeinhalt.
Im Abschnitt mit den Kundendaten dient die Telefonnummer dazu, den Kunden und dessen Anschluss zu identifizieren. Dazu muss z.B. identifiziert werden, was die Hauptnummer des Anschlusses ist (im Beispiel über ein Attribut).
Im Einzelverbindungs-Bereich dient sie dazu, den korrekten Tarif auszuwählen. Hierfür wird internationale und nationale Vorwahl gesondert ausgewiesen.
Die Szenarien sind etwas konstruiert, aber ich hoffe, der Punkt wird klar. Für ein solches Beispiel könnten wir keine DTD ausfertigen, da unterschiedliche Formate für das <telefonnummer/>
-Element erwartet würden:
<einzelverbindungsnachweis>
<briefkopf>
<firma>Deutsche Telefon GmbH</firma>
<support>
<name>Herr Firstlevel</name>
<telefonnummer>0800 12345-67</telefonnummer>
</support>
</briefkopf>
<kunde>
<anschluss>
<telefonnummer art="main">030 123456-78</telefonnummer>
<telefonnummer art="">030 123456-78</telefonnummer>
<telefonnummer art="fax">030 123456-78</telefonnummer>
</anschluss>
</kunde>
<verbindungen>
<verbindung>
<telefonnummer>
<international>+49</international>
<national>030</national>
<anschluss>12345678</anschluss>
</telefonnummer>
<zeitVon>03.02.2024 11:24:05</zeitVon>
<zeitBis>03.02.2024 11:26:20</zeitBis>
<dauer>02:15</dauer>
<tarif>flat</tarif>
</verbindung>
</verbindungen>
</einzelverbindungsnachweis>
Ein Weg, das Problem zu lösen, wäre die Attribute unterschiedlich zu benennen. Das kann aber an anderer Stelle zu Inkompatibilitäten führen.
Namespace Deklarationen
Damit für jeden Bereich gesonderte Regeln für Elemente angewendet werden können, wurden in XML Namespaces eingeführt: Den Elementnamen wird ein mit Doppelpunkt getrenntes Präfix vorangestellt (z.B. <s:telefonnummer />
), der alte Elementname wird dann local part genannt (hier: telefonnummer
).
Diese Präfixe werden einmal über ein Namespace-Attribut xmlns
definiert, in dem ihnen ein eindeutiger Identifier (URI) zugewiesen wird, z.B. xmlns:s="http://oer-informatik.de/ns/support"
. Häufig wird als URI eine Internetadresse (URL) verwendet, aber auch andere eindeutige Bezeichner (z.B. ISBN oder andere URNs) wären denkbar. Die URI muss für den Namensraum eindeutig sein und im Einflussbereich (Domäne) derjenigen liegen, die das XML-Format bestimmt. Weitere Funktionen übernimmt die URI nicht. Falls eine URL gewählt wurde, muss dort also keinerlei Informationen hinterlegt sein.
Für die drei Bereiche aus dem Beispiel könnten wir also drei Namespaces definieren, die alle über ein anders strukturiertes <telefonnummer />
-Element verfügen.
<einzelverbindungsnachweis
xmlns:s="http://oer-informatik.de/ns/support"
xmlns:k="http://oer-informatik.de/ns/kunde"
xmlns:v="http://oer-informatik.de/ns/verbindung">
<!-- ... -->
<s:telefonnummer>0800 12345-67</s:telefonnummer>
<!-- ... -->
<k:telefonnummer art="main">030 123456-78</k:telefonnummer>
<!-- ... -->
<v:telefonnummer>
<v:international>+49</v:international>
<v:national>030</v:national>
<v:anschluss>12345678</v:anschluss>
</v:telefonnummer>
<!-- ... -->
</einzelverbindungsnachweis >
Die Namensräume gelten für alle Unterelemente der Elemente, in dem sie definiert wurden (und für dieses Element bereits auch). Wie im obigen Beispiel können alle Namensräume im Rootelement deklariert werden (die komplette Datei findet sich hier).
Namespaces müssen nicht im Root-Element angegeben werden, sondern können auch dezentral in dem ersten Element gelten, für das der Namensraum gelten soll (komplettes Beispiel hier):
<s:einzelverbindungsnachweis xmlns:s="http://oer-informatik.de/ns/support">
<s:briefkopf>
<!-- ... -->
</s:briefkopf>
<k:kunde xmlns:k="http://oer-informatik.de/ns/kunde">
<k:anschluss> <!-- ... --> </k:anschluss>
</k:kunde>
<v:verbindungen xmlns:v="http://oer-informatik.de/ns/verbindung">
<v:verbindung> <!-- ... --> </v:verbindung>
</v:verbindungen>
</s:einzelverbindungsnachweis>
Namespaces in der Document Type Definition einbinden
Durch die Integration der Namespaces ist es möglich, für jedes der Elemente mit identischem local part eine eigene Elemente-Deklaration in der DTD festzulegen (komplette DTD jeweils in den verlinkten XML-Dateien):
<!-- ... -->
<!ELEMENT s:telefonnummer (#PCDATA)>
<!-- ... -->
<!ELEMENT k:telefonnummer (#PCDATA)>
<!ATTLIST k:telefonnummer art CDATA #IMPLIED>
<!-- ... -->
<!ELEMENT v:telefonnummer (v:international, v:national, v:anschluss)>
<!ELEMENT v:international (#PCDATA)>
<!ELEMENT v:national (#PCDATA)>
<!ELEMENT v:anschluss (#PCDATA)>
Default-Namensräume
Es kann ein default Namensraum deklariert werden, bei dem kein Präfix angegeben wird (xmlns="http://beispielde"
). Diesem default Namensraum gehören dann alle enthaltenen (Unter-)Elemente an, die nicht per Präfix einem anderen Namensraum zugeordnet wurden. Die zugehörigen Attribute gehören ihm jedoch nicht an, was v.a. eine Rolle spielt, wenn es darum geht, ob Attribute eindeutige Namen haben. (Komplettes Beispiel hier)
<einzelverbindungsnachweis xmlns="http://oer-informatik.de/ns/support">
<briefkopf>
<!-- ... -->
</briefkopf>
<k:kunde xmlns:k="http://oer-informatik.de/ns/kunde">
<!-- ... -->
</k:kunde>
<v:verbindungen xmlns:v="http://oer-informatik.de/ns/verbindung">
<!-- ... -->
</v:verbindungen>
</einzelverbindungsnachweis>
Wer tiefer einsteigen will: eine kleine Kopfnuss
Das kann zu etwas verzwickten Konstellationen führen, insbesondere dann, wenn Namensräume auf die gleiche URI zeigen. Wir betrachten mal folgendes Beispiel, in dem ein Bereich ohne Namensraum, ein Bereich mit default Namensraum und zwei Bereichen mit zwei zusätzlichen Namensräumen enthalten sind. Die folgende XML-Datei ist nicht valide, wir werden versuchen herauszufinden, warum.
<keinNamensraum>
<defautlNamensraum xmlns="http://oer-informatik.de/ns/default">
<nsZeigtAufDefault xmlns:ns="http://oer-informatik.de/ns/default"
xmlns:nn="http://oer-informatik.de/ns/default">
<a data="1"></a>
<ns:a data="1" ns:data="1"></ns:a>
<nn:a data="1" ns:data="1" nn:data="1"></nn:a>
</nsZeigtAufDefault>
<nsZeigtWoandersHin xmlns:ns="http://oer-informatik.de/ns/woanders"
xmlns:nn="http://oer-informatik.de/ns/default">
<a data="1"></a>
<ns:a data="1" ns:data="1"></ns:a>
<nn:a data="1" ns:data="1" nn:data="1"></nn:a>
</nsZeigtWoandersHin>
<a data="1"></a>
</defautlNamensraum>
<a data="1"></a>
</keinNamensraum>
Zunächst sieht alles wohlgeformt aus: auch alle Attribute haben über die Namensräume eindeutige Namen. Wenn wir mal farblich sichtbar machen, zu welchen Namensräumen die einzelnen Elemente und Attribute gehören, sieht es erstmal gut aus:

a data
-Attribut hat eine andere FarbeAlle Attribute gehören zu unterschiedlichen Namensräumen, das scheint also wohlgeformt zu sein.
Wenn wir jetzt aber betrachten, dass jeder Namensraum nur ein Alias ist auf eine URI und wir markieren, welche Attribute und Elemente zu welcher URI gehören, wird das Problem sichtbar:

ns:data
und nn:data
sind im nsZeigtAufDefault
-Element gleich eingefärbtDer Knackpunkt ist jeweils die Zeile
Diese verhält sich im <nsZeigtWoandersHin />
-Element anders als im <nsZeigtAufDefault />
-Element. Da alle data
-Attribute ohne Präfix keinem Namensraum angehören (auch nicht dem Default-Namensraum), sind diese schonmal einzigartig. Aber die Namensräume nn
und ns
sind ja nur Platzhalter für die jeweiligen URI - und die zeigen im <nsZeigtAufDefault />
-Element auf die gleiche URI. Somit sind in diesem Fall die Attribute ns:data
und nn:data
beide Elemente mit identischem local name im gleichen Namensraum - was in einem wohlgeformten XML-Dokument nicht sein darf.
Links und weitere Informationen
Infos von w3schools zu XML
Hinweis zur Nachnutzung als Open Educational Resource (OER)
Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: “Namespaces für komplexere XML-Dokumente definieren” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/xml-namespaces veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/datenformate/xml. Stand: 10.03.2024.
[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]