Partilhar via


Adicionar namespaces a consultas usando WITH XMLNAMESPACES

Aplica-se a:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceBase de dados SQL no Microsoft Fabric

WITH XMLNAMESPACES (Transact-SQL) fornece suporte a URI de namespace da seguinte maneira:

Usar WITH XMLNAMESPACES em consultas FOR XML

WITH XMLNAMESPACES permite incluir namespaces XML em consultas FOR XML. Por exemplo, considere a seguinte consulta FOR XML:

SELECT ProductID, Name, Color
FROM   Production.Product
WHERE  ProductID IN (316, 317)
FOR XML RAW;

Este é o resultado:

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

Para adicionar namespaces ao XML construído pela consulta FOR XML, primeiro especifique o prefixo do namespace para mapeamentos de URI usando a cláusula WITH NAMESPACES. Em seguida, use os prefixos de namespace para especificar os nomes na consulta, conforme mostrado na consulta modificada a seguir. A cláusula WITH XMLNAMESPACES especifica o prefixo do namespace (ns1) para o mapeamento de URI (uri). O prefixo ns1 é usado para especificar os nomes de elementos e atributos a serem construídos pela consulta 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;

O resultado XML inclui os prefixos de namespace:

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

O seguinte se aplica à cláusula WITH XMLNAMESPACES:

  • Ele é suportado apenas nos modos RAW, AUTO e PATH das consultas FOR XML. O modo EXPLICIT não é suportado.

  • Ele afeta apenas os prefixos de namespace das consultas FOR XML e os métodos do tipo de dados XML e, mas não o analisador XML. Por exemplo, a consulta a seguir retorna um erro, porque o documento XML não tem nenhuma declaração de namespace para o prefixo myNS.

  • As diretivas FOR XML, XMLSCHEMA e XMLDATA não podem ser usadas quando uma cláusula WITH XMLNAMESPACES está sendo usada.

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

Utilize a diretiva XSINIL

Não é possível definir o prefixo xsi na cláusula WITH XMLNAMESPACES se estiver usando a diretiva ELEMENTS XSINIL. Em vez disso, ele é adicionado automaticamente quando você usa o ELEMENTS XSINIL. A consulta a seguir usa ELEMENTS XSINIL que gera XML centrado em elementos onde valores nulos são mapeados para elementos que têm o atributo xsi:nil definido como 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;

Este é o resultado:

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

Especificar namespaces padrão

Em vez de declarar um prefixo de namespace, você pode declarar um namespace padrão usando uma palavra-chave DEFAULT. Na consulta FOR XML, ele vinculará o namespace padrão aos nós XML no XML resultante. No exemplo a seguir, o WITH XMLNAMESPACES define dois prefixos de namespace que são definidos junto com um namespace padrão.

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;

A consulta FOR XML gera XML centrado em elementos. A consulta usa ambos os prefixos de namespace na nomeação de nós. Na cláusula SELECT, ProductID, Name e Color não especificam um nome com qualquer prefixo. Portanto, os elementos correspondentes no XML resultante pertencem ao namespace padrão.

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

A consulta a seguir é semelhante à anterior, exceto que é especificado o modo 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;

Usando namespaces predefinidos

Quando você usa namespaces predefinidos, exceto o namespace xml e o namespace xsi quando ELEMENTS XSINIL é usado, você deve especificar explicitamente a associação de namespace usando WITH XMLNAMESPACES. A consulta a seguir define explicitamente o prefixo do namespace para a vinculação de URI para o namespace predefinido (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');

Este é o resultado. Os usuários do SQLXML estão familiarizados com esse modelo XML. Para obter mais informações, consulte SQLXML 4.0 Programming Concepts.

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

Somente o prefixo do namespace xml pode ser usado sem defini-lo explicitamente em WITH XMLNAMESPACES, conforme mostrado na seguinte consulta do modo PATH. Além disso, se o prefixo for declarado, ele deverá ser vinculado ao namespace http://www.w3.org/XML/1998/namespace. Os nomes especificados na cláusula SELECT referem-se ao prefixo do namespace xml que não é explicitamente definido usando WITH XMLNAMESPACES.

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

Os atributos @xml:lang usam o namespace xml predefinido. Como o XML versão 1.0 não requer a declaração explícita da associação de namespace xml, o resultado não incluirá uma declaração explícita da associação de namespace.

Este é o resultado:

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

Use WITH XMLNAMESPACES com os métodos de tipo de dados XML

Os métodos de tipo de dados xml especificados em uma consulta SELECT ou em UPDATE quando é o método modify(), todos precisam repetir a declaração de namespace em seu prólogo. Isso pode ser demorado. Por exemplo, a consulta a seguir recupera IDs de modelo de produto cujas descrições de catálogo incluem especificação. Ou seja, o elemento <Specifications> existe.

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;

Na consulta anterior, os métodos query() e exist() declaram o mesmo namespace em seu prólogo. Por exemplo:

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

Como alternativa, você pode declarar WITH XMLNAMESPACES primeiro e usar os prefixos de namespace na consulta. Nesse caso, os métodos query() e exist() não precisam incluir declarações de namespace em seu prólogo.

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

Uma declaração explícita no prolog XQuery substitui o prefixo do namespace e o namespace do elemento padrão definidos na cláusula WITH.

Ver também