- 1 Intro
- 2 Anwendungsgebiete
- 2.1 XSLT - die Programmiersprache im XML Bereich
- 2.2 Aktuelle und vergangene Anwendungen
- 2.3 Professionelle XML Verarbeitung
- 2.4 Technische Dokumentation
- 3 Wichtige Konzepte
- 3.1 Push vs. Pull Stylesheets
- 3.2 Eindeutigkeit der Regelbasis
- 3.3 Namespaces
- 3.4 Schemata
- 3.5 Standards
- 3.5.1 DITA
- 3.5.2 DITA Inhaltsmodell
- 3.5.1 DITA
- 4 Ausgewählte Themen
- 4.1 Transformationen mit XSLT
- 4.1.1 Vortransformationen
- 4.1.2 Komplexe XML-2-XML Transformationen
- 4.1.2.8 Vererbung
- 4.1.2.8 Vererbung
- 4.1.3 XSLT Streaming
- 4.1.3.1 XSLT Akkumulator
- 4.1.3.2 XSLT Iterator
- 4.1.4 Reguläre Ausdrücke
- 4.1.5 Modus vs. Tunnel Lösung
- 4.1.6 Identifikation mit
generate-id()
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4.1 Funktionen und Module
- 4.1.6.4 XPath-Achsenbereich selektieren
- 4.1.7 Webservice Calls mit doc() und unparsed-text()
- 4.1.8 Stylesheet-Parameter auf der Kommandozeile
- 4.1.9 Leerzeichenbehandlung
- 4.1.10 Mit
translate
Zeichen ersetzen
- 4.1.10.1 Spass mit dem Sequenzvergleich
- 4.1.11 Character Mappings in der Ausgabe
- 4.1.12 JSON mit XSLT 1.0 und Python lxml
- 4.1.1 Vortransformationen
- 4.2 Abfragen mit XQuery
- 4.2.5 XQuery als Programmiersprache
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.5.3.2 SQL Views in MarkLogic
- 4.2.5.3
if..then..else
Ausdrücke
- 4.2.6 Hilfreiche XQuery Schippsel
- 4.2.5 XQuery als Programmiersprache
- 4.3 XML Datenbanken
- 4.3.1 Connector zu Marklogic in Oxygen
- 4.3.2 Bi-Temporale Dokumente
- 4.3.2.1 Anlegen des Testszenarios auf der ML Konsole
- 4.3.2.2 Ausführen einiger Beispiel-Queries
- 4.3.3 Webapps mit MarkLogic
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.3.5 Wikipedia Scrapper Applikation
- 4.3.4 Dokument-Rechte in MarkLogic
- 4.3.5 MarkLogic Tools
- 4.3.5.1 EXPath Konsole
- 4.3.5.2 mlcp - MarkLogic Content Pump
- 4.3.5.3 Deployment-Tools
- 4.4 XSL-FO mit XSLT1.x
- 4.5 Testing
- 4.5.1 Validierung mit Schematron
- 4.5.2 Erste Schritte mit XSpec
- 4.5.1 Validierung mit Schematron
- 4.6 Performanz-Optimierung
- 4.1 Transformationen mit XSLT
- 5 Zusätzliches Know-How
- 5.1 XML Editoren
- 5.2 Quellcode-Versionskontrolle
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.2.2 GIT Kommandos
- 5.2.1 Kurze Geschichte zur Versionskontrolle Test
- 5.1 XML Editoren
- 6 Glossary
- 7 Tektur CCMS
3.3 Namespaces
Wenn man XML Instanzen aus unterschiedlichen Quellen mit XSLT verarbeiten will, wird man sich wohl
oder übel mit dem Thema 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">
-
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"
und diesen in XPath Selektionen und Match-Regeln verwenden.
Befinden sich in den Eingabedaten Namespaces, die man in den XSLT Stylesheets nicht handelt - der Namespace kann auch nur
an einem ganz bestimmten Element hängen - so kann es bei der Transformation - ohne Fehlermeldung - zu unerwarteten Ergebnissen kommen.
Deshalb sollte man die Daten im Vorfeld bzgl. Namespaces sehr genau analysieren.
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()}">
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">
Hier wird ein Element mit eigener Namespace Angabe in die Ausgabe geschrieben. Einfacher geschrieben:
<mein-element xmlns="mein-namespace">
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>
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>
3.3.1 Freie Wildbahn
In der freien Wildbahn bin ich erst kürzlich über folgendes Problem gestolpert:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xpath-default-namespace="https://tekturcms.de/schema/x12-xml/1.0" exclude-result-prefixes="#all" version="3.0"> <xsl:template match="my-element"> <neuer-name> <xsl:apply-templates> </neuer-name> </xsl:template> [...]
So deklariert würde das neue Element
my-element
mit einem leeren Namespace in die Ausgabe gesetzt, so
<neuer-name xmlns=""/>
. Das kann ein nachfolgender Transformationsschritt nicht lesen.
Aus diesem Grund setze ich neue Elemente immer mit dem Element-Konstruktor in die Ausgabe.
Beispiel:
<xsl:template match="my-element"> <xsl:element name="neuer-name" namespace="{namespace-uri()}"> <xsl:apply-templates> </xsl:element> </xsl:template>
3.3.2 Namespaces in XQuery
Während XSLT dazu dienen sollte, XML Daten in andere (XML-) Formate zu transformieren, dient XQuery
z.B. dazu auf einer NoSQL Datenbank Daten aus unterschiedlichen Quellen
zu selektieren, zu harmonisieren und an verarbeitende Prozesse weiterzugeben.
Deshalb ist es für mich nicht so erstaunlich, dass das Namespace Konzept in XQuery irgendwie besser
funktioniert.
Damit man überhaupt Daten auf einem mit Namespaces versehenen XML Dokument selektieren
kann, müssen alle Namspaces am Anfang des XQuery Ausdrucks angegeben werden, das sieht so aus:
xquery version "1.0-ml"; import module namespace tektur = "http://www.teturcms.de/xquery/common" at "common.xqy"; import module namespace mem = "http://xqdev.com/in-mem-update" at '/MarkLogic/appservices/utils/in-mem-update.xqy'; declare namespace local = "https://tekturcms.de/code/alex-sandbox/1.0"; declare namespace weiredns = "https://weired-ns-in-input-data.com/weired/ns"; declare namespace xs = "http://www.w3.org/2001/XMLSchema";
Hier werden zuerst Funktionen aus anderen Modulen eingebunden. Diejenigen in einer eigenen Datei
common.xqy
, sowie aus der Bibliothek
mem
in der MarkLogic
Umgebung. Danach wird ein Namespace
local
für eigene Funktionen innerhalb der Quelldatei deklariert, sowie der Namespace
weiredns
, der in den Eingabedaten
vorhanden ist. Der Namespace
xs
ist analog zum XSLT Beispiel gesetzt.