使用 PATH 模式

使用 FOR XML 构造 XML 中所述,PATH 模式提供了一种较简单的方法来混合元素和属性。PATH 模式还是一种用于引入附加嵌套来表示复杂属性的较简单的方法。尽管您可以使用 FOR XML EXPLICIT 模式查询从行集构造这种 XML,但 PATH 模式为可能很麻烦的 EXPLICIT 模式查询提供了一种较简单的替代方法。通过 PATH 模式,以及用于编写嵌套 FOR XML 查询的功能和返回 xml 类型实例的 TYPE 指令,您可以编写简单的查询。

在 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 中:

  • 列名以 @ 符号开头
  • 列名不以 @ 符号开头
  • 列名不以 @ 符号开头并包含斜杠标记 (/)
  • 若干列共享同一个前缀
  • 有一列具有不同的名称

列名以 @ 符号开头

如果列名以 @ 符号开头并且不包含斜杠标记 (/),将创建包含相应列值的 <row> 元素的属性。例如,以下查询将返回包含两列(@PmId 和 Name)的行集。在生成的 XML 中,将向相应的 <row> 元素添加 PmId 属性并为其分配 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

列名不以 @ 符号开头

如果列名不以 @ 符号开头、不是某个 XPath 节点测试并且不包含斜杠标记 (/),则将创建一个 XML 元素,该元素是行元素(默认情况下为 <row>)的子元素。

以下查询指定了列名 result。因此,将向 <row> 元素添加 <result> 子元素。

SELECT 2+2 as result
for xml PATH

结果如下:

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

以下查询为针对 xml 类型的 Instructions 列指定的 XQuery 所返回的 XML 指定了列名 ManuWorkCenterInformation。因此,将添加 <ManuWorkCenterInformation> 元素来作为 <row> 元素的子元素。

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>

列名不以 @ 符号开头并包含斜杠标记 (/)

如果列名不以 @ 符号开头,但包含斜杠标记 (/),则该列名就指明了一个 XML 层次结构。例如,列名为“Name1/Name2/Name3.../Namen”,其中每个 Namei 表示嵌套在当前行元素 (i=1) 中的元素名称或名为 Namei-1 的元素下的元素名称。如果 Namen 以 @ 开头,则它将映射到 Namen-1 元素的属性。

例如,以下查询将返回雇员 ID 和表示为复杂元素 EmpName(包含名字、中间名和姓氏)的雇员名称。

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 时的路径。包含雇员 ID 值的列名以 @ 开头。因此,将向 <row> 元素添加 EmpID 属性。其他所有列的列名中均包含指明层次结构的斜杠标记 (/)。在生成的 XML 中,<row> 元素下将包含 <EmpName> 子元素,而 <EmpName> 子元素将包含 <First>、<Middle> 和 <Last> 子元素。

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

雇员的中间名为空,默认情况下,空值映射为“缺少相应的元素或属性”。如果希望针对 NULL 值生成元素,则可以指定带有 XSINIL 的 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 指令将不起作用。但是,如上一个示例所示,可以指定带有 XSINIL 的 ELEMENTS 指令来针对空值生成元素。

除了 ID 和名称以外,以下查询还将检索雇员地址。按照地址列的列名中包含的路径,将向 <row> 元素添加 <Address> 子元素,并添加地址详细信息来作为 <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() 的列,结果与列名为通配符 (*) 时相同。

处理指令名称

对于以处理指令的名称命名的列,该列中的字符串值将被添加为此处理指定目标名称的 PI 值。

以指定为 data() 的路径命名的列

如果被指定为列名的路径为 data(),则在生成的 XML 中,该值将被作为一个原子值来处理。如果序列化中的下一项也是一个原子值,则将向 XML 中添加一个空格字符。这在创建列表类型化元素值和属性值时很有用。以下查询将检索产品型号 ID、名称和该产品型号中的产品列表。

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 语句将检索产品 ID 列表。它指定 data() 作为产品 ID 列名。由于 PATH 模式为行元素名指定了空字符串,因此不会生成行元素。相反,将返回值以分配给父级 SELECT 的 <ProductModelData> 行元素的 ProductIDs 属性。结果如下:

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

默认情况下包含 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 语法声明一个随后可用于后续 SELECT 语句的命名空间 (a:) 的过程:

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

示例

以下这些示例演示了使用 PATH 模式从 SELECT 查询生成 XML 的过程。其中许多查询都是根据 ProductModel 表中 Instructions 列标明的自行车生产说明 XML 文档指定的。有关 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,在该 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,在该 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>

除了产品型号 ID 和名称以外,以下查询还将检索产品型号的生产说明位置。由于 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

下面是部分结果。因为此查询指定 Manulnstr 作为列名,所以 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

请注意,在 WITH XMLNAMESPACES 中也定义了 MI 前缀。因此,所指定的 xml 类型的 query() 方法没有定义查询 prolog 中的前缀。结果如下:

<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 模式生成值列表

对于每个产品型号,此查询将构造产品 ID 的值列表。对于每个产品 ID,此查询还会构造 <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')

请注意上述查询的以下方面:

  • 通过使用 data() 作为列名,第一个嵌套 SELECT 语句将返回一列 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 的字符串。如果添加 type 指令 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 帮助