IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

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, « Type XML » pour des informations sur le type xml. Les expressions xmlparse et xmlserialize permettant de convertir vers ou à partir du type xml ne sont pas reprises ici. L'utilisation d'un grand nombre de ces fonctions nécessite que l'installation soit construite 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 types de données SQL et PostgreSQL avec la spécification de XML Schema, auquel cas une description plus précise sera ajoutée.

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'aggrégat. Elle concatène les valeurs en entrée pour les passer en argument à la fonction d'aggré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, « Fonctions d'agrégat » 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, « Expressions d'agrégat ». Par exemple :

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

L'approche non standard suivante était recommendée dans les versions précédentes et peut toujours être utiles 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, « Type XML » pour les différences entre documents et fragments de contenu.

9.14.2.2. XMLEXISTS

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

La fonction xmlexists renvoie true si l'expression XPath dans le premier argument renvoie des nœuds. Elle renvoie faux sinon. (Si un des arguments est NULL, le résultat est NULL.)

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 n'ont pas d'effet dans PostgreSQL mais sont autorisées pour se conformer au standard SQL et pour la compatibilité avec les autres implémentations. D'après le standard SQL, le premier BY REF est requis, le second est optionel. De plus, notez que le standard SQL spécifie que la construction xmlexists prend une expression XQuery en premier argument mais PostgreSQL supporte actuellement seulement XPath, qui est un sous-ensemble de XQuery.

9.14.2.3. 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 monte 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 xpath (une valeur de type text) avec la valeur XML xml. Elle renvoie un tableau de valeurs XML correspondant à l'ensemble de nœuds produit par une expression XPath. Si l'expression XPath renvoit une valeur scalaire à la place d'un ensemble de nœuds, un tableau à un seul élément est renvoyé.

Le second 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 XPath, cette fonction renvoie un booléen indiquant si la requête a été satisfaite ou non. Cette fonction est équivalent au prédicat standard XMLEXISTS, sauf qu'il 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 ligne ainsi qu'un ensemble de définition de colonnes facultatif.

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

L'argument obligatoire row_expression est une expression XPath qui est évaluée sur le document XML fourni pour obtenir une séquence ordonnée de nœuds XML. Cette séquence est ce que xmltable transforme en lignes.

document_expression fournit le document XML sur lequel travailler. La clause BY REF n'a pas d'effet dans PostgreSQL, mais est autorisée pour se conformer à la norme SQL et pour la compatibilité avec les autres implémentations. L'argument doit être un document XML valide; les fragments/forêts ne sont pas acceptés.

La clause obligatoire COLUMNS spécifie la liste de dolonnes dans la table renvoyée. Si la clause COLUMNS n'est pas précisée, les colonnes dans l'ensemble de résultat contient une seule colonne de type xml contenant les données qui correspondent à row_expression. Si COLUMNS est spécifié, 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 correspondant à l'ordre dans lequel les lignes en sortie apparaissent dans le document XML original fourni en entrée. Pas plus d'une colonne ne peut être marquée comme FOR ORDINALITY.

column_expression pour une colonne est une expression XPath qui est évaluée pour chaque ligne, relative au résultat de row_expression, pour trouver la valeur de la colonne. Si column_expression n'est pas précisé, alors le nom de la colonne est utilisé comme un chemin implicite.

Si l'expression XPath d'une colonne retourne plusieurs éléments, une erreur est levée. Si l'expression correspondant à un tag vide, le résultat est une chaîne vide (pas NULL). Tout xsi:nil attribut est ignoré.

Le corps du texte du XML qui correspond à column_expression est utilisé pour la valeur de la colonne. Plusieurs nœuds text() au sein d'un élément sont concaténés dans l'ordre. Chaque élément enfant, selon les instructions, et les commentaires sont ignorés, mais les contenus des textes des éléments enfants sont concaténés au résultat. Veuillez noter que le nœud text() d'espaces non significatifs entre deux élément non texte est préservé, et que l'espace non significatif de départ d'un nœud text() n'est pas aplati.

Si l'expression de chemin ne donne pas de correspondance pour une ligne mais que default_expression est spécifié, la valeur résultant de l'évaluation de cette expression est utilisée. Si la clause DEFAULT n'est pas utilisée pour la colonne, le champ sera positionné à NULL. Il est possible pour default_expression de référencer la valeur de colonnes en sortie qui apparaissent avant elle dans la liste de colonne, et donc la valeur par défaut d'une colonne peut être basée sur la valeur d'une autre colonne.

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.

Contrairement aux fonctions normales de PostgreSQL, column_expression et default_expression ne sont pas évaluées vers une simple valeur avant d'appeler la fonction. column_expression est normalement évaluée une seule fois par ligne en entrée, et default_expression est évalué chaque fois qu'une valeur par défaut est nécessaire pour un champ. Si l'expression est qualifiée comme stable ou immuable alors les évaluations répétées peuvent être évitées. Dans les fait xmltable se comporte plus comme une sous-requête que comme un appel de fonction. Cela veut dire que vous pouvez utiliser des fonctions volatiles comme nextval dans default_expression de manière utile, et que column_expression peut dépendre d'autres partie du document XML.

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 nom 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 auto-contenus et auto-descriptifs.

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 Figure 9.1, « Feuille de style XSLT pour convertir du SQL/XML en HTML » 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.

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