Поделиться через


Добавление пространств имен в запросы с использованием оператора WITH XMLNAMESPACES

Предложение WITH XMLNAMESPACES (Transact-SQL) поддерживает пространство имен URI следующим образом:

Использование WITH XMLNAMESPACES в запросах FOR XML

Использование инструкции WITH XMLNAMESPACES позволяет включать пространства имен XML в запросы FOR XML. Например, рассмотрим следующий запрос FOR XML:

SELECT ProductID, Name, Color  
FROM   Production.Product  
WHERE  ProductID=316 or ProductID=317  
FOR XML RAW  

Результат:

<row ProductID="316" Name="Blade" />  
<row ProductID="317" Name="LL Crankarm" Color="Black" />  
  

Чтобы добавить пространства имен в XML-документ, созданный запросом FOR XML, сначала укажите префиксы пространств имен для их сопоставления с URI, используя предложение WITH NAMESPACES. Затем используйте эти префиксы пространств имен для указания имен в запросе, как показано в следующем измененном запросе. Обратите внимание, что предложение WITH XMLNAMESPACES указывает префикс пространства имен (ns1) на сопоставление URI (uri). Затем префикс ns1 используется для указания создаваемого элемента и имен атрибутов в запросе FOR XML.

WITH XMLNAMESPACES ('uri' as ns1)  
SELECT ProductID as 'ns1:ProductID',  
       Name      as 'ns1:Name',   
       Color     as 'ns1:Color'  
FROM Production.Product  
WHERE ProductID=316 or ProductID=317  
FOR XML RAW ('ns1:Prod'), ELEMENTS  
  

Результирующий XML-документ содержит префиксы пространства имен:

<ns1:Prod xmlns:ns1="uri">  
  <ns1:ProductID>316</ns1:ProductID>  
  <ns1:Name>Blade</ns1:Name>  
</ns1:Prod>  
<ns1:Prod xmlns:ns1="uri">  
  <ns1:ProductID>317</ns1:ProductID>  
  <ns1:Name>LL Crankarm</ns1:Name>  
  <ns1:Color>Black</ns1:Color>  
</ns1:Prod>  
  

Следующее относится к предложению WITH XMLNAMESPACES:

  • Оно может быть использовано в запросах FOR XML только в режимах RAW, AUTO и PATH. Режим EXPLICIT не поддерживается.

  • Оно влияет только на префиксы пространств имен в запросах FOR XML и методах типа данных xml , но не на синтаксический анализатор XML. Например, следующий запрос возвращает ошибку, так как в XML-документе нет объявления пространства имени для префикса myNS.

  • Директивы FOR XML, XMLSCHEMA и XMLDATA нельзя использовать при использовании предложения WITH XMLNAMESPACES.

    CREATE TABLE T (x xml)  
    go  
    WITH XMLNAMESPACES ('http://abc' as myNS )  
    INSERT INTO T VALUES('<myNS:root/>')  
    

Использование директивы XSINIL

Невозможно определить префикс xsi в предложении WITH XMLNAMESPACES, если используется директива ELEMENTS XSINIL. Вместо этого он добавляется автоматически при использовании ЭЛЕМЕНТОВ XSINIL. В следующем запросе используется директива ELEMENTS XSINIL, формирующая ориентированный на элементы XML-документ, в котором пустые значения сопоставляются с элементами, для которых атрибут xsi:nil имеет значение True.

WITH XMLNAMESPACES ('uri' as ns1)  
SELECT ProductID as 'ns1:ProductID',  
       Name      as 'ns1:Name',   
       Color     as 'ns1:Color'  
FROM Production.Product  
WHERE ProductID=316   
FOR XML RAW, ELEMENTS XSINIL  

Результат:

<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="uri">  
  <ns1:ProductID>316</ns1:ProductID>  
  <ns1:Name>Blade</ns1:Name>  
  <ns1:Color xsi:nil="true" />  
</row>  

Указание пространств имен по умолчанию

Вместо объявления префикса пространства имени можно объявить пространство имени по умолчанию с помощью ключевого слова "DEFAULT". В запросе FOR XML таким образом происходит привязка пространства имен по умолчанию к XML-узлам результирующего XML-документа. В представленном ниже примере с помощью предложения WITH XMLNAMESPACES задается два префикса пространства имен, которые определяются вместе с пространством имен по умолчанию.

WITH XMLNAMESPACES ('uri1' as ns1,   
                    'uri2' as ns2,  
                    DEFAULT 'uri2')  
SELECT ProductID,   
      Name,  
      Color  
FROM Production.Product   
WHERE ProductID=316 or ProductID=317  
FOR XML RAW ('ns1:Product'), ROOT('ns2:root'), ELEMENTS  

В результате выполнения запроса FOR XML формируется ориентированный на элементы XML-документ. Обратите внимание, что запрос использует префиксы пространства имен в узлах именования. В операторе SELECT идентификаторы ProductID, Name и Color не содержат имя с каким-либо префиксом. Поэтому соответствующие элементы в результирующем XML-документе принадлежат к пространству имен по умолчанию.

<ns2:root xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">  
  <ns1:Product>  
    <ProductID>316</ProductID>  
    <Name>Blade</Name>  
  </ns1:Product>  
  <ns1:Product>  
    <ProductID>317</ProductID>  
    <Name>LL Crankarm</Name>  
    <Color>Black</Color>  
  </ns1:Product>  
</ns2:root>  

Приведенный ниже запрос повторяет предыдущий за исключением указания режима FOR XML AUTO.

WITH XMLNAMESPACES ('uri1' as ns1,  'uri2' as ns2,DEFAULT 'uri2')  
SELECT ProductID,   
      Name,  
      Color  
FROM Production.Product as "ns1:Product"  
WHERE ProductID=316 or ProductID=317  
FOR XML AUTO, ROOT('ns2:root'), ELEMENTS  

Использование предопределенных пространств имен

При использовании предопределённых пространств имён, за исключением пространств имён xml и xsi при использовании ELEMENTS XSINIL, необходимо явно указывать привязку пространств имён с помощью оператора WITH XMLNAMESPACES. В следующем запросе явно задается префикс пространства имен для связывания URI предопределенного пространства имен (urn:schemas-microsoft-com:xml-sql).

WITH XMLNAMESPACES ('urn:schemas-microsoft-com:xml-sql' as sql)  
SELECT 'SELECT * FROM Customers FOR XML AUTO, ROOT("a")' AS "sql:query"  
FOR XML PATH('sql:root')  

Вот результат. Данный XML-шаблон известен пользователям SQLXML. Дополнительные сведения см. в статье Основные понятия о программировании для SQLXML 4.0.

<sql:root xmlns:sql="urn:schemas-microsoft-com:xml-sql">  
  <sql:query>SELECT * FROM Customers FOR XML AUTO, ROOT("a")</sql:query>  
</sql:root>  

Только XML-префикс пространства имен может быть использован без явного задания в предложении WITH XMLNAMESPACES, как показано в следующем примере запроса в режиме PATH. Также при объявлении префикса его необходимо привязать к пространству имен http://www.w3.org/XML/1998/namespace. Имена, указанные в предложении SELECT, ссылаются на префикс пространства имен XML, который явно не определен с помощью WITH XMLNAMESPACES.

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

Атрибуты @xml:lang используют предопределенное пространство имен XML. Так как версия 1.0 XML не обязывает явное объявление привязки пространства имен, результат не будет включать явное объявление привязки пространства имен.

Результат:

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

Использование WITH XMLNAMESPACES с методами типа данных XML

Методы типа данных XML, указанные в запросе SELECT или в UPDATE, когда это метод modify(), все должны повторять объявление пространства имен в своем прологе. Это может занять некоторое время. Например, в результате выполнения следующего запроса получаются идентификаторы моделей, в описание каталогов которых включены спецификации. То есть <Specifications> элемент существует.

SELECT ProductModelID, CatalogDescription.query('  
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";  
    <Product   
        ProductModelID= "{ sql:column("ProductModelID") }"   
        />  
') AS Result  
FROM Production.ProductModel  
WHERE CatalogDescription.exist('  
    declare namespace  pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";  
     /pd:ProductDescription[(pd:Specifications)]'  
    ) = 1  

В предыдущем запросе методы query() и exist() объявляют одно пространство имен в своем прологе. Рассмотрим пример.

declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";  

В качестве альтернативы, сначала можно объявить предложение WITH XMLNAMESPACES и затем использовать указанные в нем префиксы пространства имен в запросе. В этом случае методы query() и exist() не должны включать объявления пространства имен в пролог.

WITH XMLNAMESPACES ('https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription' as pd)  
SELECT ProductModelID, CatalogDescription.query('  
    <Product   
        ProductModelID= "{ sql:column("ProductModelID") }"   
        />  
') AS Result  
FROM Production.ProductModel  
WHERE CatalogDescription.exist('  
     /pd:ProductDescription[(pd:Specifications)]'  
    ) = 1  
Go  

Обратите внимание, что явное объявление в прологе XQuery переопределяет префикс пространства имен и пространство имен элемента по умолчанию, определенное в предложении WITH.

См. также

Методы для типа данных XML
Справочник по языку XQuery (SQL Server)
WITH XMLNAMESPACES (Transact-SQL)
FOR XML (SQL Server)