I am trying to use Postgres to generate a single XML document as output.
Assume that I have a single relation, customers
. It has the columns id
, name
and email
.
I want XML that looks like this:
<customers>
<customer>
<id>0<id/>
<name>Customer 1<name/>
<email>customer1@gmail.com<email/>
<customer/>
<customer>
<id>1<id/>
<name>Customer 2<name/>
<email>customer2@gmail.com<email/>
<customer/>
<!--and so on-->
<customers/>
So far, I can generate the XML for each customer, like this:
SELECT XMLELEMENT(NAME customer,
XMLELEMENT(NAME 'id', "id"),
XMLELEMENT(NAME 'name', name),
XMLELEMENT(NAME email, email))
FROM customers;
However, concatenating this into a single XML document does not work. I have tried:
SELECT XMLELEMENT(NAME customers, XMLCONCAT((
SELECT XMLELEMENT(NAME customer,
XMLELEMENT(NAME 'id', "id"),
XMLELEMENT(NAME 'name', name),
XMLELEMENT(NAME email, email))
FROM customers;
)));
However, this fails with the message more than one row returned by a subquery used as an expression
.
There are many ways of achieving this. An easy approach is to fetch the XML elements you want in aCTE
and aggregate them with xmlagg
Sample Data
CREATE TEMPORARY TABLE customers (id int, name text, email text);
INSERT INTO customers VALUES
(0,'Customer 1','customer1@gmail.com'),
(0,'Customer 2','customer2@gmail.com');
Query
WITH j AS (
SELECT
XMLELEMENT(NAME customer,
XMLELEMENT(NAME id, id),
XMLELEMENT(NAME name, name),
XMLELEMENT(NAME email, email)) AS customers
FROM customers)
SELECT
XMLELEMENT(NAME customers, xmlagg(customers))
FROM j;
------------
<customers>
<customer>
<id>0</id>
<name>Customer 1</name>
<email>customer1@gmail.com</email>
</customer>
<customer>
<id>0</id>
<name>Customer 2</name>
<email>customer2@gmail.com</email>
</customer>
</customers>
Another alternative is to use a subquery
SELECT
XMLELEMENT(NAME customers, xmlagg((customers)))
FROM (SELECT
XMLELEMENT(NAME customer,
XMLELEMENT(NAME id, id),
XMLELEMENT(NAME name, name),
XMLELEMENT(NAME email, email)) AS customers
FROM customers) j;
Add LIMIT 1 to the Subquery. This will remove the duplicate rows.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.