XMLSerialize: version and explicit XML declaration
Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.
You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:
docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t50308psql -h localhost -U postgresBuilt from patchset v11 (message #11), September 20, 2026 at 07:24 AM.
Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:
git clone --branch t50308_11 https://github.com/hackorum-dev/postgres.gitIn a checkout you already have, add the fork once:
git remote add hackorum https://github.com/hackorum-dev/postgres.gitthen, for this patchset and every later one:
git fetch hackorum t50308_11 && git checkout t50308_11Patchset v11 (message #11) is on t50308_11
Hi,
I'm working on the flags VERSION (X076), INCLUDING XMLDECLARATION, and
EXCLUDING XMLDECLARATION (X078) for XMLSerialize, and I have a question
for SQL/XML experts on the list.
Is there any validation mechanism for VERSION <character string
literal>? The SQL/XML spec says
"The <character string literal> immediately contained in <XML serialize
version> shall be '1.0' or '1.1', or it shall identify some successor to
XML 1.0 and XML 1.1."
I was wondering if a validation here would make any sense, since
XMLSerialize is only supposed to print a string --- not to mention that
validating "some successor to XML 1.0 and XML 1.1" can be challenging :)
But again, printing an "invalid" XML string also doesn't seem very nice.
The oracle implementation accepts pretty much anything:
SQL> SELECT xmlserialize(DOCUMENT xmltype('<foo><bar>42</bar></foo>')
VERSION 'foo') AS xml FROM dual;
XML
--------------------------------------------------------------------------------
<?xml version="foo"?>
<foo>
<bar>42</bar>
</foo>
In db2, anything other than '1.0' raises an error:
db2 => SELECT XMLSERIALIZE(CONTENT XMLELEMENT(NAME "db2",service_level)
AS varchar(100) VERSION '1.0' INCLUDING XMLDECLARATION) FROM
sysibmadm.env_inst_info;
1
----------------------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><db2>DB2
v11.5.9.0</db2>
1 record(s) selected.
db2 => SELECT XMLSERIALIZE(CONTENT XMLELEMENT(NAME "db2",service_level)
AS varchar(100) VERSION '1.1' INCLUDING XMLDECLARATION) FROM
sysibmadm.env_inst_info;
SQL0171N The statement was not processed because the data type, length or
value of the argument for the parameter in position "2" of routine
"XMLSERIALIZE" is incorrect. Parameter name: "". SQLSTATE=42815
Any thoughts on how we should approach this feature?
Thanks!
Best, Jim
Jim Jones <jim.jones@uni-muenster.de> writes:
Is there any validation mechanism for VERSION <character string
literal>?
AFAICS, all we do with an embedded XML version string is pass it to
libxml2's xmlNewDoc(), which is the authority on whether it means
anything. I'd be inclined to do the same here.
regards, tom lane
Hi Tom
On 25.09.24 18:02, Tom Lane wrote:
AFAICS, all we do with an embedded XML version string is pass it to
libxml2's xmlNewDoc(), which is the authority on whether it means
anything. I'd be inclined to do the same here.
Thanks. I used xml_is_document(), which calls xmlNewDoc(), to check if
the returned document is valid or not. It then decides if an unexpected
version deserves an error or just a warning.
Attached v1 with the first attempt to implement these features.
==== INCLUDING / EXCLUDING XMLDECLARATION (SQL/XML X078) ====
The flags INCLUDING XMLDECLARATION and EXCLUDING XMLDECLARATION include
or remove the XML declaration in the XMLSerialize output of the given
DOCUMENT or CONTENT, respectively.
SELECT
xmlserialize(
DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text
INCLUDING XMLDECLARATION);
xmlserialize
---------------------------------------------------------------
<?xml version="1.0" encoding="UTF8"?><foo><bar>42</bar></foo>
(1 row)
SELECT
xmlserialize(
DOCUMENT '<?xml version="1.0"
encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text
EXCLUDING XMLDECLARATION);
xmlserialize
--------------------------
<foo><bar>42</bar></foo>
(1 row)
If omitted, the output will contain an XML declaration only if the given
XML value had one.
SELECT
xmlserialize(
DOCUMENT '<?xml version="1.0"
encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text);
xmlserialize
----------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>
(1 row)
SELECT
xmlserialize(
DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text);
xmlserialize
--------------------------
<foo><bar>42</bar></foo>
(1 row)
==== VERSION (SQL/XML X076)====
VERSION can be used to specify the version in the XML declaration of the
serialized DOCUMENT or CONTENT.
SELECT
xmlserialize(
DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text
VERSION '1.0'
INCLUDING XMLDECLARATION);
xmlserialize
---------------------------------------------------------------
<?xml version="1.0" encoding="UTF8"?><foo><bar>42</bar></foo>
(1 row)
In case of XML values of type DOCUMENT, the version will be validated by
libxml2's xmlNewDoc(), which will raise an error for invalid
versions or a warning for unsupported ones. For CONTENT values no
validation is performed.
SELECT
xmlserialize(
DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text
VERSION '1.1'
INCLUDING XMLDECLARATION);
WARNING: line 1: Unsupported version '1.1'
<?xml version="1.1" encoding="UTF8"?><foo><bar>42</bar></foo>
^
xmlserialize
---------------------------------------------------------------
<?xml version="1.1" encoding="UTF8"?><foo><bar>42</bar></foo>
(1 row)
SELECT
xmlserialize(
DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text
VERSION '2.0'
INCLUDING XMLDECLARATION);
ERROR: Invalid XML declaration: VERSION '2.0'
SELECT
xmlserialize(
CONTENT '<foo><bar>42</bar></foo>'::xml AS text
VERSION '2.0'
INCLUDING XMLDECLARATION);
xmlserialize
---------------------------------------------------------------
<?xml version="2.0" encoding="UTF8"?><foo><bar>42</bar></foo>
(1 row)
This option is ignored if the XML value had no XML declaration and
INCLUDING XMLDECLARATION was not used.
SELECT
xmlserialize(
CONTENT '<foo><bar>42</bar></foo>'::xml AS text
VERSION '1111');
xmlserialize
--------------------------
<foo><bar>42</bar></foo>
(1 row)
Best, Jim
Attachments:
v1-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v1-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1347-51
On 30.09.24 10:08, Jim Jones wrote:
On 25.09.24 18:02, Tom Lane wrote:
AFAICS, all we do with an embedded XML version string is pass it to
libxml2's xmlNewDoc(), which is the authority on whether it means
anything. I'd be inclined to do the same here.Thanks. I used xml_is_document(), which calls xmlNewDoc(), to check if
the returned document is valid or not. It then decides if an unexpected
version deserves an error or just a warning.Attached v1 with the first attempt to implement these features.
rebase
Best regards, Jim
Attachments:
v2-0001-Add-XMLSerialize-explicit-XML-declaration-SQL-XML.patchtext/x-patch; charset=UTF-8; name=v2-0001-Add-XMLSerialize-explicit-XML-declaration-SQL-XML.patchDownload+738-33
rebase
Best, Jim
Attachments:
v3-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v3-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1476-56
rebase and add missing check for xmlBufferAddHead result
--
Jim
Attachments:
v4-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v4-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1487-56
rebase
--
Jim
Attachments:
v5-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v5-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1490-56
rebased
--
Jim
Attachments:
v6-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v6-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1490-56
rebased
Jim
Attachments:
v7-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchtext/x-patch; charset=UTF-8; name=v7-0001-Add-XMLSerialize-version-and-explicit-XML-declara.patchDownload+1490-56
On Mon, Aug 3, 2026 at 7:40 PM Jim Jones <jim.jones@uni-muenster.de> wrote:
rebase
Hi Jim,
I tested the latest v9 patch on PostgreSQL 20devel.
The patch applied cleanly and the build completed successfully with
libxml support enabled. I also ran the regression tests, and all tests
passed.
I verified the new functionality introduced by the patch:
INCLUDING XMLDECLARATION correctly adds the XML declaration.
EXCLUDING XMLDECLARATION correctly removes the XML declaration.
VERSION '1.0' produces the expected output.
VERSION '1.1' generates the expected warning while still producing valid output.
An invalid version such as VERSION '2.0' correctly raises an error for
DOCUMENT values.
For CONTENT values, VERSION '2.0' is accepted as expected.
I also verified that the existing XMLSERIALIZE behavior remains
unchanged when the new options are not used.
From my testing, the patch works as expected, and I did not observe any issues.
Regards,
solai