9.15. Funções de XML #

9.15.1. Produção de conteúdo XML
9.15.2. Predicados do XML
9.15.3. Processamento de XML
9.15.4. Mapeando tabelas para XML

As funções, e expressões semelhantes a uma função, descritas nesta seção, operam nos valores do tipo de dados xml. Veja a Seção 8.13 para obter informações sobre o tipo de dados xml. As expressões semelhantes a uma função xmlserialize e xmlparse, que realizam a conversão de e para o tipo de dados xml, também estão documentadas na Seção 8.13, e não nesta seção.

O uso da maioria destas funções requer que o PostgreSQL tenha sido construído com configure --with-libxml.

9.15.1. Produção de conteúdo XML #

Está disponível um conjunto de funções, e expressões semelhantes a uma função, para produzir conteúdo XML a partir de dados SQL. Como tal, são particularmente adequadas para formatar os resultados das consultas em documentos XML para processamento em aplicações cliente.

9.15.1.1. xmltext #

xmltext ( text ) → xml

A função xmltext retorna um valor XML com um único nó de texto contendo o argumento de entrada como seu conteúdo. Entidades predefinidas como o e comercial (&), colchetes angulares / menor e maior que (< >) e aspas ("") recebem escape.

Exemplo:

SELECT xmltext('< foo & bar >');
         xmltext
-------------------------
 &lt; foo &amp; bar &gt;

9.15.1.2. xmlcomment #

xmlcomment ( text ) → xml

A função xmlcomment cria um valor XML contendo um comentário XML com o texto especificado como conteúdo. O texto não pode conter -- (dois hifens consecutivos), ou terminar por - (hífen), senão, a construção resultante não será um comentário XML válido. Se o argumento for nulo, então o resultado será nulo. [72]

Exemplo:

SELECT xmlcomment('Alô mundo!');

    xmlcomment
-------------------
 <!--Alô mundo!-->

9.15.1.3. xmlconcat #

xmlconcat ( xml [, ...] ) → xml

A função xmlconcat concatena uma lista de valores XML individuais para criar um único valor contendo um fragmento de conteúdo XML. Os valores nulos são omitidos; o resultado só será nulo se não houver nenhum argumento não nulo. [73]

Exemplo:

SELECT xmlconcat('<abc/>', '<bar>foo</bar>');

      xmlconcat
----------------------
 <abc/><bar>foo</bar>

As declarações XML, se presentes, são combinadas da seguinte forma: Se todos os valores dos argumentos tiverem a mesma declaração de versão do XML, será usada esta versão no resultado, caso contrário, nenhuma versão será usada; se todos os valores dos argumentos tiverem o valor de declaração de autonomia (standalone) igual a yes, este valor será usado no resultado; se todos os valores dos argumentos tiverem um valor de declaração de autonomia, e pelo menos um desses valores for no, então este valor será usado no resultado. Senão, o resultado não terá uma declaração de autonomia; Se o resultado exigir uma declaração de autonomia, mas nenhuma declaração de versão, então será usada uma declaração de versão com a versão 1.0, porque o XML requer uma declaração XML para conter uma declaração de versão. As declarações de codificação são ignoradas e removidas em todos os casos.

Exemplo:

SELECT xmlconcat('<?xml version="1.1" standalone="yes"?><foo/>',
                 '<?xml version="1.1" standalone="no"?><bar/>');

                     xmlconcat
---------------------------------------------------
 <?xml version="1.1" standalone="no"?><foo/><bar/>

9.15.1.4. xmlelement #

xmlelement ( NAME nome [, ↵
    XMLATTRIBUTES ( valor_do_atributo [ AS nome_do_atributo ] [, ...] ) ] ↵
    [, conteúdo [, ...]] ) → xml

A expressão xmlelement produz um elemento XML com o nome, atributos e conteúdo fornecidos. Os itens nome e nome_do_atributo mostrados na sintaxe são identificadores simples, e não valores. Os itens valor_do_atributo e conteúdo são expressões que podem produzir qualquer tipo de dados do PostgreSQL. O(s) argumento(s) dentro de XMLATTRIBUTES gera(m) atributo(s) do elemento XML; o(s) valor(es) do conteúdo são concatenados para formar o seu conteúdo. [74]

Exemplos:

SELECT xmlelement(name foo);

 xmlelement
------------
 <foo/>

SELECT xmlelement(name foo, xmlattributes('xyz' as bar));

    xmlelement
------------------
 <foo bar="xyz"/>

SELECT xmlelement(name foo, xmlattributes(current_date as bar), 'conte', 'údo');

              xmlelement
--------------------------------------
 <foo bar="2022-09-13">conteúdo</foo>

Os nomes dos elementos e atributos, que não são nomes XML válidos, recebem escape substituindo os caracteres incorretos pela sequência _xHHHH_, onde HHHH é o caractere de ponto de código Unicode em notação hexadecimal. Por exemplo: [75]

SELECT xmlelement(name "foo$bar", xmlattributes('xyz' as "a&b"));

            xmlelement
----------------------------------
 <foo_x0024_bar a_x0026_b="xyz"/>

Se o valor do atributo for uma referência de coluna, não precisa ser especificado um nome de atributo explícito; nesse caso, o nome da coluna será usado como o nome do atributo por padrão. Nos outros casos, o atributo deve receber um nome explícito. Assim sendo, este exemplo é válido:

CREATE TABLE test (a xml, b xml);
SELECT xmlelement(name test, xmlattributes(a, b)) FROM test;

Mas estes não são:

SELECT xmlelement(name test, xmlattributes('constant'), a, b) FROM test;
SELECT xmlelement(name test, xmlattributes(func(a, b))) FROM test;

O conteúdo do elemento, se for especificado, será formatado de acordo com seu tipo de dados. Se o conteúdo for do tipo de dados xml, podem ser construídos documentos XML complexos. Por exemplo:

SELECT xmlelement(name foo, xmlattributes('xyz' as bar),
                            xmlelement(name abc),
                            xmlcomment('test'),
                            xmlelement(name xyz));

                  xmlelement
----------------------------------------------
 <foo bar="xyz"><abc/><!--test--><xyz/></foo>

No Oracle 21c, o resultado desta mesma consulta é (N. T.):

<FOO BAR="xyz"><ABC></ABC><!--test--><XYZ></XYZ></FOO>

O conteúdo de outros tipos de dados será formatado usando caracteres XML válidos, significando, em particular, que os caracteres <, >, e & serão convertidos em entidades. Os dados binários (tipo de dados bytea) serão representados em codificação base64 ou hexadecimal, dependendo da definição do parâmetro de configuração xmlbinary. Espera-se que o comportamento específico para tipos de dados individuais evolua para alinhar os mapeamentos do PostgreSQL com os especificados no SQL:2006 e posteriores, conforme discutido na Seção D.3.1.3.

9.15.1.5. xmlforest #

xmlforest ( conteúdo [ AS nome ] [, ...] ) → xml

A expressão xmlforest produz uma floresta (sequência) XML de elementos usando os nomes e conteúdo fornecidos. Assim como para a função xmlelement, cada nome deve ser um identificador simples, enquanto as expressões do conteúdo podem ter qualquer tipo de dados. [76]

Exemplos:

SELECT xmlforest('abc' AS foo, 123 AS bar);

          xmlforest
------------------------------
 <foo>abc</foo><bar>123</bar>


SELECT xmlforest(table_name, column_name)
FROM information_schema.columns
WHERE table_schema = 'pg_catalog';

                                xmlforest
------------------------------------------------------------------------------------------
 <table_name>pg_stat_xact_all_tables</table_name><column_name>n_tup_ins</column_name>
 <table_name>pg_prepared_statements</table_name><column_name>parameter_types</column_name>
 ...

Como visto no segundo exemplo, o nome do elemento pode ser omitido se o valor do conteúdo for uma referência de coluna, caso onde o nome da coluna é usado por padrão. Caso contrário, deve ser especificado um nome.

Os nomes de elementos, que não são nomes XML válidos, recebem escape como foi mostrado para a função xmlelement acima. Da mesma forma, os dados do conteúdo recebem escape para tornar o conteúdo um XML válido, a menos que já seja do tipo de dados xml.

Note que as florestas XML não são documentos XML válidos se consistirem em mais de um elemento, portanto pode ser útil agrupar expressões xmlforest em xmlelement.

9.15.1.6. xmlpi #

xmlpi ( NAME nome [, conteúdo ] ) → xml

A expressão xmlpi cria uma instrução de processamento XML. Assim como para a função xmlelement, cada nome deve ser um identificador simples, enquanto as expressões do conteúdo podem ter qualquer tipo de dados. O conteúdo, caso esteja presente, não deve conter a sequência de caracteres ?>. [77]

Exemplo:

SELECT xmlpi(name php, 'echo "hello world";');

            xmlpi
-----------------------------
 <?php echo "hello world";?>

9.15.1.7. xmlroot #

xmlroot ( xml, VERSION {text|NO VALUE} [, STANDALONE {YES|NO|NO VALUE} ] ) → xml

A expressão xmlroot altera as propriedades do nó raiz de um valor XML. Se for especificada a versão, será substituído o valor da versão na declaração de versão do nó raiz; se for especificada a autonomia (standalone) será substituído o valor da autonomia na declaração de autonomia do nó raiz. [78]; [79],

SELECT xmlroot(xmlparse(document '<?xml version="1.1"?><content>abc</content>'),
               version '1.0', standalone yes);

                xmlroot
----------------------------------------
 <?xml version="1.0" standalone="yes"?>
 <content>abc</content>

9.15.1.8. xmlagg #

xmlagg ( xml ) → xml

A função xmlagg é, ao contrário das outras funções descritas aqui, uma função de agregação. Esta função concatena os valores de entrada para a chamada da função de agregação, assim como xmlconcat faz, exceto pela concatenação acontecer entre linhas, e não entre expressões em uma única linha. Veja a Seção 9.21 para obter informações adicionais sobre funções de agregação. [80]

Exemplo:

CREATE TABLE test (y int, x xml);
INSERT INTO test VALUES (1, '<foo>abc</foo>');
INSERT INTO test VALUES (2, '<bar/>');
SELECT xmlagg(x) FROM test;

        xmlagg
----------------------
 <foo>abc</foo><bar/>

Para determinar a ordem da concatenação pode ser adicionada a cláusula ORDER BY à chamada da agregação, conforme descrito na Seção 4.2.7. Por exemplo:

SELECT xmlagg(x ORDER BY y DESC) FROM test;

        xmlagg
----------------------
 <bar/><foo>abc</foo>

O seguinte enfoque, fora do padrão, costumava ser recomendado nas versões anteriores, e ainda pode ser útil em casos específicos:

SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;

        xmlagg
----------------------
 <bar/><foo>abc</foo>

9.15.2. Predicados do XML #

As expressões descritas nesta seção verificam as propriedades dos valores do tipo de dados xml.

9.15.2.1. IS DOCUMENT #

xml IS DOCUMENTboolean

A expressão IS DOCUMENT retorna verdade se o valor do argumento XML for um documento XML apropriado, falso se não for (ou seja, é um fragmento de conteúdo), ou nulo, se o argumento for nulo. Veja a Seção 8.13 para conhecer a diferença entre documentos e fragmentos de conteúdo.

9.15.2.2. IS NOT DOCUMENT #

xml IS NOT DOCUMENTboolean

A expressão IS NOT DOCUMENT retorna falso se o valor do argumento XML for um documento XML apropriado, verdade se não for (ou seja, é um fragmento de conteúdo), ou nulo, se o argumento for nulo.

9.15.2.3. XMLEXISTS #

XMLEXISTS ( text PASSING [BY {REF|VALUE}] xml [BY {REF|VALUE}] ) → boolean

A função xmlexists avalia uma expressão XPath 1.0 (o primeiro argumento), com o valor XML passado como seu item de contexto. A função retorna falso se o resultado desta avaliação gerar um conjunto de nós vazios, ou verdade se gerar qualquer outro valor. A função retorna nulo se algum argumento for nulo. O valor não nulo passado como item de contexto deve ser um documento XML, e não um fragmento de conteúdo ou qualquer valor não XML. [81]

Exemplo:

SELECT xmlexists('//town[text() = ''Toronto'']'
       PASSING BY VALUE '<towns><town>Toronto</town><town>Ottawa</town></towns>');

 xmlexists
------------
 t
(1 linha)

As cláusulas BY REF e BY VALUE são aceitas pelo PostgreSQL, mas são ignoradas, conforme discutido na Seção D.3.2.

No padrão SQL, a função xmlexists avalia uma expressão na linguagem XML Query, mas no PostgreSQL permite apenas uma expressão XPath 1.0, conforme discutido na Seção D.3.1.

9.15.2.4. xml_is_well_formed #

xml_is_well_formed ( text ) → boolean
xml_is_well_formed_document ( text ) → boolean
xml_is_well_formed_content ( text ) → boolean

Estas funções verificam se uma cadeia de caracteres do tipo de dados text representa um XML bem formado, retornando um resultado booleano. A função xml_is_well_formed_document verifica se é um documento bem formado, enquanto a função xml_is_well_formed_content verifica se o conteúdo é bem formado. A função xml_is_well_formed executa o primeiro caso se o parâmetro de configuração xmloption estiver definido como DOCUMENT, ou executa o segundo caso se estiver definido como CONTENT, significando que a função xml_is_well_formed é útil para verificar se uma simples conversão para o tipo de dados xml será bem sucedida, enquanto as outras duas funções são úteis para verificar se as variantes correspondentes da função XMLPARSE serão bem-sucedidas.

Exemplos:

SET xmloption TO DOCUMENT;
SELECT xml_is_well_formed('<>');

 xml_is_well_formed
--------------------
 f
(1 linha)

SELECT xml_is_well_formed('<abc/>');

 xml_is_well_formed
--------------------
 t
(1 linha)

SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');

 xml_is_well_formed
--------------------
 t
(1 linha)

SELECT xml_is_well_formed_document(
       '<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</pg:foo>');

 xml_is_well_formed_document
-----------------------------
 t
(1 linha)

SELECT xml_is_well_formed_document(
       '<pg:foo xmlns:pg="http://postgresql.org/stuff">bar</my:foo>');

 xml_is_well_formed_document
-----------------------------
 f
(1 linha)

O último exemplo mostra que as verificações incluem se os espaços de nomes (namespaces) são correspondidos corretamente.

9.15.3. Processamento de XML #

Para processar valores do tipo de dados xml, o PostgreSQL oferece as funções xpath e xpath_exists, que avaliam expressões XPath 1.0, e a função de tabela XMLTABLE.

9.15.3.1. xpath #

xpath ( xpath text, xml xml [, nsarray text[] ] ) → xml[]

A função xpath avalia a expressão XPath 1.0 xpath (fornecida como texto) contra o valor XML xml. Esta função retorna uma matriz de valores XML correspondentes ao conjunto de nós produzido pela expressão XPath. Se a expressão XPath retornar um valor escalar, em vez de um conjunto de nós, será retornada uma matriz de um único elemento.

O segundo argumento deve ser um documento XML bem formado. Em particular, deve ter um único elemento de nó raiz.

O terceiro argumento da função (opcional) é uma matriz de mapeamentos de espaço de nomes. Esta matriz deve ser uma matriz bidimensional do tipo de dados text, com o comprimento do segundo eixo igual a 2 (ou seja, deve ser uma matriz de matrizes, cada uma das quais consistindo em exatamente 2 elementos). O primeiro elemento de cada entrada da matriz é o nome do espaço de nomes (alias), e o segundo é o URI do espaço de nomes. Não é necessário que os aliases fornecidos nesta matriz sejam os mesmos que estão sendo usados no próprio documento XML (em outras palavras, tanto no documento XML quanto no contexto da função xpath, os aliases são locais).

Exemplo:

SELECT xpath('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
             ARRAY[ARRAY['my', 'http://example.com']]);

 xpath
--------
 {test}
(1 linha)

Para lidar com espaços de nomes padrão (anônimos), faça algo assim:

SELECT xpath('//mydefns:b/text()', '<a xmlns="http://example.com"><b>test</b></a>',
             ARRAY[ARRAY['mydefns', 'http://example.com']]);

 xpath
--------
 {test}
(1 linha)

9.15.3.2. xpath_exists #

xpath_exists ( xpath text, xml xml [, nsarray text[] ] ) → boolean

A função xpath_exists é uma forma especializada da função xpath. Em vez de retornar os valores XML individuais que satisfazem a expressão XPath 1.0, esta função retorna um valor booleano indicando se a consulta foi satisfeita ou não (especificamente, se produziu qualquer valor diferente de um conjunto de nós vazios). Esta função equivale ao predicado XMLEXISTS, exceto por também oferecer suporte para argumento de mapeamento de espaço de nomes.

Exemplo:

SELECT xpath_exists('/my:a/text()', '<my:a xmlns:my="http://example.com">test</my:a>',
                     ARRAY[ARRAY['my', 'http://example.com']]);

 xpath_exists
--------------
 t
(1 linha)

9.15.3.3. xmltable #

XMLTABLE (
    [ XMLNAMESPACES ( namespace_uri AS namespace_name [, ...] ), ]
    row_expression PASSING [BY {REF|VALUE}] document_expression [BY {REF|VALUE}]
    COLUMNS nome { type [PATH column_expression] [DEFAULT default_expression] [NOT NULL | NULL]
                  | FOR ORDINALITY }
            [, ...]
) → setof record

A expressão xmltable produz uma tabela baseado em um valor XML, um filtro XPath para extrair as linhas, e um conjunto de definições de coluna. Embora seja sintaticamente semelhante a uma função, só pode aparecer como uma tabela na cláusula FROM de uma consulta.

A cláusula opcional XMLNAMESPACES fornece uma lista separada por vírgulas de definições de espaços de nomes, onde cada namespace_uri é uma expressão do tipo de dados text, e cada namespace_name é um identificador simples. Esta cláusula determina os espaços de nomes XML usados no documento e seus aliases. Não há suporte para uma especificação de espaço de nomes padrão no momento.

O argumento requerido row_expression é uma expressão XPath 1.0 (fornecida como text), avaliada passando o valor XML document_expression como seu item de contexto, para obter um conjunto de nós XML. Esses nós são o que a função xmltable transforma em linhas de saída. Não será produzida nenhuma linha se document_expression for nulo, nem se row_expression produzir um conjunto de nós vazios, ou qualquer outro valor que não seja um conjunto de nós.

O argumento document_expression fornece o item de contexto para o argumento row_expression. Deve ser um documento XML bem formado; fragmentos/florestas não são aceitos. As cláusulas BY REF e BY VALUE são aceitas, mas ignoradas, conforme discutido na Seção D.3.2.

No padrão SQL, a função xmltable avalia as expressões na linguagem XML Query, mas o PostgreSQL permite apenas expressões XPath 1.0, conforme o discutido na Seção D.3.1.

A cláusula requerida COLUMNS determina as colunas que serão produzidas na tabela de saída. Veja o resumo da sintaxe acima para conhecer o formato. Para cada coluna é requerido o nome, assim como o tipo de dados (a menos que seja especificado FOR ORDINALITY, caso onde o tipo de dados integer está implícito). As cláusulas PATH, DEFAULT e nulo/não nulo são opcionais.

Uma coluna marcada com FOR ORDINALITY será preenchida com o número da linha, começando por 1, na ordem dos nós recuperados do conjunto de nós de resultado da row_expression. Pode ser marcada no máximo uma coluna com FOR ORDINALITY.

Nota

O XPath 1.0 não determina uma ordem para os nós em um conjunto de nós, portanto o código que depender de uma ordem específica dos resultados será dependente da implementação. Podem ser encontrados detalhes na Seção D.3.1.2.

O argumento column_expression para a coluna é uma expressão XPath 1.0, avaliada para cada linha com o nó corrente do resultado de row_expression como seu item de contexto, para encontrar o valor da coluna. Se não for fornecida nenhuma column_expression, então o nome da coluna será usado como caminho implícito.

Se a expressão XPath da coluna retornar um valor não-XML (que está limitado a cadeia de caracteres, booleano, ou precisão dupla no XPath 1.0), e a coluna tiver um tipo de dados do PostgreSQL diferente de xml, a coluna será definida como se estivesse atribuindo a sua representação cadeia de caracteres do valor do tipo de dados do PostgreSQL. (Se o valor for booleano, sua representação cadeia de caracteres será assumida como 1 ou 0, se a categoria do tipo de dados da coluna de saída for numérica, caso contrário true ou false.)

Se a expressão XPath da coluna retornar um conjunto não vazio de nós XML, e o tipo de dados do PostgreSQL da coluna for xml, a coluna receberá o resultado exato da expressão, se for da forma de documento ou conteúdo. [82]

Um resultado não-XML atribuído a uma coluna de saída xml produz conteúdo, um único nó de texto com o valor cadeia de caracteres do resultado. Um resultado XML atribuído a uma coluna de qualquer outro tipo de dados não pode ter mais de um nó, ou será gerado um erro. Se houver exatamente um nó, a coluna será definida como se estivesse atribuindo o valor cadeia de caracteres do nó (conforme definido para a função string no XPath 1.0) para o tipo de dados do PostgreSQL.

O valor cadeia de caracteres de um elemento XML é a concatenação, na ordem do documento, de todos os nós de texto contidos nesse elemento e seus descendentes. O valor cadeia de caracteres de um elemento sem nós de texto descendentes é uma cadeia de caracteres vazia (e não NULL). Quaisquer atributos xsi:nil são ignorados. Note que o nó text() contendo somente espaço em branco entre dois elementos não textuais é preservado, e que o espaço em branco inicial em um nó text() não é suprimido. Pode ser consultada a função string do XPath 1.0 para conhecer as regras que definem o valor cadeia de caracteres de outros tipos de nós XML e valores não-XML.

As regras de conversão apresentadas aqui não são exatamente as do padrão SQL, conforme discutido na Seção D.3.1.3.

Se a expressão de caminho retornar um conjunto de nós vazio para uma determinada linha (normalmente, quando não corresponde), a coluna será definida como NULL, a menos que seja especificada a default_expression; então será usado o valor resultante da avaliação desta expressão.

A default_expression, em vez de ser avaliada imediatamente quando xmltable é chamada, é avaliada sempre que há necessidade do valor padrão para a coluna. Se a expressão se qualificar como estável ou imutável, a avaliação repetida poderá ser ignorada, significando que podem ser usadas funções voláteis, como nextval, na default_expression.

As colunas podem ser marcadas como NOT NULL. Se a column_expression para uma coluna NOT NULL não corresponder a nada, e não houver nenhum DEFAULT ou default_expression que não seja avaliado como nulo, será relatado um erro.

Exemplos:

CREATE TABLE xmldata AS SELECT
xml $$
<ROWS>
  <ROW id="1">
    <COUNTRY_ID>AU</COUNTRY_ID>
    <COUNTRY_NAME>Australia</COUNTRY_NAME>
  </ROW>
  <ROW id="5">
    <COUNTRY_ID>JP</COUNTRY_ID>
    <COUNTRY_NAME>Japan</COUNTRY_NAME>
    <PREMIER_NAME>Shinzo Abe</PREMIER_NAME>
    <SIZE unit="sq_mi">145935</SIZE>
  </ROW>
  <ROW id="6">
    <COUNTRY_ID>SG</COUNTRY_ID>
    <COUNTRY_NAME>Singapore</COUNTRY_NAME>
    <SIZE unit="sq_km">697</SIZE>
  </ROW>
</ROWS>
$$ AS data;

SELECT xmltable.*
  FROM xmldata,
       XMLTABLE('//ROWS/ROW'
                PASSING data
                COLUMNS id int PATH '@id',
                        ordinality FOR ORDINALITY,
                        "COUNTRY_NAME" text,
                        country_id text PATH 'COUNTRY_ID',
                        size_sq_km float PATH 'SIZE[@unit = "sq_km"]',
                        size_other text PATH
                             'concat(SIZE[@unit!="sq_km"], " ", SIZE[@unit!="sq_km"]/@unit)',
                        premier_name text PATH 'PREMIER_NAME' DEFAULT 'not specified');

 id | ordinality | COUNTRY_NAME | country_id | size_sq_km |  size_other  | premier_name
----+------------+--------------+------------+------------+--------------+---------------
  1 |          1 | Australia    | AU         |            |              | not specified
  5 |          2 | Japan        | JP         |            | 145935 sq_mi | Shinzo Abe
  6 |          3 | Singapore    | SG         |        697 |              | not specified

O exemplo a seguir mostra a concatenação de vários nós text(), o uso do nome da coluna como filtro XPath, e o tratamento de espaços em branco, comentários XML e instruções de processamento:

CREATE TABLE xmlelements AS SELECT
xml $$
  <root>
   <element>  Hello<!-- xyxxz -->2a2<?aaaaa?> <!--x-->  bbb<x>xxx</x>CC  </element>
  </root>
$$ AS data;

SELECT xmltable.*
  FROM xmlelements, XMLTABLE('/root' PASSING data COLUMNS element text);

         element
-------------------------
   Hello2a2   bbbxxxCC

O exemplo a seguir mostra como pode ser usada a cláusula XMLNAMESPACES para especificar uma lista de espaços de nomes usados no documento XML, assim como nas expressões XPath:

WITH xmldata(data) AS (VALUES ('
<example xmlns="http://example.com/myns" xmlns:B="http://example.com/b">
 <item foo="1" B:bar="2"/>
 <item foo="3" B:bar="4"/>
 <item foo="4" B:bar="5"/>
</example>'::xml)
)
SELECT xmltable.*
  FROM XMLTABLE(XMLNAMESPACES('http://example.com/myns' AS x,
                              'http://example.com/b' AS "B"),
             '/x:example/x:item'
                PASSING (SELECT data FROM xmldata)
                COLUMNS foo int PATH '@foo',
                  bar int PATH '@B:bar');

 foo | bar
-----+-----
   1 |   2
   3 |   4
   4 |   5
(3 linhas)

9.15.4. Mapeando tabelas para XML #

As funções a seguir mapeiam o conteúdo de tabelas relacionais para valores XML. Estas funções podem ser consideradas como funcionalidade de exportação para XML:

table_to_xml ( tabela regclass, nulos boolean,
               tableforest boolean, targetns text ) → xml
query_to_xml ( consulta text, nulos boolean,
               tableforest boolean, targetns text ) → xml
cursor_to_xml ( cursor refcursor, contador integer, nulos boolean,
                tableforest boolean, targetns text ) → xml

A função table_to_xml mapeia o conteúdo da tabela especificada, passada como parâmetro tabela. O tipo de dados regclass aceita cadeias de caracteres identificando as tabelas usando a notação usual, incluindo a qualificação de esquema opcional e aspas (veja a Seção 8.19 para obter detalhes). A função query_to_xml executa a consulta cujo texto é passado pelo parâmetro consulta e mapeia o conjunto de resultados. A função cursor_to_xml traz o número indicado de linhas do cursor especificado pelo parâmetro cursor. Esta variante é recomendada se tiverem que ser mapeadas tabelas grandes, porque o valor do resultado é construído na memória por cada função.

Se tableforest for falso, o documento XML resultante terá a seguinte aparência:

<tablename>
  <row>
    <columnname1>data</columnname1>
    <columnname2>data</columnname2>
  </row>

  <row>
    ...
  </row>

  ...
</tablename>

Se tableforest for verdade, o resultado será um fragmento de conteúdo XML semelhante a este:

<tablename>
  <columnname1>data</columnname1>
  <columnname2>data</columnname2>
</tablename>

<tablename>
  ...
</tablename>

...

Se não estiver disponível nenhum nome de tabela, ou seja, ao mapear uma consulta ou um cursor, no primeiro formato será usada a cadeia de caracteres table, e row no segundo formato.

A escolha entre esses formatos fica a critério do usuário. O primeiro formato é um documento XML apropriado, que será importante em muitas aplicações. O segundo formato tende a ser mais útil na função cursor_to_xml se os valores do resultado forem reagrupados em um documento posteriormente. As funções para produzir conteúdo XML discutidas acima, em particular xmlelement, podem ser usadas para alterar os resultados a gosto.

Os valores de dados são mapeados da mesma forma descrita para a função xmlelement acima.

O parâmetro nulos determina se os valores nulos devem ser incluídos na saída. Caso seja verdade (true), os valores nulos nas colunas são representados como:

<columnname xsi:nil="true"/>

onde xsi é o prefixo do espaço de nomes XML para XML Schema Instance. Uma declaração de espaço de nomes apropriada será adicionada ao valor do resultado. Se for falso (false), as colunas contendo valores nulos são simplesmente omitidas da saída.

O parâmetro targetns determina o espaço de nomes XML desejado do resultado. Se não for desejado nenhum espaço de nomes específico, deve ser passada uma cadeia de caracteres vazia.

As seguintes funções retornam documentos XML Schema descrevendo os mapeamentos realizados pelas funções correspondentes acima:

table_to_xmlschema ( tabela regclass, nulos boolean,
                     tableforest boolean, targetns text ) → xml
query_to_xmlschema ( consulta text, nulos boolean,
                     tableforest boolean, targetns text ) → xml
cursor_to_xmlschema ( cursor refcursor, nulos boolean,
                      tableforest boolean, targetns text ) → xml

É essencial serem passados os mesmos parâmetros para obter mapeamentos de dados XML e documentos XML Schema correspondentes.

As funções a seguir produzem mapeamentos de dados XML e o esquema XML correspondente em um documento (ou floresta), juntos. Estas funções podem ser úteis quando se deseja resultados autocontidos e autodescritivos:

table_to_xml_and_xmlschema ( tabela regclass, nulos boolean,
                             tableforest boolean, targetns text ) → xml
query_to_xml_and_xmlschema ( consulta text, nulos boolean,
                             tableforest boolean, targetns text ) → xml

Além disso, estão disponíveis as seguintes funções para produzir mapeamentos análogos de esquemas inteiros ou de todo o banco de dados corrente:

schema_to_xml ( esquema name, nulos boolean,
                tableforest boolean, targetns text ) → xml
schema_to_xmlschema ( esquema name, nulos boolean,
                      tableforest boolean, targetns text ) → xml
schema_to_xml_and_xmlschema ( esquema name, nulos boolean,
                              tableforest boolean, targetns text ) → xml

database_to_xml ( nulos boolean,
                  tableforest boolean, targetns text ) → xml
database_to_xmlschema ( nulos boolean,
                        tableforest boolean, targetns text ) → xml
database_to_xml_and_xmlschema ( nulos boolean,
                                tableforest boolean, targetns text ) → xml

Estas funções ignoram tabelas que não podem ser lidas pelo usuário corrente. Além disso, as funções para todo o banco de dados ignoram os esquemas para os quais o usuário corrente não tem o privilégio USAGE (procura).

Note que potencialmente estas funções produzem muitos dados, que precisam ser acumulados na memória. Ao solicitar o mapeamento de conteúdo de grandes esquemas ou bancos de dados, pode valer a pena considerar mapear as tabelas em separado, possivelmente até mesmo por meio de um cursor.

O resultado do mapeamento de conteúdo de esquema se parece com:

<schemaname>

table1-mapping

table2-mapping

...

</schemaname>

onde o formato do mapeamento de tabela depende do parâmetro tableforest, conforme explicado acima.

O resultado do mapeamento de conteúdo de banco de dados se parece com:

<dbname>

<schema1name>
  ...
</schema1name>

<schema2name>
  ...
</schema2name>

...

</dbname>

onde o mapeamento do esquema é como mostrado acima.

Como exemplo de uso da saída produzida por estas funções, o Exemplo 9.2 mostra uma folha de estilo XSLT que converte a saída da função table_to_xml_and_xmlschema em um documento HTML contendo uma representação tabular dos dados da tabela. De maneira semelhante, os resultados destas funções podem ser convertidos em outros formatos baseados em XML.

Exemplo 9.2. Folha de estilo XSLT para conversão de saída SQL/XML para HTML

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns="http://www.w3.org/1999/xhtml"
>

  <xsl:output method="xml"
      doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
      doctype-public="-//W3C/DTD XHTML 1.0 Strict//EN"
      indent="yes"/>

  <xsl:template match="/*">
    <xsl:variable name="schema" select="//xsd:schema"/>
    <xsl:variable name="tabletypename"
                  select="$schema/xsd:element[@name=name(current())]/@type"/>
    <xsl:variable name="rowtypename"
                  select="$schema/xsd:complexType[@name=$tabletypename] ↵
                  /xsd:sequence/xsd:element[@name='row']/@type"/>

    <html>
      <head>
        <title><xsl:value-of select="name(current())"/></title>
      </head>
      <body>
        <table>
          <tr>
            <xsl:for-each select="$schema/xsd:complexType[@name=$rowtypename] ↵
                                  /xsd:sequence/xsd:element/@name">
              <th><xsl:value-of select="."/></th>
            </xsl:for-each>
          </tr>

          <xsl:for-each select="row">
            <tr>
              <xsl:for-each select="*">
                <td><xsl:value-of select="."/></td>
              </xsl:for-each>
            </tr>
          </xsl:for-each>
        </table>
      </body>
    </html>
  </xsl:template>

</xsl:stylesheet>



[72] Semelhante à função XMLCOMMENT do Oracle. (N. T.)

[73] Semelhante à função XMLCONCAT do Oracle. (N. T.)

[74] Semelhante à função XMLELEMENT do Oracle. (N. T.)

[75] No Oracle, o & vai fazer com o SQL*Plus peça para fornecer o valor para b, porque este será considerado como sendo um parâmetro da consulta. (N. T.)

[76] Semelhante à função XMLFOREST do Oracle. (N. T.)

[77] Semelhante à função XMLPI do Oracle. (N. T.)

[78] IBM – XMLRoot() function: A função XMLRoot() cria um valor XML fornecendo a versão e propriedades independentes nas informações da raiz XML (prólogo) de um valor especificado do tipo de dados XML. (N. T.)

[79] IBM – XML.standalone: O elemento standalone do XML define a existência de um DTD definido externamente. (N. T.)

[80] Semelhante à função XMLAGG do Oracle. (N. T.)

[81] Semelhante à função XMLEXISTS do Oracle. (N. T.)

[82] Um resultado contendo mais de um nó de elemento no nível superior, ou texto sem espaço em branco fora de um elemento, é um exemplo de forma de conteúdo. Um resultado XPath não pode ter nenhuma forma, por exemplo, se retornar um nó de atributo selecionado no elemento que o contém. Tal resultado será colocado em forma de conteúdo com cada nó não permitido substituído por seu valor cadeia de caracteres, conforme definido para a função string no XPath 1.0. string function.