Использование режима PATH

Как описано в разделе Создание XML с помощью предложения FOR XML, режим PATH является простым способом смешивания элементов и атрибутов. Режим PATH является также простым способом создания дополнительных вложенных объектов для отражения сложных свойств. Для построения таких XML-документов из набора строк можно использовать запросы FOR XML в режиме EXPLICIT, но режим 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-документом:

  • имя столбца начинается с символа @;
  • имя столбца не начинается с символа @;
  • имя столбца не начинается с символа @ и содержит косую черту (/);
  • несколько столбцов имеют одинаковый префикс;
  • один из столбцов имеет другое имя.

Имя столбца начинается с символа @

Если имя столбца начинается с символа @ и не содержит косую черту (/), создается атрибут элемента <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

Имя столбца не начинается с символа @

Если имя столбца начинается с символа @, не является одной из XPath-функций проверки узла и не содержит косую черту (/), по умолчанию создается элемент XML <row>, который представляет собой вложенный элемент элемента строки.

В результате следующего запроса указывается имя столбца. Дочерний элемент <result> добавляется к элементу <row>.

SELECT 2+2 as result
for xml PATH

Результат:

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

Следующий запрос указывает имя столбца, ManuWorkCenterInformation, для XML-данных, возвращенных запросом XQuery, указанным по отношению к столбцу Instructions типа xml. Элемент <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. Например, если столбец имеет имя «Имя1/Имя2/Имя3.../Имяn», каждое Имяi представляет имя элемента, вложенного в элемент текущей строки (для i=1) или расположенного под элементом Имяi-1. Если Имяn начинается с символа @, оно сопоставляется с атрибутом элемента Имяn-1.

Например, следующий запрос возвращает идентификатор работника и имя, представленное сложным элементом 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

Имена столбцов используются в качестве пути при построении XML-документа в режиме PATH. Имя столбца, содержащего значения идентификатора работника, начинается с символа @. Поэтому атрибут EmpID добавляется к элементу <row>. Имена всех других столбцов содержат символ косой черты (/), являющийся признаком иерархии. В итоговом XML-документе будет присутствовать дочерний элемент <EmpName> внутри элемента <row>, а элемент <EmpName> будет в свою очередь содержать дочерние элементы <First>, <Middle> и <Last>.

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

Отчество работника имеет значение NULL, которое по умолчанию сопоставляется с отсутствием элемента или атрибута. Если необходимо сформировать элементы для значений NULL, укажите директиву ELEMENTS с ключевым словом XSINIL, как показано в данном запросе.

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-документ. Поэтому указание директивы ELEMENTS в режиме PATH не имеет никакого смысла. Однако, как показано в предыдущем примере, директива 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. Например, в следующем запросе столбец, содержащий XML-данные, возвращенные в результате запроса на языке XQuery к столбцу Instructions, имеет имя «*».

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()

Строковое значение столбца с именем text() добавляется в качестве комментария XML.

node()

Для столбца с именем node() результат аналогичен результату, получаемому для столбца с символом-шаблоном (*) в качестве имени.

processing-instruction(name)

Строковое значение столбца с именем инструкции обработки добавляется в качестве значения инструкции для целевого имени инструкции обработки.

Имена столбцов с путем, указанным как 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 указывает для имени элемента строки пустую строку, формирования элемента строки не происходит. Вместо этого возвращаются значения, назначенные атрибуту ProductIDs элемента строки <ProductModelData> в родительской инструкции SELECT. Результат:

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

Столбцы, по умолчанию содержащие значение NULL

По умолчанию значение NULL в столбце сопоставляется с отсутствием атрибута, узла или элемента. Это поведение, установленное по умолчанию, может быть изменено с помощью запроса к элементно-ориентированному документу XML с использованием директивы ELEMENTS и указания ключевого слова 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>

Поддержка пространства имен

В этом выпуске поддержка пространства имен в режиме PATH осуществляется с помощью предложения WITH NAMESPACES. Например, в следующем запросе синтаксис WITH NAMESPACES применяется для объявления пространства имен («a:»), которое затем можно использовать в последующей инструкции SELECT:

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

Примеры

В этих примерах показано использование режима PATH при формировании XML-документа из запроса SELECT. Многие из этих запросов являются запросами к XML-документам с инструкциями по производству велосипедов, хранящимся в столбце Instructions таблицы ProductModel. Дополнительные сведения об инструкциях XML см. в разделе Представление типов xml-данных в базе данных AdventureWorks.

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>

Следующий результат совпадает с результатом запроса в режиме RAW с указанным параметром ELEMENTS. Запрос возвращает элементно-ориентированный 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, то для получения расположения указывается метод query() типа данных xml.

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, XML-данные, возвращенные методом query(), помещаются в тег <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. В результате метод query() типа xml не определяет префикс в прологе запроса. Результат:

<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 возвращает список столбцов ProductID, для чего использует значение data() в качестве имени столбца. Поскольку в режиме FOR XML PATH запрос указывает для имени элемента строки пустую строку, формирование элемента не происходит. Вместо этого атрибуту ProductID назначается список значений.
  • Вторая вложенная инструкция SELECT извлекает имена продуктов для модели продукта. Запрос формирует элементы <ProductName>, которые возвращаются в виде элементов <ProductNames>, поскольку в качестве имени столбца в запросе указано 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')

Г. Добавление пространств имен в итоговый 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

Атрибут @xml:lang, добавляемый к элементу <English>, определяется в предварительно заданном пространстве имен xml.

Результат:

<Translation>
  <English xml:lang="en">food</English>
  <German xml:lang="ger">Essen</German>
</Translation>

Следующий запрос похож на приведенный в примере В, отличаясь тем, что в нем пространства имен добавляются в результирующий XML-документ с помощью предложения WITH XMLNAMESPACES. Дополнительные сведения см. в разделе Добавление пространств имен с помощью предложения 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>

См. также

Справочник

Создание XML с помощью предложения FOR XML

Основные понятия

Добавление пространств имен с помощью предложения WITH XMLNAMESPACES

Другие ресурсы

SELECT (Transact-SQL)

Справка и поддержка

Получение помощи по SQL Server 2005