Documentation PostgreSQL 14.22 » Langage SQL » Fonctions et opérateurs » Fonctions XML

Précédent | Niveau supérieur | Suivant
9.14. Fonctions UUID | Sommaire | 9.16. Fonctions et opérateurs JSON

## 9.15. Fonctions XML

Les fonctions et les expressions décrites dans cette section opèrent sur des valeurs de type `xml`. Voir Section 8.13 pour des informations sur le type `xml`. Les expressions `xmlparse` et `xmlserialize` pour convertir vers ou à partir d'un type `xml` sont documentées ici, et non pas dans cette section.

L'utilisation de la plupart de ces fonctions requiert que PostgreSQL soit construit avec `configure --with-libxml`.

### 9.15.1. Produire du contenu XML

Un ensemble de fonctions et d'expressions est disponible pour produire du contenu XML à partir de données SQL. Elles sont donc tout particulièrement intéressantes pour formater le résultat de requêtes en des documents XML pour un traitement dans des applications clientes.

#### 9.15.1.1. `xmlcomment`

    xmlcomment ( text ) → xml

La fonction `xmlcomment` crée une valeur XML contenant un commentaire XML avec le texte spécifié comme contenu. Le texte ne peut pas contenir « `--` » ou se terminer avec un « `-` », sinon la construction résultante serait un commentaire XML invalide. Si l'argument est NULL, le résultat est NULL.

Example:

    SELECT xmlcomment('hello');

      xmlcomment
    --------------
     <!--hello-->

#### 9.15.1.2. `xmlconcat`

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

La fonction `xmlconcat` concatène une liste de valeurs XML individuelles pour créer une seule valeur contenant un fragment de contenu XML. Les valeurs NULL sont omises. Le résultat est NULL si tous les arguments sont NULL.

Example:

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

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

Les déclarations XML sont combinées ainsi. Si toutes les valeurs des arguments ont la même déclaration de version XML, cette version est utilisée comme résultat. Sinon, aucune version n'est utilisée. Si toutes les valeurs des arguments ont une valeur de déclarationl standalone à « yes », alors cette valeur est utilisée dans le résultat. Si toutes les valeurs d'agument ont une valeur de déclaration standalone et qu'au moins une de ces valeurs est « no », alors cette valeur est utilisée dans le résultat. Dans tous les autres cas, le résultat n'aura pas de déclaration standalone. Si le résultat nécessite une déclaration standalone, mais par de déclaration version, une déclaration version 1.0 sera utilisée car XML requiert qu'une déclaration XML contiennent une déclaration de version. Les déclarations d'encodage sont ignorés et supprimés dans tous les cas.

Example:

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

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

#### 9.15.1.3. `xmlelement`

    xmlelement ( NAME name [, XMLATTRIBUTES ( attvalue [ AS attname ] [, ...] ) ] [, content [, ...]] ) → xml

L'expression `xmlelement` produit un élément XML avec le nom, les attributs et le contenu donnés. Les éléments `name` et `attname` affichés dans la syntaxe sont de simples identifiants, et non pas des valeurs. Les éléments `attvalue` et `content` sont des expressions, qui peuvent être de n'importe quel type de données PostgreSQL. Les arguments dans `XMLATTRIBUTES` génèrent les attributs de l'élément XML ; les valeurs `content` sont concaténées pour former son contenu.

Examples:

    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éments et d'attributs qui ne sont pas des noms XML valides sont échappés en remplaçant les caractères problématiques par la séquence `_x`HHHH`_`, où `HHHH` est le point code Unicode du caractère dans sa notation hexadécimale. Par exemple :

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

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

Un nom d'attribut explicite n'a pas besoin d'être spécifié si la valeur de l'attribut est une référence de colonne, auquel cas le nom de la colonne sera utilisé comme nom d'attribut par défaut. Dans les autres cas, l'attribut doit se voir donner 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 ces exemples ne le sont pas :

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

Le contenu d'un élément, si indiqué, sera formaté suivant ton 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 sera formaté en une donnée caractère XML valide. Ceci signifie en particulier que les caractères <, >, et & seront convertis en entités. Les données binaires (type de données `bytea`) seront représentées dans un encodage base64 ou hex, 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.15.1.4. `xmlforest`

    xmlforest ( content [ AS name ] [, ...] ) → xml

L'expression `xmlforest` produit une forêt (séquence) XML d'éléments en utilisant les noms et le contenu donnés. Quant à `xmlelement`, chaque `name` doit être un simple identifiant, alors que les expressions `content` peuvent avoir n'importe quel type de données.

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 deuxième exemple, le nom de l'élément peut être omis si la valeur contenue est une référence de colonne, auquel cas le nom de l'élément est utilisé par défaut. Sinon un nom doit être spécifié.

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

Notez que les forêts XML ne sont pas des documents XML valides si elles consistent de plus d'un élément, donc il pourrait être utile d'envelopper les expressions `xmlforest` dans `xmlelement`.

#### 9.15.1.5. `xmlpi`

    xmlpi ( NAME name [, content ] ) → xml

L'instruction `xmlpi` crée une instruction de traitement XML. Quant à `xmlelement`, `name` doit être un simple identifiant, alors que l'expression `content` peut contenir tout type de données. Si présent, `content` ne doit pas contenir la séquence de caractères `?>`.

Exemple :

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

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

#### 9.15.1.6. `xmlroot`

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

L'expression `xmlroot` altère les propriétés du nœud racine d'une valeur XML. Si une version est spécifié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.15.1.7. `xmlagg`

    xmlagg ( xml ) → xml

La fonction `xmlagg` est, contrairement aux autres fonctions décrites ici, une fonction d'agrégat. Elle concatène les valeurs en entrée à l'appel de fonction d'agrégat, tout comme le fait `xmlconcat`, sauf que la concaténation survient au travers des lignes plutôt qu'au travers des expressions dans une seule ligne. Voir Section 9.21 pour l'information supplémentaire 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é à 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 recommendée dans les versions précédentes et pourrait toujours être utile dans des cas spécifiques :

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

### 9.15.2. Prédicats XML

Les expressions décrites dans cette section vérifient les propriétés des valeurs `xml`.

#### 9.15.2.1. `IS DOCUMENT`

    xml IS DOCUMENT → boolean

L'expression `IS DOCUMENT` renvoie true si la valeur de l'argument XML est un document XML propre, false si elle ne l'est pas (c'est-à-dire un fragment de contenu), ou null si l'argument est null. Voir Section 8.13 sur la différence entre les documents et les fragments de contenu.

#### 9.15.2.2. `IS NOT DOCUMENT`

    xml IS NOT DOCUMENT → boolean

L'expression `IS NOT DOCUMENT` renvoie false si la valeur de l'argument XML est un document XML propre, true si elle ne l'est pas (c'est-à-dire un fragment de contenu), ou null si l'argument est null.

#### 9.15.2.3. `XMLEXISTS`

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

La fonction `xmlexists` évalue une expression XPath 1.0 (le premier argument), avec la valeur XML passée comme son élément de contexte. La fonction renvoie false si le résultat de cette évaluation renvoie un ensemble de nœud vide, true si elle renvoie toute autre valeur. La fonction renvoie null si un argument vaut null. Une valeur non null passée comme élément de contexte doit être un document XML, et non pas un fragment de contenu ou une valeur non XML.

Example:

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

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

Les clauses `BY REF` et `BY VALUE` sont acceptées dans PostgreSQL, mais sont ignorées comme indiqué 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.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

Ces fonctions vérifient si une chaîne de type `text` représente un XML bien formé, renvoyant 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 que c'est une contenu bien formé. `xml_is_well_formed` fait le premier si le paramètre de configuration xmloption est configuré à `DOCUMENT`, et le deuxième s'il est configuré à `CONTENT`. Ceci signifie que `xml_is_well_formed` est utile pour voir si une simple conversion vers le type `xml` réussira, alors que les deux autres fonctions sont utiles pour voir si les variantes correspondantes de `XMLPARSE` réussira.

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 une vérification de correspondance sur les espaces de nom.

### 9.15.3. Traiter du XML

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

#### 9.15.3.1. `xpath`

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

La fonction `xpath` évalue l'expression XPath 1.0 indiquée dans `xpath` (sous la forme d'une donnée de type text) avec la valeur XML de type `xml`. Elle renvoie des valeurs XML correspondant à l'ensemble de nœuds produits par l'expression XPath. Si l'expression XPath renvoie une valeur scalaire plutôt qu'un ensemble de nœuds, un tableau d'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 d'espaces de nom. Ce tableau devrait être un tableau de `text` à deux dimensions avec la longueur du deuxième axe égale à 2 (cela devrait être un tableau de tableaux, chacun des deux contenant exactement deux éléments). Le premier élément de chaque entrée de tableau est le nom de l'espace de noms (alias), le second est l'URI de l'espace de noms. Il n'est pas requis que les alias fournis dans ce tableau soient identiques à ceux utilisés dans le document XML lui-même (en d'autres termes, dans le document XML et dans le contexte de la fonction `xpath` function context, les alias sont local).

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 les espaces de noms par défaut (anonymes), faire ceci :

    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.15.3.2. `xpath_exists`

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

La fonction `xpath_exists` est une forme spécialisée de la fonction `xpath`. Au lieu de renvoyer les valeurs XML individuelles satisfaisant l'expression XPath 1.0, cette fonction renvoie un booléen indiquant si la requête était satisfaite ou non (spécifiquement s'il produit une valeur autre qu'un ensemble vide de nœuds). Cette fonction est équivalente au prédicat `XMLEXISTS`, sauf qu'il offre aussi du support pour l'argument de correspondance d'espaces de noms.

Example:

    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.15.3.3. `xmltable`

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

L'expression `xmltable` produit une table basée sur une valeur XML, un filtre XPath pour extraire les lignes et un ensemble de définition de colonnes. Bien que cela ressemble syntaxiquement à une fonction, il peut aussi apparaître comme une table dans la clause `FROM` de la requête.

La clause `XMLNAMESPACES` optionnelle donne une liste, séparée par des virgules, des définitions d'espaces de nom, où chaque `namespace_uri` est une expression `text` et chaque `namespace_name` est un simple identifiant. Elle spécifie les espaces de nom XML utilisés dans le document et leur alias. La spécification d'un espace de nom par défaut n'est actuellement pas supportée.

L'argument requis `row_expression` est une expression XPath 1.0 (donné sous la forme d'un `text`) qui est évaluée, passant la valeur XML `document_expression` sous la forme d'un élément de contexte, pour obtenir un ensemble de nœuds XML. Ces nœuds sont ce que `xmltable` transforme des lignes en sortie. Aucune ligne ne sera produite si `document_expression` est NULL, ou si `row_expression` produit un ensemble vide de nœuds ou tout autre valeur qu'un ensemble de nœuds.

`document_expression` fournit l'élément de contexte pour `row_expression`. Cela doit être un document XML bien formé ; les fragments/forêts ne sont pas acceptés. Les clauses `BY REF` et `BY VALUE` sont acceptées mais ignorées, comme discuté dans Section D.3.2.

Dans le standard SQL, la fonction `xmltable` évalue des expressions dans le langage XML Query, mais PostgreSQL autorise seulement les expressions XPath 1.0, comme discutées dans Section D.3.1.

La clause requise `COLUMNS` spécifie les colonnes produites dans la table en sortie. Voir le résumé de la syntaxe ci-dessus pour le format. Un nom est requis pour chaque colonne, comme l'est un type de données (sauf si `FOR ORDINALITY` est spécifié, auquel cas le type `integer` est implicite). Les clauses de chemin, de valeur par défaut et de nullabilité sont optionnelles.

Une colonne marquée `FOR ORDINALITY` sera peuplée avec les numéros de lignes, commençant par 1, dans l'ordre des nœuds récupérés à partir de l'ensemble de nœuds résultats de `row_expression`. Au plus une colonne sera marquée `FOR ORDINALITY`.

### Note

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

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

Si une expression XPath de colonne renvoie une valeur non XML (qui est limitée à une chaîne, un booléen ou un double en XPath 1.0) et la colonne a un type type autre que `xml`, la colonne sera configurée ainsi en affectant la représentation textuelle de la valeur vers le type PostgreSQL. (Si la valeur est un booléen, sa représentation textuelle est comprise comme `1` ou `0` si la catégorie du type de la colonne en sortie est numérique, sinon `true` ou `false`.)

Si l'expression XPath d'une colonne renvoie un ensemble non vide de nœuds XML et si le type PostgreSQL de la colonne est `xml`, la colonne sera affectée au résultat exact de l'expression s'il est de forme document ou contenu. [8]

Un résultat non XML affecté à une colonne `xml` en sortie produit du contenu, un nœud texte simple avec la valeur chaîne du résultat. Un résultat XML affecté à une colonne de tout autre type pourrait ne pas avoir plus d'un nœud, sinon une erreur est levée. S'il y a exactement un nœud, la colonne sera configurée d'après son affectation de la valeur textuelle du nœud (comme défini pour la fonction `string` XPath 1.0) du type PostgreSQL.

The string value of an XML element is the concatenation, in document order, of all text nodes contained in that element and its descendants. The string value of an element with no descendant text nodes is an empty string (not `NULL`). Any `xsi:nil` attributes are ignored. Note that the whitespace-only `text()` node between two non-text elements is preserved, and that leading whitespace on a `text()` node is not flattened. The XPath 1.0 `string` function may be consulted for the rules defining the string value of other XML node types and non-XML values.

Les règles de conversion présentées ici ne sont pas exactement ceux du standard SQL, comme discuté dans Section D.3.1.3.

Si l'expression de chemin renvoie un ensemble vide de nœuds (typiquement quand cela ne correspond pas) pour une ligne donnée, la colonne sera configurée à `NULL`, sauf si une `default_expression` est indiquée ; alors la valeur résultant de l'évaluation d'une expression est utilisé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 qualifie comme stable ou immuable, l'évaluation de répétition peut être ignorée. Ceci signifie que vous pouvez utiliser utilement les fonctions volatiles comme `nextval` dans `default_expression`.

Les colonnes peuvent être marquées `NOT NULL`. Si `column_expression` pour une colonne `NOT NULL` ne correspond à rien et qu'il n'y a ni valeur par défaut (`DEFAULT`) ni `default_expression`, elle s'évalue à NULL, une erreur est rapportée.

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 une concaténation de plusieurs nœuds text(), une utilisation du nom de colonne en tant que filtre XPath, et le traitement des espaces blancs, 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   bbbxxxCC

L'exemple suivant illustre comment la clause `XMLNAMESPACES` peut être utilisé pour spécifier une liste d'espaces de noms utilisée dans le document XML ainsi que dans les expressions 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.15.4. Correspondances tables et XML

Les fonctions suivantes font correspondre le contenu des tables relationnelles aux valeurs XML. Elles peuvent être vues comme une fonctionnalité d'export du XML :

    table_to_xml ( table regclass, nulls boolean,
                   tableforest boolean, targetns text ) → xml
    query_to_xml ( query text, nulls boolean,
                   tableforest boolean, targetns text ) → xml
    cursor_to_xml ( cursor refcursor, count integer, nulls boolean,
                    tableforest boolean, targetns text ) → xml

`table_to_xml` fait correspondre le contenu de la table nommée, passée en paramètre sous le nom de `table`. Le type `regclass` accepte les chaînes identifiant les tables en utilisant la notation habituelle incluant une qualification optionnelle avec le nom du schéma et les guillemets doubles (voir Section 8.19 pour les détails). `query_to_xml` exécute la requête dont le texte est passé avec le paramètre `query` et fait la correspondance avec 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 des tables volumineuses sont utilisées car la valeur de résultat est construire en mémoire par chaque fonction.

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

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

      <row>
        ...
      </row>

      ...
    </tablename>

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

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

    <tablename>
      ...
    </tablename>

    ...

Si aucun nom de table n'est disponible, par exemple pour une requête ou un curseur, la chaîne indiquée pour `table` est utilisée pour le premier format, et `row` pour le deuxième format.

Le choix entre ces formats dépend de l'utilisateur. Le premier format est un document XML propre, qui sera important pour de nombreuses applications. Le deuxième format tend à être plus utile dans la fonction `cursor_to_xml` si les valeurs du résultat sont à réassembler en un seul document plus tard. 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 projetées de la même façon que décrit pour la fonction `xmlelement` ci-dessus.

Le paramètre `nulls` détermine si les valeurs NULL doivent être incluses dans la sortie. Si true, les valeurs NULL dans les colonnes sont représentées sous cette forme :

    <columnname xsi:nil="true"/>

où `xsi` est le préfixe de l'espace de nom XML pour XML Schema Instance. Une déclaration appropriée d'espace de nom sera ajoutée à la valeur résultat. Si false, les colonnes contenant des valeurs NULL seront simplement omises dans la sortie.

Le paramètre `targetns` spécifie l'espace de nom XML désiré pour le résultat. Si aucun espace de nom n'est souhaité, une chaîne vide doit être passée.

Les fonctions suivantes renvoient les documents XML Schema décrivant les correspondances réalisées par les fonctions ci-dessus :

    table_to_xmlschema ( table regclass, nulls boolean,
                         tableforest boolean, targetns text ) → xml
    query_to_xmlschema ( query text, nulls boolean,
                         tableforest boolean, targetns text ) → xml
    cursor_to_xmlschema ( cursor refcursor, nulls boolean,
                          tableforest boolean, targetns text ) → xml

Il est essentiel que les mêmes paramètres soient passés dans l'ordre pour obtenir les projections de données XML correspondantes et les documents XML Schema.

Les fonctions suivantes produisent les projections de données XML correspondantes et les documents XML Schema dans un document (ou forêt), liés ensemble. Elles peuvent être utiles lorsque des résultats auto contenus et auto descriptifs sont désirés :

    table_to_xml_and_xmlschema ( table regclass, nulls boolean,
                                 tableforest boolean, targetns text ) → xml
    query_to_xml_and_xmlschema ( query text, nulls boolean,
                                 tableforest boolean, targetns text ) → xml

De plus, les fonctions suivantes sont disponibles pour produire des projections analogues de schémas entiers ou de la base de donnée courante entière :

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

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

Ces fonctions ignorent les tables qui ne sont pas lisibles par l'utilisateur courant. Les fonctions sur la base entière ignorent en plus les schémas pour lesquels l'utilisateur actuel ne dispose pas du droit `USAGE`.

Notez qu'elles peuvent produire beaucoup de données, entièrement stockées en mémoire. Lors de demandes de création de contenu à partir de gros schémas ou de base, il peut être intéressant de réfléchir à traiter les tables séparément, potentiellement même via un curseur.

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

    <schemaname>

    table1-mapping

    table2-mapping

    ...

    </schemaname>

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

Le résultat d'un contenu de base ressemble à ceci :

    <dbname>

    <schema1name>
      ...
    </schema1name>

    <schema2name>
      ...
    </schema2name>

    ...

    </dbname>

où la correspondance de schéma est indiquée ci-dessus.

Comme exemple d'utilisation de la sortie de ces fonctions, Exemple 9.1 montre une feuille de style XSLT qui convertit la sortie de `table_to_xml_and_xmlschema` en un document HTML contenant une représentation en tableau des données de la table. D'une façon similaire, le résultat de ces fonctions peut être converti en d'autres formats basés sur le XML.

Exemple 9.1. Feuille de style XSLT pour convertir un résultat 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>

[8] Un résultat contenant plus d'un nœud élément au niveau haut ou du texte sans espace blanc à l'extérieur d'un élément, est un exemple de forme contenu. Un résultat XPath peut être de toute forme, par exemple s'il renvoie un nœud attribut sélectionné à partir de l'élément qui le contient. Un tel résultat sera placé dans sa forme contenu avec chacun des nœuds non autorisés replacés par sa valeur de chaîne de texte, comme définis pour la fonction `string` XPath 1.0.