Postgres JSONb vers XML avec tag_name et tag_value

Oct 11 2020

Je suis nouveau dans les fonctions XML de Postgres. J'ai un tableau comme ci-dessous:

id  (VARCHAR) | field1 (text) | attributes  (jsonb)     
--------------+---------------+----------------------------------

 123          |   a           |   {"age": "1", "place": "TX"}                 
 456          |   b           |   {"age": "2", "name": "abcdef"}     
 789          |               |       
 098          |   c           |   {"name": "gefd"}     

Voudrais le convertir en:

 <Company id="123" field="a">
      <CompanyTag tagName="age" tagValue="1"/>
      <CompanyTag tagName="place" tagValue="TX"/>
 </Company>
 <Company id="456" field="b">
      <CompanyTag tagName="age" tagValue="2"/>
      <CompanyTag tagName="name" tagValue="abcdef"/>
 </Company>
 <Company id="789"/>
  <Company id="098" field="c">
      <CompanyTag tagName="name" tagValue="gefd"/>
 </Company>

A été capable de convertir facilement les deux premières colonnes en utilisant ci-dessous, mais le JSONb a la partie la plus difficile:

#SELECT xmlelement(name Company, xmlattributes(id as id, field1 as field)) from comp_emp;;
 <Company id="123" field="a"/>
 <Company id="456" field="b"/>
 <Company id="789"/>
 <Company id="098" field="c"/>

Veuillez me guider dans la bonne direction.

Réponses

2 Bergi Oct 11 2020 at 06:09

En me basant sur la solution de @Georges Martin, je n'utiliserais pas une jointure latérale et une clause de regroupement, mais plutôt une sous-requête imbriquée:

SELECT XMLELEMENT(
  NAME "Company", 
  XMLATTRIBUTES(id AS id, field1 AS field), 
  (SELECT XMLAGG(
    XMLELEMENT(
      NAME "companyTag", 
      XMLATTRIBUTES(
        attr.key AS "tagName", 
        attr.value AS "tagValue"
      )
    )
  ) FROM JSONB_EACH_TEXT(attributes) AS attr)
) FROM comp_emp;

( démo en ligne )

1 GeorgesMartin Oct 11 2020 at 05:53

C'est une solution partielle car j'ai oublié la field1colonne mais ceci:

SELECT 
 XMLELEMENT(
  NAME "Company", 
  XMLATTRIBUTES(id AS id), 
  XMLAGG(
   XMLELEMENT(
    NAME "CompanyTag", 
    XMLATTRIBUTES(
     (attr).key AS "tagName", 
     (attr).value AS "tagValue"
    )
   )
  )
 ) 
FROM (
 SELECT 
  id, JSONB_EACH_TEXT(attributes) AS attr 
 FROM comp_emp
) AS sub 
GROUP BY id;

retourne déjà:

<Company id="098">
  <CompanyTag tagName="name" tagValue="gefd"/>
</Company>
<Company id="456">
  <CompanyTag tagName="age" tagValue="2"/>
  <CompanyTag tagName="name" tagValue="abcdef"/>
</Company>
<Company id="123">
  <CompanyTag tagName="age" tagValue="1"/>
  <CompanyTag tagName="place" tagValue="TX"/>
</Company>