Consultando XML usando OPENXML

OPENXML, uma palavra-chave do Transact-SQL, fornece um conjunto de linhas em documentos XML na memória que é semelhante a uma tabela ou exibição. OPENXML permite acesso a dados XML ainda que ele seja um conjunto de linhas relacional. Ele faz isso fornecendo uma exibição do conjunto de linhas da representação interna de um documento XML. Os registros no conjunto de linhas podem ser armazenados em tabelas do banco de dados.

OPENXML pode ser usado em instruções SELECT e SELECT INTO sempre que provedores de conjunto de linhas, uma exibição ou OPENROWSET podem ser exibidos como a origem. Para obter mais informações sobre a sintaxe de OPENXML, consulte OPENXML (Transact-SQL).

Para escrever consultas em relação a um documento XML usando OPENXML, você deve primeiro chamar sp_xml_preparedocument. Isso analisa o documento XML e retorna um identificador ao documento analisado pronto para consumo. O documento analisado é uma representação da árvore DOM (Document Object Model) de vários nós no documento XML. O identificador do documento é passado para OPENXML. Em seguida, o OPENXML fornece uma exibição do conjunto de linhas do documento, baseado nos parâmetros passados para ele.

ObservaçãoObservação

A partir do SQL Server 2005, sp_xml_preparedocument usa uma versão atualizada pelo SQL do analisador MSXML, Msxmlsql.dll. Essa versão do analisador MSXML foi criada para oferecer suporte ao SQL Server e permanecer para compatível com o MSXML versão 2.6.

A representação interna de um documento XML deve ser removida da memória chamando o procedimento armazenado do sistema sp_xml_removedocument para liberar a memória.

A ilustração a seguir mostra o processo.

Analisando XML com OPENXML

Observe que para entender o OPENXML, é necessário estar familiarizado com consultas XPath e ter um entendimento de XML. Para obter mais informações sobre suporte ao XPath no SQL Server, consulte Usando consultas XPath no SQLXML 4.0.

ObservaçãoObservação

O OpenXML permite que os padrões de linha e coluna do XPath sejam parametrizados como variáveis. Essa parametrização pode resultar em injeções de expressões XPath, se o programador expuser a parametrização a usuários externos (por exemplo, se os parâmetros forem fornecidos por meio de um procedimento armazenado chamado externamente). Para evitar esses problemas potenciais de segurança, é recomendável que os parâmetros de XPath nunca sejam expostos a chamadores externos.

Parâmetros de OPENXML

Os parâmetros para OPENXML incluem:

  • Um identificador de documento XML (idoc)

  • Uma expressão XPath para identificar os nós a serem mapeados para linhas (rowpattern)

  • Uma descrição do conjunto de linhas a ser gerado

  • Mapeamento entre as colunas do conjunto de linhas e os nós XML

Identificador do documento XML (idoc)

O identificador do documento é retornado pelo procedimento armazenado sp_xml_preparedocument.

Expressão XPath para identificar os nós a serem processados (rowpattern)

A expressão XPath especificada como rowpattern identifica um conjunto de nós no documento XML. Cada nó identificado por rowpattern corresponde a uma única linha no conjunto de linhas gerado por OPENXML.

Os nós identificados pela expressão XPath podem ser qualquer nó XML no documento XML. Se rowpattern identificar um conjunto de elementos no documento XML, haverá uma linha no conjunto de linhas para cada nó de elemento identificado. Por exemplo, se rowpattern terminar em um atributo, será criada uma linha para cada nó de atributo selecionado por rowpattern.

Descrição do conjunto de linhas a ser gerado

Um esquema de conjunto de linhas usado por OPENXML para gerar o conjunto de linhas resultante. É possível usar as seguintes opções ao especificar um esquema de conjunto de linhas.

Usando o formato de tabela de borda

Você deve usar o formato de tabela de borda para especificar um esquema de conjunto de linhas. Não use a cláusula WITH.

Quando isso é feito, o OPENXML retorna um conjunto de linhas no formato de tabela de borda. Isso é referido como uma tabela de borda, porque cada borda na árvore do documento XML analisado é mapeada para uma linha no conjunto de linhas.

Tabelas de borda representam a estrutura do documento XML refinado dentro de uma única tabela. Essa estrutura inclui o nomes dos atributos e elementos, a hierarquia do documento, os namespaces e as instruções de processamento. O formato de tabela de borda permite obter informações adicionais que não são expostas pelas metapropriedades. Para obter mais informações sobre metapropriedades, consulte Especificando metapropriedades no OPENXML29bfd1c6-3f9a-43c4-924a-53d438e442f4.

As informações adicionais fornecidas por uma tabela de borda permitem armazenar e consultar o tipo de dados de um elemento e de um atributo e o tipo de nó, e também armazenar e consultar informações sobre a estrutura do documento XML. Com essas informações adicionais, também pode ser possível construir seu próprio sistema de gerenciamento de documentos XML.

Usando uma tabela de borda, é possível escrever procedimentos armazenados que usam documentos XML como entrada BLOB (bloco de objetos binários grandes), produzir a tabela de borda e, em seguida, extrair e analisar o documento em um nível mais detalhado. Esse nível detalhado pode incluir a localização da hierarquia do documento, os nomes dos atributos e elementos, os namespaces e as instruções de processamento.

A tabela de borda também pode funcionar como um formato de armazenamento para documentos XML quando o mapeamento para outros formatos relacionais não for lógico e um campo ntext não estiver fornecendo informações estruturais suficientes.

Em situações em que é possível usar um analisador XML para examinar um documento XML, é possível usar uma tabela de borda em vez de obter as mesmas informações.

A tabela seguinte descreve a estrutura da tabela de borda.

Nome da coluna

Tipo de dados

Descrição

id

bigint

É a ID exclusiva do nó do documento.

O elemento raiz tem um valor de ID igual a 0. Os valores negativos da ID são reservados.

parentid

bigint

Identifica o pai do nó. O pai identificado por esse ID necessariamente não é o elemento pai. No entanto isso depende do Tipo do Nó cujo pai é identificado por esse ID. Por exemplo, se o nó for um nó de texto, seu pai poderá ser um nó de atributo.

Se o nó estiver no nível superior no documento XML, seu ParentID será NULL.

tipo de nó

int

Identifica o tipo de nó e é um inteiro que corresponde à numeração do tipo de nó DOM (document object model) do XML.

Os seguintes são os valores que podem aparecer nessa coluna para indicar o tipo do nó:

1 = Nó de elemento

2 = Nó de atributo

3 = Nó de texto

4 = Nó de seção CDATA

5 = Nó de referência de entidade

6 = Nó de entidade

7 = Nó de instrução de processamento

8 = Nó de comentário

9 = Nó de documento

10 = Nó de tipo de documento

11 = Nó de fragmento de documento

12 = Nó de notação

Para obter mais informações, consulte o tópico "Propriedade nodeType" no SDK do MSXML (Microsoft XML.

localname

nvarchar(max)

Fornece o nome local do elemento ou do atributo. Será NULL se o objeto DOM não tiver um nome.

prefixo

nvarchar(max)

É o prefixo do namespace do nome do nó.

namespaceuri

nvarchar(max)

É o URI do namespace do nó. Se o valor for NULL, nenhum namespace estará presente.

datatype

nvarchar(max)

É o tipo real de dados da linha de atributo ou de elemento e é normalmente NULL. O tipo de dados é deduzido do DTD embutido ou do esquema embutido.

prev

bigint

É a ID de XML do elemento irmão anterior. Será NULL se não houver nenhum irmão anterior direto.

text

ntext

Contém o valor do atributo ou o conteúdo do elemento em formulário de texto. Ou será NULL, se a entrada da tabela de borda não precisar de um valor.

Usando a cláusula WITH para especificar uma tabela existente

Você pode usar a cláusula WITH para especificar o nome de uma tabela existente. Para isso, basta especificar o nome de uma tabela existente cujo esquema possa ser usado por OPENXML para gerar o conjunto de linhas.

Usando a cláusula WITH para especificar um esquema

É possível usar a cláusula WITH para especificar um esquema completo. Para especificar o esquema do conjunto de linhas, você especifica os nomes das colunas, seus tipos de dados e seus mapeamentos para o documento XML.

Você pode especificar o padrão da coluna usando o parâmetro ColPattern na SchemaDeclaration. O padrão da coluna especificado é usado para mapear uma coluna do conjunto de linhas para o nó XML que é identificado pelo padrão da linha e também é usado para determinar o tipo de mapeamento.

Se ColPattern não for especificado para uma coluna, a coluna do conjunto de linhas será mapeada para o nó XML com o mesmo nome, com base no mapeamento especificado pelo parâmetro flags. No entanto se ColPattern for especificado como parte da especificação do esquema na cláusula WITH, ele sobrescreverá o mapeamento especificado no parâmetro flags.

Mapeamento entre as colunas do conjunto de linhas e os nós XML

Na instrução OPENXML, você pode opcionalmente especificar o tipo de mapeamento, como centrado em atributo ou centrado em elemento, entre as colunas do conjunto de linhas e os nós XML identificados pelo rowpattern. Essas informações são usadas na transformação entre os nós XML nós e as colunas do conjunto de linhas.

É possível especificar o mapeamento de qualquer um dos modos e também especificar os dois:

  • Usando o parâmetro flags

    O mapeamento especificado pelo parâmetro flags pressupõe correspondência de nomes na qual os nós XML são mapeados para as colunas do conjunto de linhas correspondentes com o mesmo nome.

  • Usando o parâmetro ColPattern

    ColPattern, uma expressão XPath, é especificada como parte de SchemaDeclaration na cláusula WITH. O mapeamento especificado em ColPattern substitui o mapeamento especificado pelo parâmetro flags.

    ColPattern pode ser usado para especificar o tipo de mapeamento, como centrado em atributo ou centrado em elemento, que sobrescreve ou aprimora o mapeamento indicado pelo flags.

    ColPattern é especificado nas seguintes circunstâncias:

    • O nome da coluna no conjunto de linhas é diferente do nome do atributo ou elemento para o qual ele é mapeado. Nesse caso, ColPattern é usado para identificar o elemento XML e o nome do atributo para o qual a coluna do conjunto de linhas é mapeado.

    • Você quer mapear um atributo de metapropriedade para a coluna. Nesse caso, ColPattern é usado para identificar a metapropriedade para a qual a coluna do conjunto de linhas é mapeada. Para obter mais informações sobre como usar metapropriedades, consulte Especificando metapropriedades no OPENXML.

Os parâmetros flags e ColPattern são opcionais. Se nenhum mapeamento for especificado, será pressuposto o mapeamento centrado em atributo. O mapeamento centrado em atributo é o valor padrão do parâmetro flags.

Mapeamento centrado em atributo

A definição do parâmetro flags no OPENXML como 1 (XML_ATTRIBUTES) especifica mapeamento centrado em atributo. Se flags contiver XML_ ATTRIBUTES, o conjunto de linhas exposto fornecerá ou consumirá linhas onde cada elemento XML é representado como uma linha. Os atributos XML são mapeados para os atributos definidos na SchemaDeclaration ou que são fornecidos pelo Tablename da cláusula WITH com base na correspondência de nomes. A correspondência de nomes significa que os atributos XML de um nome específico são armazenados em uma coluna no conjunto de linhas com o mesmo nome.

Se o nome da coluna for diferente do nome de atributo para o qual ele é mapeado, ColPattern deverá ser especificado.

Se o atributo XML tiver um qualificador de namespace, o nome da coluna no conjunto de linhas também precisará ter o qualificador.

Mapeamento centrado em elemento

A definição do parâmetro flags no OPENXML como 2 (XML_ELEMENTS) especifica mapeamento centrado em elemento. É semelhante ao mapeamento centrado em atributo, com exceção das seguintes diferenças:

  • A correspondência de nomes do exemplo de mapeamento, uma mapeamento de coluna para um elemento XML com o mesmo nome seleciona os subelementos não complexos, a menos que o padrão em nível de coluna seja especificado. No processo de recuperação, se o subelemento for complexo porque contém subelementos adicionais, a coluna será definida como NULL. Valores de atributos dos subelementos são ignorados então.

  • Para vários subelementos com o mesmo nome, o primeiro nó é retornado.