Sobald man keine eigene Entscheidung über das XML-Format treffen kann,
die angelieferten Daten tief verschachtelt sind und fast gar nicht den benötigten
relationalen Strukturen entsprechen, genügt die einfache Zuordnung nicht
mehr und man muss auf die Möglichkeit zurückgreifen, die genaue Zuordnung
mit Hilfe von XPath-Ausdrücken auszuführen. Das in der nächsten
Abfrage erzeugte XML-Dokument bietet einen solchen komplexen Aufbau. Innerhalb
der sich wiederholenden Product-Elemente gibt es ein Attribut für die Produktnummer,
ein Kind-Element für den Namen mit einem Textknoten sowie zwei weitere
Kinder, die selbst wieder Kinder für Preis- und Detailinformationen besitzen.
<Product-List>
<Product ProductNumber="BK-R19B-52">
<Name>Road-750 Black, 52</Name>
<Prices>
<Standard>343.6496</Standard>
<List>539.9900</List>
</Prices>
<Details>
<Size>52</Size>
<Color>Black</Color>
</Details>
</Product>
</Product-List>
Bei einer Zerlegung in XML ist es normalerweise so, dass die Blätter des XML-Baums zu Spalten werden sollen. Das nachfolgende Beispiel zeigt also, wie die Daten abgerufen werden. Dies geschieht mit Hilfe des PATH-Modus und den Spaltennamen, welche die Struktur der Verschachtelung angeben.
Die Zerlegung erfolgt dann zwar wiederum innerhalb der OPENXML-Anweisung, wobei hier allerdings zusätzlich noch nach den Datentypen, die für die einzelne erzeugte Spalte verwendet werden sollen, auch noch ein XPath-Ausdruck folgt, der relativ zum vorher ausgewählten Knoten weitere Knoten auswählt. Der Ausdruck ist dabei relativ zu den Knoten, die im XPath-Ausdruck in der OPENXML-Anweisung ausgewählt werden. Im aktuellen Beispiel sind dies wie zuvor die einzelnen Product-Elemente. Sie besitzen die beschriebenen Kind-Elemente, Attribute sowie die beiden besonderen Kind-Elemente Details und Prices, welche jeweils selbst wieder Kind-Element enthalten. Diese beiden Elemente erfordern einen XPath-Ausdruck, der über dieses Eltern-Element hinweg die jeweiligen Kinder aus-wählt. Bei einer noch tieferen Verschachtelung setzt sich dieses Verfahren fort.
-- XML-Variable erstellen
DECLARE @productXML xml, @idoc int
-- XML abrufen
SET @productXML = (
SELECT ProductNumber AS "@P-Nr",
Name AS "Name",
StandardCost AS "Prices/Standard",
ListPrice AS "Prices/List",
Size AS "Details/Size",
Color AS "Details/Color"
FROM Production.Product
ORDER BY ProductID DESC
FOR XML PATH('Product'), ROOT('Product-List'))
-- Standardzerlegung für alle Zeilen
EXEC sp_xml_preparedocument @idoc OUTPUT, @productXML
SELECT *
FROM OPENXML(@idoc, '/Product-List/Product',2)
WITH (ProductNumber nvarchar(25) '@P-Nr',
Name nvarchar(50) 'Name',
StandardCost money 'Prices/Standard',
ListPrice money 'Prices/List',
Size nvarchar(5) 'Details/Size',
Color nvarchar(15) 'Details/Color')

Das Prinzip ist verblüffend einfach, wenn man die XPath-Syntax verstanden hat. Es lassen sich sehr komplizierte und anspruchsvolle Zerlegungen denken, doch mit der XPath-Technik ist dies letztendlich im Vergleich zu anderen Datenbanken einfacher. Die vorheri-ge Abbildung fasst den Vorgang noch einmal zusammen. Deutlich ist zu erkennen, wie der so genannte XPath-Kontext Product-List/Product innerhalb von OPENXML eingerich-tet wird und weshalb die verschiedenen XPath-Ausdrücke in den einzelnen Spalten die unterschiedlichen Kinder und Kindeskinder sowie das Attribut auswählen. Durch die An-gabe 2, welche die elementzentrierte Zuordnung festlegt, hätte man übrigens das Kind Na-me auch überhaupt nicht nennen brauchen, wenn die zuzuordnende Spalte gleichfalls diesen Namen trägt.
Mit XPath ist es möglich, von jedem Knoten in einem Dokument jeden anderen Knoten zu erreichen. Dies muss sich nicht auf Elemente und Attribute begrenzen, wird allerdings für die meisten Zerlegungen durchaus der Fall sein. Dies bedeutet, man könnte aus jedem denkbaren XPath-Kontext die benötigten Zuordnungen angeben. Lediglich das Reihenele-ment wie Product sollte bereits in OPENXML ausgewählt sein. Als Beispiel für ein extra kompliziertes Vorgehen, das nur die Syntax zeigen will, wählt man in der nachfolgenden Zerlegung das Element Prices ebenfalls in OPENXML aus. Dies hat zur Folge, dass man die Eltern und sogar die Großeltern-Elemente aufrufen muss, um aus Prices wieder alle benö-tigten Blätter im XML-Baum auszuwählen.
Wie schon zuvor aufgefallen, kann man sich die Navigation durch ein XML-Dokument wie die Navigation durch eine Ordnerstruktur vorstellen. Dies erkennt man an dem Schräg-strich, der eine Ebene tiefer führt, sowie an dem einzelnen Punkt für die Eltern und an den zwei Punkten für die Großeltern-Ebene. Alternativ lassen sich auch die so genannten Ach-sen-Namen parent und ancestor angeben, wobei die beiden Doppelpunkte Achsen- und Knotennamen trennen. Das @-Zeichen steht für die Auswahl von Attributen.
SELECT *
FROM OPENXML(@idoc, '/Product-List/Product/Prices',2)
WITH (ProductNumber nvarchar(25) '../@P-Nr',
Name nvarchar(50) 'ancestor::Product/Name',
StandardCost money 'Standard',
ListPrice money 'List',
Size nvarchar(5) '../Details/Size',
Color nvarchar(15) 'parent::Product/Details/
Color')
Es entsteht wieder dieselbe Ausgabe wie zuvor, sodass sie im vorherigen Beispiel angege-ben ist und hier nicht noch einmal wiederholt wird.
comelio.com
