WITH XMLNAMESPACES (Transact-SQL) 通过以下方式提供命名空间 URI 支持:
当 使用 FOR XML 查询构造 XML 时,它将命名空间前缀设置为 URI 映射。
它使命名空间与 URI 的映射可以用于 xml 数据类型方法的静态命名空间上下文。
在 FOR XML 查询中使用 WITH XMLNAMESPACES
WITH XMLNAMESPACES 允许在 FOR XML 查询中包含 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" />
若要将命名空间添加到 FOR XML 查询构造的 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=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 前缀的命名空间声明。
使用 WITH XMLNAMESPACES 子句时,不能使用 FOR XML 指令、XMLSCHEMA 和 XMLDATA。
CREATE TABLE T (x xml) go WITH XMLNAMESPACES ('http://abc' as myNS ) INSERT INTO T VALUES('<myNS:root/>')
使用 XSINIL 指令
如果使用 ELEMENTS XSINIL 指令,则不能在 WITH XMLNAMESPACES 子句中定义 xsi 前缀。 而是在使用 ELEMENTS XSINIL 时自动添加它。 以下查询使用 ELEMENTS XSINIL 生成以元素为中心的 XML,其中 null 值映射到将 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
使用预定义命名空间
使用预定义命名空间时,除使用 ELEMENTS XSINIL 时的 xml 命名空间和 xsi 命名空间外,必须使用 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')
结果如下: SQLXML 用户熟悉此 XML 模板。 有关详细信息,请参阅 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 子句中指定的名称是指未使用 WITH XMLNAMESPACES 显式定义的 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 属性使用预定义的 xml 命名空间。 由于 XML 版本 1.0 不需要 xml 命名空间绑定的显式声明,因此结果将不包括命名空间绑定的显式声明。
结果如下:
<Translation>
<English xml:lang="en">food</English>
<German xml:lang="ger">Essen</German>
</Translation>
将 WITH XMLNAMESPACES 与 xml 数据类型方法配合使用
在 SELECT 查询中指定的 xml 数据类型方法 ,或者在 UPDATE 中指定为 modify() 方法时,所有方法必须在其 prolog 中重复命名空间声明。 这很耗时。 例如,以下查询检索目录说明中包含规格的产品型号 ID。 也就是说,该 <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() 方法在其 prolog 中声明相同的命名空间。 例如:
declare namespace pd="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelDescription";
或者,可以首先声明 WITH XMLNAMESPACES,并在查询中使用命名空间前缀。 在这种情况下, query() 和 exist() 方法不必在其 prolog 中包含命名空间声明。
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 prolog 中的显式声明将替代命名空间前缀和 WITH 子句中定义的默认元素命名空间。
另请参阅
xml 数据类型方法
Xquery 语言参考 (SQL Server)
WITH XMLNAMESPACES (Transact-SQL)
FOR XML (SQL Server)