On 25.08.23 16:49, Vik Fearing wrote:
I am talking specifically about this: @@ -505,6 +506,10 @@ xmlcomment(PG_FUNCTION_ARGS) appendStringInfoText(&buf, arg); appendStringInfoString(&buf, "-->"); + + + + PG_RETURN_XML_P(stringinfo_to_xmltype(&buf)); #else NO_XML_SUPPORT();
I have no idea how xmlcomment() got changed in this patch :D nice catch!
I do not think this should be addressed in this patch because there are quite a lot of functions that need to handle this.
v4 attached. Jim
From ea812791ffdce22d5f5615da361f67c801089f91 Mon Sep 17 00:00:00 2001 From: Jim Jones <jim.jo...@uni-muenster.de> Date: Fri, 25 Aug 2023 14:05:39 +0200 Subject: [PATCH v4] Add XMLText function (SQL/XML X038) This function implements the standard XMLTest function, which converts text into xml text nodes. It uses the libxml2 function xmlEncodeSpecialChars to escape predifined entites (&"<>), so that those do not cause any conflict when concatenating the text node output with existing xml documents. This patch includes also documentation and regression tests. --- doc/src/sgml/func.sgml | 30 +++++++++++++++++++++++ src/backend/catalog/sql_features.txt | 2 +- src/backend/utils/adt/xml.c | 22 +++++++++++++++++ src/include/catalog/pg_proc.dat | 3 +++ src/test/regress/expected/xml.out | 36 ++++++++++++++++++++++++++++ src/test/regress/expected/xml_1.out | 23 ++++++++++++++++++ src/test/regress/expected/xml_2.out | 36 ++++++++++++++++++++++++++++ src/test/regress/sql/xml.sql | 7 ++++++ 8 files changed, 158 insertions(+), 1 deletion(-) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 7a0d4b9134..2f01a2c25d 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -14058,6 +14058,36 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple documents for processing in client applications. </para> + <sect3 id="functions-producing-xml-xmltext"> + <title><literal>xmltext</literal></title> + + <indexterm> + <primary>xmltext</primary> + </indexterm> + +<synopsis> +<function>xmltext</function> ( <type>text</type> ) <returnvalue>xml</returnvalue> +</synopsis> + + <para> + The function <function>xmltext</function> returns an XML value with a single + text node containing the input argument as its content. Predefined entities + like ampersand (<literal><![CDATA[&]]></literal>), left and right angle brackets + (<literal><![CDATA[< >]]></literal>), and quotation marks (<literal><![CDATA[""]]></literal>) + are escaped. + </para> + + <para> + Example: +<screen><![CDATA[ +SELECT xmltext('< foo & bar >'); + xmltext +------------------------- + < foo & bar > +]]></screen> + </para> + </sect3> + <sect3 id="functions-producing-xml-xmlcomment"> <title><literal>xmlcomment</literal></title> diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt index b33065d7bf..680d541673 100644 --- a/src/backend/catalog/sql_features.txt +++ b/src/backend/catalog/sql_features.txt @@ -633,7 +633,7 @@ X034 XMLAgg YES X035 XMLAgg: ORDER BY option YES X036 XMLComment YES X037 XMLPI YES -X038 XMLText NO +X038 XMLText YES X040 Basic table mapping YES X041 Basic table mapping: null absent YES X042 Basic table mapping: null as nil YES diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index 866d0d649a..7f6984dd88 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -47,6 +47,7 @@ #ifdef USE_LIBXML #include <libxml/chvalid.h> +#include <libxml/entities.h> #include <libxml/parser.h> #include <libxml/parserInternals.h> #include <libxml/tree.h> @@ -5006,3 +5007,24 @@ XmlTableDestroyOpaque(TableFuncScanState *state) NO_XML_SUPPORT(); #endif /* not USE_LIBXML */ } + +Datum +xmltext(PG_FUNCTION_ARGS) +{ +#ifdef USE_LIBXML + text *arg = PG_GETARG_TEXT_PP(0); + text *result; + xmlChar *xmlbuf = NULL; + + xmlbuf = xmlEncodeSpecialChars(NULL,xml_text2xmlChar(arg)); + + Assert(xmlbuf); + + result = cstring_to_text_with_len((const char *) xmlbuf, xmlStrlen(xmlbuf)); + xmlFree(xmlbuf); + PG_RETURN_XML_P(result); +#else + NO_XML_SUPPORT(); + return 0; +#endif +} \ No newline at end of file diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 9805bc6118..ff00c6365d 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -8789,6 +8789,9 @@ { oid => '2922', descr => 'serialize an XML value to a character string', proname => 'text', prorettype => 'text', proargtypes => 'xml', prosrc => 'xmltotext' }, +{ oid => '3813', descr => 'generate XML text node', + proname => 'xmltext', proisstrict => 't', prorettype => 'xml', + proargtypes => 'text', prosrc => 'xmltext' }, { oid => '2923', descr => 'map table contents to XML', proname => 'table_to_xml', procost => '100', provolatile => 's', diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out index 398345ca67..13e4296bf8 100644 --- a/src/test/regress/expected/xml.out +++ b/src/test/regress/expected/xml.out @@ -1785,3 +1785,39 @@ SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH <foo/> | <foo/> (1 row) +SELECT xmltext(NULL); + xmltext +--------- + +(1 row) + +SELECT xmltext(''); + xmltext +--------- + +(1 row) + +SELECT xmltext(' '); + xmltext +--------- + +(1 row) + +SELECT xmltext('foo `$_-+?=*^%!|/\()[]{}'); + xmltext +-------------------------- + foo `$_-+?=*^%!|/\()[]{} +(1 row) + +SELECT xmltext('foo & <"bar">'); + xmltext +----------------------------------- + foo & <"bar"> +(1 row) + +SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char); + xmltext +--------------------------------- + x<P>73</P>0.42truej +(1 row) + diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out index 63b779470f..eb9c6f2ed4 100644 --- a/src/test/regress/expected/xml_1.out +++ b/src/test/regress/expected/xml_1.out @@ -1402,3 +1402,26 @@ DETAIL: This functionality requires the server to be built with libxml support. SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH '"<foo/>"', b xml PATH '"<foo/>"'); ERROR: unsupported XML feature DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmltext(NULL); + xmltext +--------- + +(1 row) + +SELECT xmltext(''); +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmltext(' '); +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmltext('foo `$_-+?=*^%!|/\()[]{}'); +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmltext('foo & <"bar">'); +ERROR: unsupported XML feature +DETAIL: This functionality requires the server to be built with libxml support. +SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char); +ERROR: unsupported XML feature +LINE 1: SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j':... + ^ +DETAIL: This functionality requires the server to be built with libxml support. diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out index 43c2558352..c8ed8e0cfa 100644 --- a/src/test/regress/expected/xml_2.out +++ b/src/test/regress/expected/xml_2.out @@ -1765,3 +1765,39 @@ SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH <foo/> | <foo/> (1 row) +SELECT xmltext(NULL); + xmltext +--------- + +(1 row) + +SELECT xmltext(''); + xmltext +--------- + +(1 row) + +SELECT xmltext(' '); + xmltext +--------- + +(1 row) + +SELECT xmltext('foo `$_-+?=*^%!|/\()[]{}'); + xmltext +-------------------------- + foo `$_-+?=*^%!|/\()[]{} +(1 row) + +SELECT xmltext('foo & <"bar">'); + xmltext +----------------------------------- + foo & <"bar"> +(1 row) + +SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char); + xmltext +--------------------------------- + x<P>73</P>0.42truej +(1 row) + diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql index a591eea2e5..bd4a4e7acd 100644 --- a/src/test/regress/sql/xml.sql +++ b/src/test/regress/sql/xml.sql @@ -660,3 +660,10 @@ SELECT * FROM XMLTABLE('*' PASSING '<e>pre<!--c1--><?pi arg?><![CDATA[&ent1]]><n \x SELECT * FROM XMLTABLE('.' PASSING XMLELEMENT(NAME a) columns a varchar(20) PATH '"<foo/>"', b xml PATH '"<foo/>"'); + +SELECT xmltext(NULL); +SELECT xmltext(''); +SELECT xmltext(' '); +SELECT xmltext('foo `$_-+?=*^%!|/\()[]{}'); +SELECT xmltext('foo & <"bar">'); +SELECT xmltext('x'|| '<P>73</P>'::xml || .42 || true || 'j'::char); \ No newline at end of file -- 2.34.1