Freigeben über


Beispiele: Verwenden des PATH-Modus

Die folgenden Beispiele veranschaulichen die Verwendung des PATH-Modus beim Generieren von XML aus einer SELECT-Abfrage. Viele dieser Abfragen werden anhand der XML-Dokumente zur Fahrradherstellung angegeben, die in der Spalte "Anweisungen" der Tabelle "ProductModel" gespeichert sind.

Angeben einer einfachen PATH-Modus-Abfrage

Diese Abfrage gibt einen FOR XML PATH-Modus an.

USE AdventureWorks2012;  
GO  
SELECT   
       ProductModelID,  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 OR ProductModelID=119  
FOR XML PATH;  
GO  

Das folgende Ergebnis ist elementorientiertes XML, bei dem jeder Spaltenwert im resultierenden Rowset in ein Element eingeschlossen wird. Da die SELECT Klausel keine Aliase für die Spaltennamen angibt, entsprechen die generierten untergeordneten Elementnamen den entsprechenden Spaltennamen in der SELECT Klausel. Für jede Zeile im Rowset wird ein <row> Tag hinzugefügt.

<row>

<ProductModelID>122</ProductModelID>

<Name>All-Purpose Bike Stand</Name>

</row>

<row>

<ProductModelID>119</ProductModelID>

<Name>Bike Wash</Name>

</row>

Das folgende Ergebnis entspricht der RAW Modusabfrage mit der ELEMENTS angegebenen Option. Es gibt elementorientiertes XML mit einem Standardelement <row> für jede Zeile im Resultset zurück.

USE AdventureWorks2012;  
GO  
SELECT ProductModelID,  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 OR ProductModelID=119  
FOR XML RAW, ELEMENTS;  

Optional können Sie den Zeilenelementnamen angeben, um den Standardnamen <row>zu überschreiben. Die folgende Abfrage gibt z. B. das <ProductModel> Element für jede Zeile im Rowset zurück.

USE AdventureWorks2012;  
GO  
SELECT ProductModelID,  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 or ProductModelID=119  
FOR XML PATH ('ProductModel');  
GO  

Der resultierende XML-Code hat einen angegebenen Zeilenelementnamen.

<ProductModel>

<ProductModelID>122</ProductModelID>

<Name>All-Purpose Bike Stand</Name>

</ProductModel>

<ProductModel>

<ProductModelID>119</ProductModelID>

<Name>Bike Wash</Name>

</ProductModel>

Wenn Sie eine Zeichenfolge mit null Länge angeben, wird das Umbruchelement nicht erstellt.

USE AdventureWorks2012;  
GO  
SELECT ProductModelID,  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 OR ProductModelID=119  
FOR XML PATH ('');  
GO  

Dies ist das Ergebnis:

<ProductModelID>122</ProductModelID>

<Name>All-Purpose Bike Stand</Name>

<ProductModelID>119</ProductModelID>

<Name>Bike Wash</Name>

Angeben von XPath-ähnlichen Spaltennamen

In der folgenden Abfrage beginnt der ProductModelID angegebene Spaltenname mit '@' und enthält keine Schrägstriche ('/'). Daher wird ein Attribut des <row> Elements mit dem entsprechenden Spaltenwert im resultierenden XML erstellt.

USE AdventureWorks2012;  
GO  
SELECT ProductModelID AS "@id",  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 OR ProductModelID=119  
FOR XML PATH ('ProductModelData');  
GO  

Dies ist das Ergebnis:

< ProductModelData id="122">

<Name>All-Purpose Bike Stand</Name>

</ ProductModelData >

< ProductModelData id="119">

<Name>Bike Wash</Name>

</ ProductModelData >

Sie können ein einzelnes Element auf oberster Ebene hinzufügen, indem Sie die root Option in FOR XMLangeben.

SELECT ProductModelID AS "@id",  
       Name  
FROM Production.ProductModel  
WHERE ProductModelID=122 or ProductModelID=119  
FOR XML PATH ('ProductModelData'), root ('Root');  
GO  

Um eine Hierarchie zu generieren, können Sie PATH-ähnliche Syntax einschließen. Ändern Sie beispielsweise den Spaltennamen für die Name Spalte in "SomeChild/ModelName", und Sie erhalten XML mit Hierarchie, wie in diesem Ergebnis gezeigt:

<Root>

<ProductModelData id="122">

<SomeChild>

<ModelName>All-Purpose Bike Stand</ModelName>

</SomeChild>

</ProductModelData>

<ProductModelData id="119">

<SomeChild>

<ModelName>Bike Wash</ModelName>

</SomeChild>

</ProductModelData>

</Root>

Neben der Produktmodell-ID und dem Namen ruft die folgende Abfrage die Fertigungsanweisungsspeicherorte für das Produktmodell ab. Da die Spalte "Anweisungen" vom xml Typ ist, wird die query() Methode des xml Datentyps angegeben, um den Speicherort abzurufen.

SELECT ProductModelID AS "@id",  
       Name,  
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";  
                /MI:root/MI:Location   
              ') AS ManuInstr  
FROM Production.ProductModel  
WHERE ProductModelID = 7  
FOR XML PATH ('ProductModelData'), root ('Root');  
GO  

Dies ist das Teilergebnis. Da die Abfrage ManuInstr als Spaltennamen angibt, wird der von der query() Methode zurückgegebene XML-Code in ein <ManuInstr> Tag eingeschlossen, wie in der folgenden Abbildung gezeigt:

<Root>

<ProductModelData id="7">

<Name>HL Touring Frame</Name>

<ManuInstr>

<MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"

<MI:step>...</MI:step>...

</MI:Location>

...

</ManuInstr>

</ProductModelData>

</Root>

In der vorherigen FOR XML-Abfrage möchten Sie möglicherweise Namespaces für die Elemente <Root> und <ProductModelData> einschließen. Dazu können Sie zuerst das Präfix für die Namespacebindung definieren, indem Sie WITH XMLNAMESPACES verwenden und Präfixe in der FOR XML-Abfrage verwenden. Weitere Informationen finden Sie unter Hinzufügen von Namespaces zu Abfragen mit WITH XMLNAMESPACES.

USE AdventureWorks2012;  
GO  
WITH XMLNAMESPACES (  
   'uri1' AS ns1,    
   'uri2' AS ns2,  
   'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' as MI)  
SELECT ProductModelID AS "ns1:ProductModelID",  
       Name           AS "ns1:Name",  
       Instructions.query('  
                /MI:root/MI:Location   
              ')   
FROM Production.ProductModel  
WHERE ProductModelID=7  
FOR XML PATH ('ns2:ProductInfo'), root('ns1:root');  
GO  

Beachten Sie, dass das MI-Präfix auch in der WITH XMLNAMESPACES definiert ist. Daher definiert die Methode query() des angegebenen Typs xml das Präfix im Abfrageprolog nicht. Dies ist das Ergebnis:

<ns1:root xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">

<ns2:ProductInfo>

<ns1:ProductModelID>7</ns1:ProductModelID>

<ns1:Name>HL Touring Frame</ns1:Name>

<MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"

LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10" xmlns="">

<MI:step>

Insert <MI:material>aluminum sheet MS-2341</MI:material> into the <MI:tool>T-85A framing tool</MI:tool>.

</MI:step>

...

</MI:Location>

...

</ns2:ProductInfo>

</ns1:root>

Generieren einer Wertliste mithilfe des PATH-Modus

Für jedes Produktmodell erstellt diese Abfrage eine Wertliste mit Produkt-IDs. Für jede Produkt-ID erstellt <ProductName> die Abfrage auch geschachtelte Elemente, wie in diesem XML-Fragment dargestellt:

<ProductModelData ProductModelID="7" ProductModelName="..."

ProductIDs="product id list in the product model" >

<ProductName>...</ProductName>

<ProductName>...</ProductName>

...

</ProductModelData>

Dies ist die Abfrage, die den gewünschten XML-Code erzeugt:

USE AdventureWorks2012;  
GO  
SELECT ProductModelID     AS "@ProductModelID",  
       Name               S "@ProductModelName",  
      (SELECT ProductID AS "data()"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
       FOR XML PATH ('')) S "@ProductIDs",  
       (SELECT Name AS "ProductName"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
        FOR XML PATH ('')) as "ProductNames"  
FROM   Production.ProductModel  
WHERE  ProductModelID= 7 or ProductModelID=9  
FOR XML PATH('ProductModelData');  

Beachten Sie hinsichtlich der vorherigen Abfrage Folgendes:

  • Die erste geschachtelte SELECT gibt eine Liste von ProductIDs zurück, wobei data() als Spaltenname verwendet wird. Da die Abfrage eine leere Zeichenfolge als Zeilenelementnamen angibt FOR XML PATH, wird kein Element generiert. Stattdessen wird die Wertliste dem ProductID Attribut zugewiesen.

  • Das zweite geschachtelte Objekt SELECT ruft Produktnamen für Produkte im Produktmodell ab. Es generiert <ProductName> Elemente, die in das <ProductNames> Element eingeschlossen werden, weil die Abfrage ProductNames als Spaltenname angibt.

Dies ist das Teilergebnis:

<ProductModelData PId="7"

ProductModelName="HL Touring Frame"

ProductIDs="885 887 ...">

<ProductNames>

<ProductName>HL Touring Frame - Yellow, 60</ProductName>

<ProductName>HL Touring Frame - Yellow, 46</ProductName></ProductNames>

...

</ProductModelData>

<ProductModelData PId="9"

ProductModelName="LL Road Frame"

ProductIDs="722 723 724 ...">

<ProductNames>

<ProductName>LL Road Frame - Black, 58</ProductName>

<ProductName>LL Road Frame - Black, 60</ProductName>

<ProductName>LL Road Frame - Black, 62</ProductName>

...

</ProductNames>

</ProductModelData>

Die Unterabfrage, die die Produktnamen erstellt, gibt das Ergebnis als Zeichenfolge zurück, die entitisiert und dann dem XML-Code hinzugefügt wird. Wenn Sie die Typdirektive hinzufügen, FOR XML PATH (''), typegibt die Unterabfrage das Ergebnis als xml Typ zurück, und es tritt keine Entitisierung auf.

USE AdventureWorks2012;  
GO  
SELECT ProductModelID AS "@ProductModelID",  
      Name AS "@ProductModelName",  
      (SELECT ProductID AS "data()"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
       FOR XML PATH ('')  
       ) AS "@ProductIDs",  
       (  
       SELECT Name AS "ProductName"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
       FOR XML PATH (''), type  
       ) AS "ProductNames"  
  
FROM Production.ProductModel  
WHERE ProductModelID= 7 OR ProductModelID=9  
FOR XML PATH('ProductModelData');  

Hinzufügen von Namespaces im resultierenden XML

Wie im Hinzufügen von Namespaces mit WITH XMLNAMESPACES beschrieben, können Sie WITH XMLNAMESPACES verwenden, um Namespaces in die PATH-Modusabfragen einzuschließen. In der SELECT-Klausel angegebene Namen enthalten beispielsweise Namespacepräfixe. Die folgende PATH Modusabfrage erstellt XML mit Namespaces.

SELECT 'en'    as "English/@xml:lang",  
       'food'  as "English",  
       'ger'   as "German/@xml:lang",  
       'Essen' as "German"  
FOR XML PATH ('Translation')  
GO  

Das @xml:lang Attribut, das dem <English> Element hinzugefügt wird, wird im vordefinierten XML-Namespace definiert.

Dies ist das Ergebnis:

<Translation>

<English xml:lang="en">food</English>

<German xml:lang="ger">Essen</German>

</Translation>

Die folgende Abfrage ähnelt dem Beispiel C, außer dass sie WITH XMLNAMESPACES verwendet, um Namespaces in das XML-Ergebnis einzuschließen. Weitere Informationen finden Sie unter Hinzufügen von Namespaces zu Abfragen mit WITH XMLNAMESPACES.

USE AdventureWorks2012;  
GO  
WITH XMLNAMESPACES ('uri1' AS ns1,  DEFAULT 'uri2')  
SELECT ProductModelID AS "@ns1:ProductModelID",  
      Name AS "@ns1:ProductModelName",  
      (SELECT ProductID AS "data()"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
       FOR XML PATH ('')  
       ) AS "@ns1:ProductIDs",  
       (  
       SELECT ProductID AS "@ns1:ProductID",   
              Name AS "@ns1:ProductName"  
       FROM   Production.Product  
       WHERE  Production.Product.ProductModelID =   
              Production.ProductModel.ProductModelID  
       FOR XML PATH , type   
       ) AS "ns1:ProductNames"  
FROM Production.ProductModel  
WHERE ProductModelID= 7 OR ProductModelID=9  
FOR XML PATH('ProductModelData'), root('root');  

Dies ist das Ergebnis:

<root xmlns="uri2" xmlns:ns1="uri1">

<ProductModelData ns1:ProductModelID="7" ns1:ProductModelName="HL Touring Frame" ns1:ProductIDs="885 887 888 889 890 891 892 893">

<ns1:ProductNames>

<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="885" ns1:ProductName="HL Touring Frame - Yellow, 60" />

<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="887" ns1:ProductName="HL Touring Frame - Yellow, 46" />

...

</ns1:ProductNames>

</ProductModelData>

<ProductModelData ns1:ProductModelID="9" ns1:ProductModelName="LL Road Frame" ns1:ProductIDs="722 723 724 725 726 727 728 729 730 736 737 738">

<ns1:ProductNames>

<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="722" ns1:ProductName="LL Road Frame - Black, 58" />

...

</ns1:ProductNames>

</ProductModelData>

</root>

Siehe auch

Verwenden des PATH-Modus mit FOR XML