Iniciando com XQuery – Namespaces têm solução!

É muito comum em cenário com XML ter situações que no cabeçalho do arquivo há “xmlns” e nós com prefixos “xsi:”, “xsd:” e entre outros, deixando o DBA ou desenvolvedor responsável pelas consultas confuso com o fato de consultas com simples XQueries não trazerem nenhum resultado.

Mesmo que o comportamento “padrão” nestes cenários na maioria das vezes é dar um REPLACE no cabeçalho do XML, vamos aprender como resolver esta situação de forma prática.

O XML que usarei para o exemplo possui um namespace bem comum para dados oriundos de aplicações como o http://tempuri.org/, que é o namespace padrão do exemplo (URL declarada com xmlns sem qualquer sufixo):

DECLARE @X XML

SET @X = '
<ArrayOfDsItem xmlns="http://tempuri.org/" xmlns:ns2="http://tempuri2.org/">
  <DsItem Code="1" Value="ACRE" Value2="AC">
    <ns2:Status>Não existe</ns2:Status>
  </DsItem>
  <DsItem Code="5" Value="BAHIA" Value2="BA" />
  <DsItem Code="11" Value="MATO GROSSO" Value2="MT" />
  <DsItem Code="13" Value="MINAS GERAIS" Value2="MG" />
  <DsItem Code="19" Value="RIO DE JANEIRO" Value2="RJ" />
  <DsItem Code="21" Value="RIO GRANDE DO SUL" Value2="RS" />
  <DsItem Code="24" Value="SÃO PAULO" Value2="SP" />
</ArrayOfDsItem>'

Visto que estamos tratando de um namespace padrão, podemos determinar ou por T-SQL ou por XQuery, que este é o bendito namespace de todo o XML:

-- Definindo o namespace padrão
;WITH XMLNAMESPACES (DEFAULT 'http://tempuri.org/')
SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla
FROM @X.nodes('//ArrayOfDsItem/DsItem') AS N(E)

SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla
FROM @X.nodes('
	declare default element namespace "http://tempuri.org/";
	//ArrayOfDsItem/DsItem
') AS N(E)

Ou podemos criar um namespace sinônimo (ns), o que afetará um pouco a nossa XQuery:

-- Definindo um sinonimo para namespace padrão (ns)
;WITH XMLNAMESPACES ('http://tempuri.org/' AS ns)
SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla
FROM @X.nodes('//ns:ArrayOfDsItem/ns:DsItem') AS N(E)

SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla
FROM @X.nodes('
	declare namespace ns = "http://tempuri.org/";
	//ns:ArrayOfDsItem/ns:DsItem
') AS N(E)

Mas e agora, tenho dois ou mais namespaces no XML, o que podemos fazer? Podemos optar por qualquer uma das práticas anteriores (definindo um sinônimo ou definindo o namespace padrão) e mais os sinônimos para os namespaces secundários:

-- Definindo o namespace padrão e o sinonimo para o secundário (ns2)
;WITH XMLNAMESPACES (
	DEFAULT 'http://tempuri.org/',
	'http://tempuri2.org/' AS ns2
)
SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla,
	E.value('ns2:Status[1]', 'varchar(25)') AS Comentario
FROM @X.nodes('//ArrayOfDsItem/DsItem') AS N(E)

SELECT
E.value('@Value', 'varchar(25)') AS Estado,
E.value('@Value2', 'char(2)') AS Sigla,
E.value('
	declare namespace ns2 = "http://tempuri2.org/";
	ns2:Status[1]
' , 'varchar(25)') AS Comentario
FROM @X.nodes('
	declare default element namespace "http://tempuri.org/";
	//ArrayOfDsItem/DsItem
') AS N(E)

-- Definindo sinonimos para namespace padrão (ns) e para o secundário (ns2)
;WITH XMLNAMESPACES (
	'http://tempuri.org/' AS ns,
	'http://tempuri2.org/' AS ns2
)
SELECT
	E.value('@Value', 'varchar(25)') AS Estado,
	E.value('@Value2', 'char(2)') AS Sigla,
	E.value('ns2:Status[1]', 'varchar(25)') AS Comentario
FROM @X.nodes('//ns:ArrayOfDsItem/ns:DsItem') AS N(E)

SELECT
E.value('@Value', 'varchar(25)') AS Estado,
E.value('@Value2', 'char(2)') AS Sigla,
E.value('
	declare namespace ns2 = "http://tempuri2.org/";
	ns2:Status[1]
' , 'varchar(25)') AS Comentario
FROM @X.nodes('
	declare namespace ns = "http://tempuri.org/";
	//ns:ArrayOfDsItem/ns:DsItem
') AS N(E)

Ficou legal, não ficou? Mas nada te impede de colocar alguns REPLACEs na sua query e ser feliz…

No próximo artigo veremos com iniciar um pequeno caos com o FOR XML e Namespaces…

3 pensamentos sobre “Iniciando com XQuery – Namespaces têm solução!

  1. De novo, grande iniciativa.
    Estamos com um projeto para importar Nfe, estamos indo bem, mas nosso problema são os campos de impostos ICMS, IPI. A tag pode variar de produto para produto.
    Teria um exemplo relacionado a isso?

  2. Pingback: Extraindo informações de arquivo XML para o SQL Server « Alex Souza

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s