PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 11.22 » Langage SQL » Fonctions et opérateurs » Fonctions XML

9.14. Fonctions XML

Les fonctions et expressions décrites dans cette section opèrent sur des valeurs de type xml. Lire la Section 8.13 pour des informations sur le type xml. Les expressions xmlparse et xmlserialize permettant de convertir vers ou à partir du type xml sont documentées ici, pas dans cette section.

L'utilisation d'un grand nombre de ces fonctions nécessite que PostgreSQL soit construit avec configure --with-libxml.

9.14.1. Produire un contenu XML

Un ensemble de fonctions et expressions de type fonction est disponible pour produire du contenu XML à partir de données SQL. En tant que telles, elles conviennent particulièrement bien pour formater les résultats de requêtes en XML à traiter dans les applications clientes.

9.14.1.1. xmlcomment

xmlcomment(text)
      

La fonction xmlcomment crée une valeur XML contenant un commentaire XML avec, comme contenu, le texte indiqué. Le texte ne peut pas contenir « -- » ou se terminer par un « - », de sorte que la construction résultante représente un commentaire XML valide. Si l'argument est NULL, le résultat est NULL.

Exemple :

SELECT xmlcomment('bonjour');

  xmlcomment
--------------
 <!--bonjour-->
       

9.14.1.2. xmlconcat

 xmlconcat(xml[, ...])
     

La fonction xmlconcat concatène une liste de valeurs XML individuelles pour créer une valeur simple contenant un fragment de contenu XML. Les valeurs NULL sont omises ; le résultat est NULL seulement s'il n'y a pas d'arguments non NULL.

Exemple :

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

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

Les déclarations XML, si elles sont présentes, sont combinées comme suit. Si toutes les valeurs en argument ont la même déclaration de version XML, cette version est utilisée dans le résultat. Sinon aucune version n'est utilisée. Si toutes les valeurs en argument ont la valeur de déclaration « standalone » à « yes », alors cette valeur est utilisée dans le résultat. Si toutes les valeurs en argument ont une valeur de déclaration « standalone » et qu'au moins l'une d'entre elles est « no », alors cette valeur est utilisée dans le résultat. Sinon le résultat n'a aucune déclaration « standalone ». Si le résultat nécessite une déclaration « standalone » sans déclaration de version, une déclaration de version 1.0 est utilisée, car le standard XML impose qu'une déclaration XML contienne une déclaration de version. Les déclarations d'encodage sont ignorées et supprimées dans tous les cas.

Exemple :

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

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

9.14.1.3. xmlelement

 xmlelement(name nom [, xmlattributes(valeur [AS nom_attribut] [, ... ])] [, contenu, ...])
      

L'expression xmlelement produit un élément XML avec le nom, les attributs et le contenu donnés.

Exemples :

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), 'cont', 'ent');

             xmlelement
-------------------------------------
 <foo bar="2007-01-26">content</foo>

Les noms d'élément et d'attribut qui ne sont pas des noms XML valides sont modifiés en remplaçant les caractères indésirables par une séquence _xHHHH_, où HHHH est le codage Unicode du caractère en notation hexadécimal. Par exemple :

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

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

Un nom explicite d'attribut n'a pas besoin d'être indiqué si la valeur de l'attribut est la référence d'une colonne, auquel cas le nom de la colonne est utilisé comme nom de l'attribut par défaut. Dans tous les autres cas, l'attribut doit avoir un nom explicite. Donc, cet exemple est valide :

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

Mais ceux-ci ne le sont pas :

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

Si le contenu de l'élément est précisé, il est formaté en fonction du type de données. Si le contenu est lui-même de type xml, des documents XML complexes peuvent être construits. Par exemple :

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

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

Le contenu des autres types est formaté avec des données XML valides. Cela signifie en particulier que les caractères <, >, et & sont convertis en entités. Les données binaires (type bytea) sont représentées dans un encodage base64 ou hexadécimal, suivant la configuration du paramètre xmlbinary. Le comportement particulier pour les types de données individuels devrait évoluer pour aligner les correspondances PostgreSQL avec ceux spécifiés dans SQL:2006 et ultérieurs, comme discuté dans Section D.3.1.3.

9.14.1.4. xmlforest

 xmlforest(contenu [AS nom] [, ...])
    

L'expression xmlforest produit un arbre XML (autrement dit une séquence) d'éléments utilisant les noms et le contenu donnés.

Exemples :

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_authid</table_name><column_name>rolname</column_name>
 <table_name>pg_authid</table_name><column_name>rolsuper</column_name>
 ...

Comme indiqué dans le second exemple, le nom de l'élément peut être omis si la valeur du contenu est une référence de colonne, auquel cas le nom de la colonne est utilisé par défaut. Sinon, un nom doit être indiqué.

Les noms d'éléments qui ne sont pas des noms XML valides sont échappés comme indiqué pour xmlelement ci-dessus. De façon similaire, les données de contenu sont échappées pour rendre le contenu XML valide, sauf s'il est déjà de type xml.

Les arbres XML ne sont pas des documents XML valides s'ils sont constitués de plus d'un élément. Il peut donc s'avérer utile d'emballer les expressions xmlforest dans xmlelement.

9.14.1.5. xmlpi

 xmlpi(name target [, content])
     

L'expression xmlpi crée une instruction de traitement XML. Le contenu, si présent, ne doit pas contenir la séquence de caractères ?>.

Exemple :

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

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

9.14.1.6. xmlroot

 xmlroot(xml, version text | no value [, standalone yes|no|no value])
      

L'expression xmlroot modifie les propriétés du nœud racine d'une valeur XML. Si une version est indiquée, elle remplace la valeur dans la déclaration de version du nœud racine. Si un paramètre « standalone » est spécifié, il remplace la valeur dans la déclaration « standalone » du nœud racine.

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.14.1.7. xmlagg

xmlagg(xml)
       

La fonction xmlagg est, à la différence des fonctions décrites ici, une fonction d'agrégat. Elle concatène les valeurs en entrée pour les passer en argument à la fonction d'agrégat, comme le fait la fonction xmlconcat, sauf que la concaténation survient entre les lignes plutôt qu'entre les expressions d'une même ligne. Voir Section 9.20 pour plus d'informations sur les fonctions d'agrégat.

Exemple :

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

Pour déterminer l'ordre de la concaténation, une clause ORDER BY peut être ajoutée à l'appel de l'agrégat comme décrit dans Section 4.2.7. Par exemple :

SELECT xmlagg(x ORDER BY y DESC) FROM test;
        xmlagg
----------------------
 <bar/><foo>abc</foo>

L'approche non standard suivante était recommandée dans les versions précédentes et peut toujours être utile dans certains cas particuliers :

SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab;
        xmlagg
----------------------
 <bar/><foo>abc</foo>

9.14.2. Prédicats XML

Les expressions décrites dans cette section vérifient les propriétés de valeurs du type xml.

9.14.2.1. IS DOCUMENT

xml IS DOCUMENT
        

L'expression IS DOCUMENT renvoie true si la valeur de l'argument XML est un document XML correct, false dans le cas contraire (c'est-à-dire qu'il s'agit d'un fragment de document) ou NULL si l'argument est NULL. Voir la Section 8.13 pour les différences entre documents et fragments de contenu.

9.14.2.2. IS NOT DOCUMENT

             xml IS NOT DOCUMENT
        

L'expression IS NOT DOCUMENT renvoie false si la valeur XML est un document XML propre, vrai s'il ne l'est pas (ie, c'est un fragment de document) et NULL si l'argument est NULL.

9.14.2.3. XMLEXISTS

XMLEXISTS(text PASSING [BY REF] xml [BY REF])
        

La fonction xmlexists évalue une expression XPath 1.0 (le premier argument), avec la valeur XML fournie comme élément de contexte. La fonction renvoie false si le résultat de cette évaluation ramène un ensemble de nœuds vide, et vrai pour toute autre valeur. La fonction renvoie NULL si un des arguments est NULL. Une valeur non NULL passée en tant qu'élément de contexte doit être un document XML, et non pas un fragment de contenu ou toute valeur non XML.

Exemple :

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

 xmlexists
------------
 t
(1 row)

Les clauses BY REF sont acceptées dans PostgreSQL mais sont ignorées, comme discuté dans Section D.3.2. Dans le standard SQL, la fonction xmlexists évalue une expression dans le langage XML Query, mais PostgreSQL autorise seulement une expression XPath 1.0 comme discuté dans Section D.3.1.

9.14.2.4. xml_is_well_formed

xml_is_well_formed(text)
xml_is_well_formed_document(text)
xml_is_well_formed_content(text)
         

Ces fonctions vérifient si la chaîne text est du XML bien formé et renvoient un résultat booléen. xml_is_well_formed_document vérifie si le document est bien formé alors que xml_is_well_formed_content vérifie si le contenu est bien formé. xml_is_well_formed est équivalent à xml_is_well_formed_document si le paramètre de configuration xmloption vaut DOCUMENT et est équivalent à xml_is_well_formed_content si le paramètre vaut CONTENT. Cela signifie que xml_is_well_formed est utile pour savoir si une conversion au type xml va réussir, alors que les deux autres sont utiles pour savoir si les variantes correspondantes de XMLPARSE vont réussir.

Exemples :

SET xmloption TO DOCUMENT;
SELECT xml_is_well_formed('<>');
 xml_is_well_formed
--------------------
 f
(1 row)

SELECT xml_is_well_formed('<abc/>');
 xml_is_well_formed
--------------------
 t
(1 row)

SET xmloption TO CONTENT;
SELECT xml_is_well_formed('abc');
 xml_is_well_formed
--------------------
 t
(1 row)

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

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

Le dernier exemple montre que les vérifications incluent les correspondances d'espace de noms.

9.14.3. Traiter du XML

Pour traiter les valeurs du type xml, PostgreSQL fournit les fonctions xpath et xpath_exists, qui évaluent les expressions XPath 1.0, ainsi que la fonction de table XMLTABLE.

9.14.3.1. xpath

xpath(xpath, xml [, nsarray])
          

La fonction xpath évalue l'expression XPath 1.0 xpath (une valeur de type text) avec la valeur XML xml. Elle renvoie un tableau de valeurs XML correspondant à l'ensemble de nœuds produits par une expression XPath. Si l'expression XPath renvoie une valeur scalaire à la place d'un ensemble de nœuds, un tableau à un seul élément est renvoyé.

Le deuxième argument doit être un document XML bien formé. En particulier, il doit avoir un seul élément de nœud racine.

Le troisième argument (optionnel) de la fonction est un tableau de correspondances de namespace. Ce tableau text doit avoir deux dimensions dont la seconde a une longueur 2 (en fait, c'est un tableau de tableaux à exactement deux éléments). Le premier élément de chaque entrée du tableau est le nom du namespace (alias), le second étant l'URI du namespace. Il n'est pas requis que les alias fournis dans ce tableau soient les mêmes que ceux utilisés dans le document XML (autrement dit, que ce soit dans le contexte du document XML ou dans celui de la fonction xpath, les alias ont une vue locale).

Exemple :

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

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

Pour gérer des namespaces par défaut (anonymes), faites ainsi :

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

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

9.14.3.2. xpath_exists

xpath_exists(xpath, xml [, nsarray])
           

La fonction xpath_exists est une forme spécialisée de la fonction xpath. Au lieu de renvoyer les valeurs XML individuelles qui satisfont l'expression XPath 1.0, cette fonction renvoie un booléen indiquant si la requête a été satisfaite ou non (plus spécifiquement si elle a produit d'autres valeurs qu'un ensemble de nœuds vide). Cette fonction est équivalente au prédicat standard XMLEXISTS, sauf qu'elle fonctionne aussi avec un argument de correspondance d'espace de nom.

Exemple :

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

9.14.3.3. xmltable

xmltable( [XMLNAMESPACES(namespace uri AS namespace name[, ...]), ]
          row_expression PASSING [BY REF] document_expression [BY REF]
          COLUMNS name { type [PATH column_expression] [DEFAULT default_expression] [NOT NULL | NULL]
                        | FOR ORDINALITY }
                   [, ...]
)
            

La fonction xmltable produit une table basée sur la valeur XML donnée, un filtre XPath pour extraire les lignes, ainsi qu'un ensemble de définitions de colonnes.

La clause facultative XMLNAMESPACES est une liste d'espaces de noms séparés par des virgules. Elle spécifie les espaces de noms utilisés dans le document et leurs alias. Une spécification d'espace de noms par défaut n'est pour le moment pas supportée.

L'argument requis row_expression est une expression XPath 1.0 qui est évaluée, passant document_expression comme élément de contexte, pour obtenir un ensemble de nœuds XML. Ces nœuds sont ce que xmltable transforme en lignes en sortie. Aucune ligne ne sera produite si document_expression est null ou si row_expression produit un ensemble de nœuds vide ou toute valeur autre qu'un ensemble de nœuds.

document_expression fournit l'élément de contexte pour row_expression. Ce doit être un document XML bien formé : les fragments/forêts ne sont pas acceptés. La clause BY REF est acceptée mais ignorée, comme discuté dans Section D.3.2. Dans le standard SQL, la fonction xmltable évalue les expressions dans le langage XML Query, mais PostgreSQL autorise seulement les expressions XPath 1.0, comme discuté dans Section D.3.1.

La clause obligatoire COLUMNS spécifie la liste de colonnes dans la table renvoyée. Chaque entrée décrit une seule colonne. Voir le résumé de la syntaxe ci-dessus pour le format. Le nom et le type sont obligatoires ; le chemin, valeur par défaut et la possibilité d'être NULL sont facultatifs.

Une colonne marquée FOR ORDINALITY sera remplie de numéros de ligne, commençant à 1, dans l'ordre des nœuds récupérés à partir de l'ensemble de nœuds résultat row_expression. Pas plus d'une colonne ne peut être marquée comme FOR ORDINALITY.

Note

XPath 1.0 ne spécifie pas un ordre pour les nœuds dans un ensemble de nœuds, donc un code qui se base sur un ordre particulier des résultats sera dépendant de l'implémentation. Les détails sont disponibles dans Section D.3.1.2.

Le column_expression pour une colonne est une expression XPath 1.0 qui est évaluée pour chaque ligne, avec le nœud actuel du résultat row_expression comme son élément de contexte, pour trouver la valeur de la colonne. Si aucun column_expression n'est fourni, alors le nom de la colonne est utilisé comme chemin implicite.

Si une expression XPath d'une colonne renvoie une valeur non XML (limitée à une chaîne, un booléen ou un double avec XPath 1.0) et que la colonne a un type PostgreSQL autre que xml, la colonne sera initialisée à la représentation textuelle de la valeuur pour le type PostgreSQL. Dans cette version, un booléen XPath ou un résultat double doit être explicitement converti en chaîne (autrement dit, la fonction string de XPath 1.0 autour de l'expression originelle de la colonne) ; PostgreSQL peut alors affecter avec succès la chaîne à une colonne résultante SQL de type booléen ou double. Ces règles de conversion diffèrent de celles du standard SQL, comme discuté dans Section D.3.1.3.

Dans cette version, les colonnes SQL résultantes du type xml ou les expressions colonne XPath s'évaluant en un type XML, quelque soit le type SQL de la colonne en sortie, sont gérées comme décrit dans Section D.3.2 ; le comportement change de façon significative dans PostgreSQL 12.

Si l'expression de chemin renvoie un ensemble de nœuds vide (généralement quand il n'y a pas de correspondance) pour une ligne donnée, la colonne sera configurée à la valeur NULL, sauf si default_expression est précisée ; alors la valeur résultante de l'évaluation de l'expression est utilisée.

Les colonnes peuvent être marquées comme NOT NULL. Si column_expression pour une colonne NOT NULL n'a pas de correspondance et qu'il n'y a pas de DEFAULT ou que default_expression est aussi évalué à NULL, une erreur est levée.

Une default_expression, plutôt qu'être évaluée immédiatement quand xmltable est appelée, est évaluée à chaque fois qu'une valeur par défaut est nécessaire pour la colonne. Si l'expression est qualifiée de stable ou immuable, l'évaluation répérée peut être évitée. Ceci signifie que vous pouvez utiliser utilement des fonctions volatiles comme nextval dans default_expression.

Exemples:

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

L'exemple suivant montre la concaténation de multiples nœuds text(), l'utilisation du nom de colonne comme un filtre XPath, ainsi que le traitement des espaces non significatfs, des commentaires XML et le traitement des instructions :

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   bbbCC
            

L'exemple suivant illustre comment la clause XMLNAMESPACES peut être utilisée pour spécifier l'espace de nom par défaut, et une liste d'espaces de nom supplémentaire utilisés aussi bien dans le document XML que dans les expression 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 rows)

9.14.4. Transformer les tables en XML

Les fonctions suivantes transforment le contenu de tables relationnelles en valeurs XML. Il s'agit en quelque sorte d'un export XML.

table_to_xml(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xml(query text, nulls boolean, tableforest boolean, targetns text)
cursor_to_xml(cursor refcursor, count int, nulls boolean,
              tableforest boolean, targetns text)

Le type en retour de ces fonctions est xml.

table_to_xml transforme le contenu de la table passée en argument (paramètre tbl). regclass accepte des chaînes identifiant les tables en utilisant la notation habituelle, incluant les qualifications possibles du schéma et les guillemets doubles. query_to_xml exécute la requête dont le texte est passé par le paramètre query et transforme le résultat. cursor_to_xml récupère le nombre indiqué de lignes à partir du curseur indiqué par le paramètre cursor. Cette variante est recommandée si la transformation se fait sur de grosses tables, car la valeur en résultat est construite en mémoire pour chaque fonction.

Si tableforest vaut false, alors le document XML résultant ressemble à ceci :

<tablename>
  <row>
    <columnname1>donnees</columnname1>
    <columnname2>donnees</columnname2>
  </row>

  <row>
    ...
  </row>

  ...
</tablename>

Si tableforest vaut true, le résultat est un fragment XML qui ressemble à ceci :

<tablename>
  <columnname1>donnees</columnname1>
  <columnname2>donnees</columnname2>
</tablename>

<tablename>
  ...
</tablename>

...

Si aucune table n'est disponible, c'est-à-dire lors d'une transformation à partir d'une requête ou d'un curseur, la chaîne table est utilisée dans le premier format, et la chaîne row dans le second.

Le choix entre ces formats dépend de l'utilisateur. Le premier format est un document XML correct, ce qui est important dans beaucoup d'applications. Le second format tend à être plus utile dans la fonction cursor_to_xml si les valeurs du résultat sont à rassembler plus tard dans un document. Les fonctions pour produire du contenu XML discutées ci-dessus, en particulier xmlelement, peuvent être utilisées pour modifier les résultats.

Les valeurs des données sont transformées de la même façon que ce qui est décrit ci-dessus pour la fonction xmlelement.

Le paramètre nulls détermine si les valeurs NULL doivent être incluses en sortie. À true, les valeurs NULL dans les colonnes sont représentées ainsi :

<columnname xsi:nil="true"/>

xsi est le préfixe de l'espace de noms XML pour l'instance XML Schema. Une déclaration appropriée d'un espace de noms est ajoutée à la valeur du résultat. À false, les colonnes contenant des valeurs NULL sont simplement omises de la sortie.

Le paramètre targetns indique l'espace de noms souhaité pour le résultat. Si aucun espace de noms particulier n'est demandé, une chaîne vide doit être passée.

Les fonctions suivantes renvoient des documents XML Schema décrivant la transformation réalisée par les fonctions ci-dessus.

table_to_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
cursor_to_xmlschema(cursor refcursor, nulls boolean, tableforest boolean, targetns text)
           

Il est essentiel que les mêmes paramètres soient passés pour obtenir les bonnes transformations de données XML et des documents XML Schema.

Les fonctions suivantes réalisent la transformation des données XML et du XML Schema correspondant en un seul document (ou arbre), liés ensemble. Elles sont utiles lorsque les résultats doivent être autocontenus et autodescriptifs.

table_to_xml_and_xmlschema(tbl regclass, nulls boolean, tableforest boolean, targetns text)
query_to_xml_and_xmlschema(query text, nulls boolean, tableforest boolean, targetns text)
           

De plus, les fonctions suivantes sont disponibles pour produire des transformations analogues de schémas complets ou de bases de données complètes.

schema_to_xml(schema name, nulls boolean, tableforest boolean, targetns text)
schema_to_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)
schema_to_xml_and_xmlschema(schema name, nulls boolean, tableforest boolean, targetns text)

database_to_xml(nulls boolean, tableforest boolean, targetns text)
database_to_xmlschema(nulls boolean, tableforest boolean, targetns text)
database_to_xml_and_xmlschema(nulls boolean, tableforest boolean, targetns text)
           

Elles peuvent produire beaucoup de données, qui sont construites en mémoire. Lors de transformations de gros schémas ou de grosses bases, il peut être utile de considérer la transformation séparée des tables, parfois même via un curseur.

Le résultat de la transformation du contenu d'un schéma ressemble à ceci :

<nomschema>

transformation-table1

transformation-table2

...

</nomschema>

où le format de transformation d'une table dépend du paramètre tableforest comme expliqué ci-dessus.

Le résultat de la transformation du contenu d'une base ressemble à ceci :

<nombase>

<nomschema1>
  ...
</nomschema1>

<nomschema2>
  ...
</nomschema2>

...

</nombase>

avec une transformation du schéma identique à celle indiquée ci-dessus.

En exemple de l'utilisation de la sortie produite par ces fonctions, la Exemple 9.1 montre une feuille de style XSLT qui convertit la sortie de table_to_xml_and_xmlschema en un document HTML contenant un affichage en tableau des données de la table. D'une façon similaire, les données en résultat de ces fonctions peuvent être converties dans d'autres formats basés sur le XML.

Exemple 9.1. Feuille de style XSLT pour convertir du SQL/XML en 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>