Добавление пространств имен в запросы с помощью WITH XMLNAMESPACES
Область применения: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure
Предложение WITH XMLNAMESPACES (Transact-SQL) поддерживает пространство имен URI следующим образом:
Разрешается сопоставление префикса пространства имен с адресом URI при создании XML с помощью предложения FOR XML .
Разрешается сопоставление пространства имен с адресом URI в статическом контексте пространств имен методов типа данных xml.
Использование WITH XMLNAMESPACES в ЗАПРОСАХ FOR XML
Использование предложения WITH XMLNAMESPACES позволяет включать пространства имен XML в запросы FOR XML. Например, рассмотрим следующий запрос FOR XML:
SELECT ProductID, Name, Color
FROM Production.Product
WHERE ProductID IN (316, 317)
FOR XML RAW;
Результат:
<row ProductID="316" Name="Blade" />
<row ProductID="317" Name="LL Crankarm" Color="Black" />
Чтобы добавить пространства имен в XML-документ, созданный с помощью запроса FOR XML, вначале с помощью предложения WITH NAMESPACES укажите префикс пространства имен для сопоставления с адресом URI. Затем используйте эти префиксы пространств имен для указания имен в запросе, как показано в следующем измененном запросе. Предложение 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 IN (316, 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 ('https://abc' as myNS ) INSERT INTO T VALUES('<myNS:root/>'); GO
Использование директивы 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 IN (316, 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 IN (316, 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. Так как 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.