Wenn man XML Instanzen aus unterschiedlichen Quellen mit XSLT verarbeiten will, wird man sich wohl oder übel mit dem Thema Namespaces XML Konstrukte Namespaces auseinander setzen müssen, um Konflikte in den Elementselektoren zu vermeiden.
Gerade bei hintereinandergeschalteten Transformationen kann es auch passieren, dass unerwartet ein Namespace in die Ausgabe generiert wird, den der folgende Prozesschritt nicht versteht, weil er dort nicht deklariert wurde.
Es gibt meherere Möglichkeiten einen Namespace im Stylesheet zu deklarieren. Gehen wir davon aus, dass in einem Transformationsschritt genau eine Quelle und max. eine Konfigurationsdatei verarbeitet wird, dann kann das Stylsheet-Element bspw. so aussehen:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tektur="https://namespace-eigener-xslt-funktionen" xmlns="http://namespace-in-der-xml-eingabe.com/" xpath-default-namespace="https://namespace-der-konfigdatei.com/" exclude-result-prefixes="#all">Plain Text
Der xsl Namespace ist natürlich der Namespace für die XSLT Answeisungen und muss deklariert werden.
Der xs Namespace ist notwendig, wenn man typisiert arbeiten will. Er erlaubt das Einbinden von Datentypen nach der XML Schema Spezifikation und somit die bessere Validierung des Stylesheets zur Compile-Zeit.
Die Deklaration eines eigenen geprefixten Namespaces erlaubt das Einbinden von eigenen XSLT Funktionen, wie z.B. auch das Einbinden der FunctX Bibliothek
Der Nicht-geprefixte Namespace ist der Default-Namespace und kann einen Namespace aus der Eingabe behandeln
Das Attribut xpath-default-namespace gibt einen weiteren Namespace an, der in XPath Funktionen verwendet werden kann. In diesem Feld würde ich den Namespace einer Konfigurations- oder separaten Datendatei angeben.
Mehr als einen Namespace in der Eingabe sollte man aus meiner Sicht bei der XML Verarbeitung mit XSLT vermeiden - wenn es geht. Ggf. empfiehlt es sich, die Eingabe vor der Verarbeitung zu normalisieren und Elemente ggf. umzubenennen. Ansonsten kann man auch eigene Namespace-Prefixes deklarieren, wie z.B.:
xmlns:ext="https://www.tekturcms.de/external-tools"Plain Text
und diesen in XPath Selektionen und Match-Regeln verwenden.
Namespaces in der Eingabe werden also meistens über die Kopfdeklaration in der Stylesheetdatei gehandelt. Welcher Namespace schliesslich in die Ausgabe geschrieben wird, hängt vom aktuell verarbeiteten Kontextknoten ab:
Elemente, die man erzeugt, erhalten automatisch den Default-Namespace (wenn man nicht explizit einen Namespace angibt).
Elemente, die man kopiert, transportieren den Namespace, den sie in der Eingabe hatten (wenn man dies nicht explizit verhindert).
Um diese beiden Default Einstellungen zu steuern (bzw. zu überschreiben) gibt es mehrere Möglichkeiten:
<xsl:element name="{local-name()}" namespace="{namespace-uri()}">Plain Text
Hier wird ein Element mit dem un-geprefixten Namespace des Kontextknotens deklariert. Wenn der Kontextknoten keinen anderen Namespace hat, so wird hierdurch sichergestellt, dass der Default-Namespace auch tatsächlich in die Ausgabe kommt.
<xsl:element name="meinelement" namespace="mein-namespace">Plain Text
Hier wird ein Element mit eigener Namespace Angabe in die Ausgabe geschrieben. Einfacher geschrieben:
<mein-element xmlns="mein-namespace">Plain Text
Es gibt auch ein Attribut am xsl:copy Element, das den Vorgang des Namespace-Kopierens steuern kann:
<xsl:template match="p"> <xsl:copy copy-namespaces="no"> <xsl:apply-templates/> </xsl:copy> </xsl:template>Plain Text
Hier wird der Namespace am p Element nicht in die Ausgabe geschrieben.
Ebenso kann eine Default-Kopierregel verwendet werden, die es verbietet einen Namespace weiterzuvererben:
<xsl:template match="@* | node()"> <xsl:copy inherit-namespaces="no"> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template>Plain Text