範例:使用 PATH 模式
以下範例說明使用 PATH 模式從 SELECT 查詢產生 XML。這些查詢中有許多是針對自行車製造指示的 XML 文件所指定,這些文件是儲存在 ProductModel 資料表的 Instructions 資料行中。如需有關 XML 指示的詳細資訊,請參閱<在 AdventureWorks 資料庫中的 xml 資料類型表示法>。
指定簡單 PATH 模式查詢
此查詢指定 FOR XML PATH 模式。
SELECT
ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH
go
以下結果是元素中心的 XML,在產生的資料列集中每個資料行值都是包裝在元素中。因為 SELECT 子句並不會為資料行名稱指定任何別名,所以產生的子元素名稱與 SELECT 子句中對應的資料行名稱相同。資料列集中的每個資料列都會加入 <row> 標記。
<row>
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
</row>
<row>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
</row>
下列結果與指定 ELEMENTS 選項之 RAW 模式查詢的結果相同。它會為結果集中的每個資料列傳回元素中心的 XML 加上預設 <row> 元素。
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML RAW, ELEMENTS
您可以選擇性地指定資料列元素名稱以覆寫預設的 <row>。例如,下列查詢會為資料列集中的每個資料列傳回 <ProductModel> 元素。
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModel')
Go
產生的 XML 將會有指定的資料列元素名稱。
<ProductModel>
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
</ProductModel>
<ProductModel>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
</ProductModel>
如果您指定零長度的字串,就不會產生包裝的元素。
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('')
Go
以下是結果:
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
指定類似 XPath 的資料行名稱
在下列查詢中,指定的 ProductModelID 資料行名稱是以 '@' 開頭,而且不包含斜線 ('/')。因此,會在產生的 XML 中建立含有對應資料行值之 <row> 元素的屬性。
SELECT ProductModelID as "@id",
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData')
go
以下是結果:
< ProductModelData id="122">
<Name>All-Purpose Bike Stand</Name>
</ ProductModelData >
< ProductModelData id="119">
<Name>Bike Wash</Name>
</ ProductModelData >
您可以在 FOR XML 中指定 root 選項,以加入單一最上層元素。
SELECT ProductModelID as "@id",
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData'), root ('Root')
go
若要產生階層,您可以加入類似 PATH 的語法。例如,將 Name 資料行的名稱變更為 "SomeChild/ModelName",您就可以取得具有階層的 XML,如下列結果所示:
<Root>
<ProductModelData id="122">
<SomeChild>
<ModelName>All-Purpose Bike Stand</ModelName>
</SomeChild>
</ProductModelData>
<ProductModelData id="119">
<SomeChild>
<ModelName>Bike Wash</ModelName>
</SomeChild>
</ProductModelData>
</Root>
除了產品型號識別碼與名稱之外,下列查詢還會擷取該產品型號的製造指示位置。由於 Instructions 資料行是 xml 類型,所以可以指定 xml 資料類型的 query() 方法來擷取位置。
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
以下是部份結果。因為查詢指定 ManuInstr 做為資料行名稱,query() 方法所傳回的 XML 會包裝在 <ManuInstr> 標記中,如下列所示:
<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>
在上述 FOR XML 查詢中,您可能會想要包含 <Root> 與 <ProductModelData> 元素的命名空間。完成此動作的方式是先使用 WITH XMLNAMESPACES 與 FOR XML 查詢中的前置詞,以定義命名空間繫結的前置詞。如需詳細資訊,請參閱<使用 WITH XMLNAMESPACES 來加入命名空間>。
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
請注意 MI 前置詞在 WITH XMLNAMESPACES 中也有定義。因此,指定 xml 類型的 query() 方法並不會定義查詢初構中的前置詞。結果如下:
<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" >
<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>
使用 PATH 模式產生值清單
對於每個產品型號,此查詢會建構產品識別碼的值清單。對於每個產品識別碼,此查詢也會建構 <ProductName> 的巢狀元素,如下列 XML 片段所示:
<ProductModelData ProductModelID="7" ProductModelName="..."
ProductIDs="product id list in the product model" >
<ProductName>...</ProductName>
<ProductName>...</ProductName>
...
</ProductModelData>
這是會產生您所需 XML 的查詢:
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 ('')) as "ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData')
請注意,下列項目是從上一個查詢而來:
第一個巢狀 SELECT 使用 data() 做為資料行名稱,以傳回 ProductID 的清單。因為查詢在 FOR XML PATH 中將空字串指定為資料列元素名稱,所以不會產生元素。值清單會改指派給 ProductID 屬性。
第二個巢狀 SELECT 會擷取產品型號中的產品名稱。它會產生包裝在 <ProductNames> 元素中的 <ProductName> 元素,因為查詢會將 ProductNames 指定為資料行名稱。
以下是部份結果:
<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>
建構產品名稱的子查詢會以實體化字串傳回結果,然後加入 XML。如果您加入類型指示詞 FOR XML PATH (''), type,子查詢會以 xml 類型傳回結果,而且不會發生實體化。
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')
在產生的 XML 中加入命名空間
如<使用 WITH XMLNAMESPACES 新增命名空間>主題中所述,您可以使用 WITH XMLNAMESPACES 在 PATH 模式查詢中包含命名空間。例如,SELECT 子句中指定的名稱包括命名空間前置詞。下列 PATH 模式查詢會建構包含命名空間的 XML。
SELECT 'en' as "English/@xml:lang",
'food' as "English",
'ger' as "German/@xml:lang",
'Essen' as "German"
FOR XML PATH ('Translation')
go
加入 <English> 元素的 @xml:lang 屬性是定義在預先定義的 xml 命名空間。
結果如下:
<Translation>
<English xml:lang="en">food</English>
<German xml:lang="ger">Essen</German>
</Translation>
下列查詢與範例 C 相似,除了它使用 WITH XMLNAMESPACES 在 XML 結果中加入命名空間之外。如需詳細資訊,請參閱<使用 WITH XMLNAMESPACES 來加入命名空間>。
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')
以下是結果:
<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>