使用 PATH 模式

如<使用 FOR XML 建構 XML>主題中所述,PATH 提供比較簡單的方式來混合元素與屬性。PATH 模式也是導入其他巢狀以代表複雜屬性的較簡單方式。您可以使用 FOR XML EXPLICIT 模式查詢來建構從資料列集而來的這類 XML,但是 PATH 模式對於可能會比較繁雜的 EXPLICIT 模式查詢提供較簡單的替代方案。PATH 模式還可撰寫巢狀 FOR XML 查詢及 TYPE 指示詞,以傳回 xml 類型執行個體,這將可讓您撰寫較不複雜的查詢。

在 PATH 模式中,資料行名稱或資料行別名是被視為 XPath 運算式。這些運算式指出值如何對應至 XML。每個 XPath 運算式都是提供項目類型的相對 XPath,這些項目類型包括屬性、元素、純量值、將會產生與資料列元素相對的節點名稱與階層。

本主題描述資料列集中對應資料行的下列條件:

  • 沒有名稱的資料行
  • 有名稱的資料行
  • 以萬用字元 (*) 指定有名稱的資料行
  • 具有 XPath 節點測試名稱的資料行
  • data() 指定路徑的資料行名稱
  • 預設包含 NULL 值的資料行

沒有名稱的資料行

任何沒有名稱的資料行都將予以內嵌。例如,未指定資料行別名的計算資料行或巢狀純量查詢將會產生沒有名稱的資料行。如果資料行是 xml 類型,就會插入資料類型執行個體的內容。否則,就會以文字節點插入資料行內容。

SELECT 2+2
FOR XML PATH

產生此 XML。依預設,對於資料列集中的每個資料列,在產生的 XML 中會產生 <row> 元素。這與 RAW 模式相同。

<row>4</row>

下列查詢會傳回三個資料行的資料列集。沒有名稱的第三個資料行具有 XML 資料。PATH 模式會插入 xml 類型的執行個體。

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

以下是部份結果:

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location ...LocationID="10" ...></MI:Location>
  <MI:Location ...LocationID="20" ...></MI:Location>
   ...
</row>

有名稱的資料行

以下是具有名稱的資料列集資料行以區分大小寫的方式對應至產生的 XML 之特定條件:

  • 資料行名稱以 At 符號 (@) 開頭。
  • 資料行名稱不是以 At 符號 (@) 開頭。
  • 資料行名稱不是以 At 符號 (@) 開頭且包含斜線 (/)。
  • 數個資料行共用相同的前置詞
  • 一個資料行具有不同的名稱

資料行名稱以 At 符號 (@) 開頭。

如果資料行名稱是以 At 符號 (@) 開頭且包含斜線 (/),就會建立具有對應資料行值的 <row> 元素之屬性。例如,下列查詢會傳回二個資料行 (@PmId、Name) 的資料列集。在產生的 XML 中,PmId 屬性會加入對應的 <row> 元素中,並會將 ProductModelID 值指派給該元素。

SELECT ProductModelID as "@PmId",
       Name
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

以下是結果:

<row PmId="7">
  <Name>HL Touring Frame</Name>
</row>

請注意在相同的層級中,屬性必須在任何其他節點類型的前面,例如元素節點與文字節點。下列查詢將傳回錯誤:

SELECT Name,
       ProductModelID as "@PmId"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

資料行名稱不是以 At 符號 (@) 開頭

如果資料行名稱不是以 At 符號 (@) 開頭、不是其中一個 XPath 節點測試,而且不包含斜線 (/),預設會建立資料列元素 <row> 的子元素之 XML 元素。

下列查詢指定資料行名稱、結果。因此,<result> 子元素會加入 <row> 元素。

SELECT 2+2 as result
for xml PATH

以下是結果:

<row>
  <result>4</result>
</row>

下列查詢針對 xml 類型的 Instructions 資料行指定的 XQuery 所傳回的 XML,指定資料行名稱、ManuWorkCenterInformation。因此,將以 <row> 元素的子元素加入 <ManuWorkCenterInformation> 元素。

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
                /MI:root/MI:Location 
              ') as ManuWorkCenterInformation
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

以下是結果:

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <ManuWorkCenterInformation>
    <MI:Location ...LocationID="10" ...></MI:Location>
    <MI:Location ...LocationID="20" ...></MI:Location>
     ...
  </ManuWorkCenterInformation>
</row>

資料行名稱不是以 At 符號 (@) 開頭且包含斜線 (/)

如果資料行名稱不是以 At 符號 (@) 開頭,但包含斜線 (/),則資料行名稱會指出 XML 階層。例如,如果資料行名稱是 "Name1/Name2/Name3.../Namen ",則每個 Namei 代表一個元素名稱,是巢狀在目前資料列元素 (for i=1) 中,或是在具有名稱 Namei-1 的元素之下。如果 Namen 以 '@' 開頭,它會對應至 Namen-1 元素的屬性。

例如,下列查詢將會傳回員工識別碼與姓名,它們是以複雜的元素 EmpName 所代表,該元素包含姓名的 First、Middle 以及 Last。

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

資料行名稱是在 PATH 模式中建構 XML 時做為路徑之用。包含員工識別碼值的資料行名稱是以 '@' 開頭,因此會將 EmpID 屬性加入 <row> 元素。在指出階層的資料行名稱中所有其他的資料行都包含斜線 ('/')。產生的 XML 在 <row> 元素下將有 <EmpName> 子元素,而且 <EmpName> 子元素將有 <First>、<Middle> 以及 <Last> 子元素。

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
</row>

員工中間名字為 Null,Null 值預設與缺少的元素或屬性相對應。如果您要為 NULL 值產生元素,您可以指定具有 XSINL 的 ELEMENTS 指示詞,如下列查詢所示。

SELECT EmployeeID "@EmpID", 
       FirstName  "EmpName/First", 
       MiddleName "EmpName/Middle", 
       LastName   "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

以下是結果:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

根據預設,PATH 模式會產生元素中心的 XML。因此,在 PATH 模式查詢中指定 ELEMENTS 指示詞將不會有效果。然而,如上述範例所示,ELEMENTS 指示詞加上 XSINIL 就可以為 Null 值產生元素。

除了識別碼與名稱之外,下列查詢還會擷取員工地址。根據地址資料行的資料行名稱,會將 <Address> 子元素加入 <row> 元素,而地址詳細資料則會以 <Address> 元素的子元素加入。

SELECT EmployeeID   "@EmpID", 
       FirstName    "EmpName/First", 
       MiddleName   "EmpName/Middle", 
       LastName     "EmpName/Last",
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City         "Address/City"
FROM   HumanResources.Employee E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

以下是結果:

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Last>Achong</Last>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
</row>

數個資料行共用相同的路徑前置詞

如果數個後續的資料行共用相同的路徑前置詞,則會在相同的名稱下將它們群組在一起。即使不同的命名空間前置詞是與相同的命名空間繫結,但仍使用了它們,就會將路徑視為不同。在上述查詢中,FirstName、MiddleName 以及 LastName 資料行是共用相同的 EmpName 前置詞。因此,會將它們以 <EmpName> 子元素加入。當您在上述範例中建立 <Address> 元素時也是如此。

一個資料行具有不同的名稱

如果具有不同名稱的資料行出現在其間,它將會拆散群組,如下列修改的查詢所示。查詢會在 FirstName 與 MiddleName 資料行之間加入地址資料行,以拆散上述查詢所指定的 FirstName、MiddleName 以及 LastName 的群組。

SELECT EmployeeID "@EmpID", 
       FirstName "EmpName/First", 
       AddressLine1 "Address/AddrLine1",
       AddressLine2 "Address/AddrLIne2",
       City "Address/City",
       MiddleName "EmpName/Middle", 
       LastName "EmpName/Last"
FROM   HumanResources.EmployeeAddress E, Person.Contact C, Person.Address A
WHERE  E.EmployeeID = C.ContactID
AND    E.AddressID = A.AddressID
AND    E.EmployeeID=1
FOR XML PATH

因此,查詢會建立兩個 <EmpName> 元素。第一個 <EmpName> 元素具有 <FirstName> 子元素,而第二個 <EmpName> 元素則具有 <MiddleName> 及 <LastName> 子元素。

以下是結果:

<row EmpID="1">
  <EmpName>
    <First>Gustavo</First>
  </EmpName>
  <Address>
    <AddrLine1>7726 Driftwood Drive</AddrLine1>
    <City>Monroe</City>
  </Address>
  <EmpName>
    <Last>Achong</Last>
  </EmpName>
</row>

以萬用字元指定有名稱的資料行

如果以萬用字元 (*) 指定資料行名稱,則插入該資料行內容的方式,就像沒有指定資料行名稱一樣。如果資料行是非 xml 類型的資料行,則會以文字節點插入資料行內容,如下列範例所示:

SELECT EmployeeID "@EmpID", 
       FirstName "*", 
       MiddleName "*", 
       LastName "*"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH

以下是結果:

<row EmpID="1">GustavoAchong</row>

如果資料行是 xml 類型,就會插入對應的 XML 樹狀結構。例如,下列查詢為資料行名稱指定 "*",該資料行名稱包含針對 Instructions 資料行的 XQuery 所傳回的 XML。

SELECT 
       ProductModelID,
       Name,
       Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
                /MI:root/MI:Location 
              ') as "*"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH 
go

以下是結果。會插入 XQuery 所傳回的 XML,但不會有包裝元素。

<row>
  <ProductModelID>7</ProductModelID>
  <Name>HL Touring Frame</Name>
  <MI:Location LocationID="10">...</MI:Location>
  <MI:Location LocationID="20">...</MI:Location>
...
</row>

具有 XPath 節點測試名稱的資料行

如果資料行名稱是其中一個 XPath 節點測試,將會對應內容,如下表所示。

如果資料行名稱是 XPath 節點測試,會將內容對應至對應的節點。如果資料行的 SQL 類型是 xml,就會傳回錯誤。

資料行名稱 行為

text()

對於有 text() 名稱的資料行,將會以文字節點加入該資料行中的字串值。

comment()

對於有 comment() 名稱的資料行,將會以 XML 註解加入該資料行中的字串值。

node()

對於有 node() 名稱的資料行,其結果與資料行名稱為萬用字元 (*) 的結果相同。

processing-instruction(name)

對於有處理指示名稱的資料行,將會以處理指示目標名稱的 PI 值加入該資料行中的字串值。

以 data() 指定路徑的資料行名稱

如果以資料行名稱指定的路徑是 "data()",則在產生的 XML 中會將其值視為不可部份完成值。如果序列化的下一個項目也是不可部份完成值,就會在 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"
FROM  Production.ProductModel
WHERE ProductModelID= 7 
FOR XML PATH('ProductModelData')

巢狀 SELECT 會擷取產品識別碼的清單。它會將 "data()" 指定為產品識別碼的資料行名稱。因為 PATH 模式會為資料列元素名稱指定空白字串,所以並不會產生資料列元素。反而是,會以指派給父項 SELECT 中 <ProductModelData> 資料列項目的 ProductID 屬性來傳回值。以下是結果:

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

預設包含 NULL 值的資料行

依預設,資料行中的 Null 值會與缺少的屬性、節點或元素相對應。此預設行為是可以覆寫的,方法為使用 ELEMENTS 指示詞來要求元素中心的 XML,並指定 XSINIL 來要求為 NULL 值加入元素,如下列查詢所示:

SELECT EmployeeID as "@EmpID", 
       FirstName  as "EmpName/First", 
       MiddleName as "EmpName/Middle", 
       LastName   as "EmpName/Last"
FROM   HumanResources.Employee E, Person.Contact C
WHERE  E.EmployeeID = C.ContactID
AND    E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL

下列範例會顯示結果。請注意如果沒有指定 XSINIL,將不會有 <Middle> 元素。

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" EmpID="1">
  <EmpName>
    <First>Gustavo</First>
    <Middle xsi:nil="true" />
    <Last>Achong</Last>
  </EmpName>
</row>

命名空間支援

在此版本中,是使用 WITH NAMESPACES 來提供 PATH 模式的命名空間支援。例如,下列查詢示範 WITH NAMESPACES 語法以宣告命名空間 ("a:"),它可用於後續的 SELECT 陳述式中:

WITH XMLNAMESPACES('a' as a)
SELECT 1 as 'a:b'
FOR XML PATH

範例

以下範例說明使用 PATH 模式從 SELECT 查詢產生 XML。這些查詢中有許多是針對腳踏車製造指示的 XML 文件所指定,這些文件是儲存在 ProductModel 資料表的 Instructions 資料行中。如需有關 XML 指示的詳細資訊,請參閱<在 AdventureWorks 資料庫中的 xml 資料類型表示法>。

A. 指定簡單 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>

B. 指定類似 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>

C. 使用 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>
    &lt;ProductName&gt;HL Touring Frame - Yellow, 60&lt;/ProductName&gt;
    &lt;ProductName&gt;HL Touring Frame - Yellow, 46&lt;/ProductName&gt;</ProductNames>
    ...
</ProductModelData>
<ProductModelData PId="9" 
                  ProductModelName="LL Road Frame" 
                  ProductIDs="722 723 724 ...">
  <ProductNames>
     &lt;ProductName&gt;LL Road Frame - Black, 58&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 60&lt;/ProductName&gt;
     &lt;ProductName&gt;LL Road Frame - Black, 62&lt;/ProductName&gt;
     ...
  </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')

D. 在產生的 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>

請參閱

參考

使用 FOR XML 建構 XML

概念

使用 WITH XMLNAMESPACES 來加入命名空間

其他資源

SELECT (Transact-SQL)

說明及資訊

取得 SQL Server 2005 協助