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

From adfc1b9137ac8b004fe9e495fb79f2bf4b21cf49 Mon Sep 17 00:00:00 2001
From: Jim Jones <jim.jo...@uni-muenster.de>
Date: Fri, 21 Feb 2025 10:10:40 +0100
Subject: [PATCH v2] Add XMLSerialize: explicit XML declaration (SQL/XML X078)

This adds the options INCLUDING XMLDECLARATION and EXCLUDING
XMLDECLARATION to XMLSerialize, which include or remove the
XML declaration of a given DOCUMENT or CONTENT, respectively.

SELECT
  xmlserialize(DOCUMENT val AS text INCLUDING XMLDECLARATION);

SELECT
  xmlserialize(DOCUMENT val AS text EXCLUDING XMLDECLARATION);

If not specified, the output will contain an XML declaration or
not depending on the given XML value. This patch also includes
regression tests and documentation.
---
 doc/src/sgml/datatype.sgml            |  34 ++++-
 src/backend/catalog/sql_features.txt  |   2 +-
 src/backend/executor/execExprInterp.c |   3 +-
 src/backend/parser/gram.y             |  15 +-
 src/backend/parser/parse_expr.c       |   1 +
 src/backend/utils/adt/ruleutils.c     |   5 +
 src/backend/utils/adt/xml.c           |  91 ++++++++---
 src/include/nodes/parsenodes.h        |   1 +
 src/include/nodes/primnodes.h         |   9 ++
 src/include/parser/kwlist.h           |   1 +
 src/include/utils/xml.h               |   2 +-
 src/test/regress/expected/xml.out     | 208 +++++++++++++++++++++++++-
 src/test/regress/expected/xml_1.out   | 154 +++++++++++++++++++
 src/test/regress/expected/xml_2.out   | 208 +++++++++++++++++++++++++-
 src/test/regress/sql/xml.sql          |  36 +++++
 15 files changed, 738 insertions(+), 32 deletions(-)

diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 87679dc4a1..b9b84cda45 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -4511,7 +4511,7 @@ xml '<foo>bar</foo>'
     <type>xml</type>, uses the function
     <function>xmlserialize</function>:<indexterm><primary>xmlserialize</primary></indexterm>
 <synopsis>
-XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> [ [ NO ] INDENT ] )
+XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <replaceable>type</replaceable> [ [ NO ] INDENT ] [INCLUDING XMLDECLARATION | EXCLUDING XMLDECLARATION] )
 </synopsis>
     <replaceable>type</replaceable> can be
     <type>character</type>, <type>character varying</type>, or
@@ -4528,6 +4528,38 @@ XMLSERIALIZE ( { DOCUMENT | CONTENT } <replaceable>value</replaceable> AS <repla
     type likewise produces the original string.
    </para>
 
+   <para>
+   The options <type>INCLUDING XMLDECLARATION</type> and <type>EXCLUDING XMLDECLARATION</type> specify
+   whether the XML declaration of an XML <replaceable>value</replaceable> is included in the serialized string or not, respectively.
+   If not specified, the output will only contain an XML delcaration if the XML <replaceable>value</replaceable> had one.
+   </para>
+
+   <para>
+Examples:
+   </para>
+<screen><![CDATA[
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              xmlserialize
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <foo><bar>42</bar></foo>              +
+
+
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              xmlserialize
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <foo>                                 +
+   <bar>42</bar>                       +
+ </foo>                                +
+
+
+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>+
+]]></screen>
+
    <para>
     When a character string value is cast to or from type
     <type>xml</type> without going through <type>XMLPARSE</type> or
diff --git a/src/backend/catalog/sql_features.txt b/src/backend/catalog/sql_features.txt
index 2f250d2c57..c9b9e5e0f0 100644
--- a/src/backend/catalog/sql_features.txt
+++ b/src/backend/catalog/sql_features.txt
@@ -667,7 +667,7 @@ X074	XMLSerialize: binary string serialization and DOCUMENT option			NO
 X075	XMLSerialize: binary string serialization			NO	
 X076	XMLSerialize: VERSION			NO	
 X077	XMLSerialize: explicit ENCODING option			NO	
-X078	XMLSerialize: explicit XML declaration			NO	
+X078	XMLSerialize: explicit XML declaration			YES	
 X080	Namespaces in XML publishing			NO	
 X081	Query-level XML namespace declarations			NO	
 X082	XML namespace declarations in DML			NO	
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 1c3477b03c..91d3352bb9 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4540,7 +4540,8 @@ ExecEvalXmlExpr(ExprState *state, ExprEvalStep *op)
 				*op->resvalue =
 					PointerGetDatum(xmltotext_with_options(DatumGetXmlP(value),
 														   xexpr->xmloption,
-														   xexpr->indent));
+														   xexpr->indent,
+														   xexpr->xmldeclaration));
 				*op->resnull = false;
 			}
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 7d99c9355c..024015f088 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -620,6 +620,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <defelt>	xmltable_column_option_el
 %type <list>	xml_namespace_list
 %type <target>	xml_namespace_el
+%type <ival> 	opt_xml_declaration_option
 
 %type <node>	func_application func_expr_common_subexpr
 %type <node>	func_expr func_expr_windowless
@@ -788,8 +789,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 
 	WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE
 
-	XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLEXISTS XMLFOREST XMLNAMESPACES
-	XMLPARSE XMLPI XMLROOT XMLSERIALIZE XMLTABLE
+	XML_P XMLATTRIBUTES XMLCONCAT XMLDECLARATION XMLELEMENT XMLEXISTS XMLFOREST
+	XMLNAMESPACES XMLPARSE XMLPI XMLROOT XMLSERIALIZE XMLTABLE
 
 	YEAR_P YES_P
 
@@ -16079,7 +16080,7 @@ func_expr_common_subexpr:
 					$$ = makeXmlExpr(IS_XMLROOT, NULL, NIL,
 									 list_make3($3, $5, $6), @1);
 				}
-			| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename xml_indent_option ')'
+			| XMLSERIALIZE '(' document_or_content a_expr AS SimpleTypename xml_indent_option opt_xml_declaration_option ')'
 				{
 					XmlSerialize *n = makeNode(XmlSerialize);
 
@@ -16087,6 +16088,7 @@ func_expr_common_subexpr:
 					n->expr = $4;
 					n->typeName = $6;
 					n->indent = $7;
+					n->xmldeclaration = $8;
 					n->location = @1;
 					$$ = (Node *) n;
 				}
@@ -16311,6 +16313,11 @@ xml_indent_option: INDENT							{ $$ = true; }
 			| /*EMPTY*/								{ $$ = false; }
 		;
 
+opt_xml_declaration_option: INCLUDING XMLDECLARATION	{ $$ = XMLSERIALIZE_INCLUDING_XMLDECLARATION; }
+			| EXCLUDING XMLDECLARATION					{ $$ = XMLSERIALIZE_EXCLUDING_XMLDECLARATION; }
+			| /*EMPTY*/									{ $$ = XMLSERIALIZE_NO_XMLDECLARATION_OPTION; }
+		;
+
 xml_whitespace_option: PRESERVE WHITESPACE_P		{ $$ = true; }
 			| STRIP_P WHITESPACE_P					{ $$ = false; }
 			| /*EMPTY*/								{ $$ = false; }
@@ -18006,6 +18013,7 @@ unreserved_keyword:
 			| WRAPPER
 			| WRITE
 			| XML_P
+			| XMLDECLARATION
 			| YEAR_P
 			| YES_P
 			| ZONE
@@ -18663,6 +18671,7 @@ bare_label_keyword:
 			| XML_P
 			| XMLATTRIBUTES
 			| XMLCONCAT
+			| XMLDECLARATION
 			| XMLELEMENT
 			| XMLEXISTS
 			| XMLFOREST
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index bad1df732e..3b5c35a79b 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -2489,6 +2489,7 @@ transformXmlSerialize(ParseState *pstate, XmlSerialize *xs)
 
 	xexpr->xmloption = xs->xmloption;
 	xexpr->indent = xs->indent;
+	xexpr->xmldeclaration = xs->xmldeclaration;
 	xexpr->location = xs->location;
 	/* We actually only need these to be able to parse back the expression. */
 	xexpr->type = targetType;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index d11a8a20ee..8bd6536b95 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -10150,6 +10150,11 @@ get_rule_expr(Node *node, deparse_context *context,
 						appendStringInfoString(buf, " INDENT");
 					else
 						appendStringInfoString(buf, " NO INDENT");
+
+					if (xexpr->xmldeclaration == XMLSERIALIZE_INCLUDING_XMLDECLARATION)
+						appendStringInfoString(buf, " INCLUDING XMLDECLARATION");
+					else if (xexpr->xmldeclaration == XMLSERIALIZE_EXCLUDING_XMLDECLARATION)
+						appendStringInfoString(buf, " EXCLUDING XMLDECLARATION");
 				}
 
 				if (xexpr->op == IS_DOCUMENT)
diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index db8d0d6a7e..97ccd64802 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -653,7 +653,8 @@ xmltotext(PG_FUNCTION_ARGS)
 
 
 text *
-xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
+xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent,
+						XmlSerializeDeclarationOption xmldeclaration)
 {
 #ifdef USE_LIBXML
 	text	   *volatile result;
@@ -666,7 +667,8 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 	PgXmlErrorContext *xmlerrcxt;
 #endif
 
-	if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
+	if (xmloption_arg != XMLOPTION_DOCUMENT &&
+		xmldeclaration == XMLSERIALIZE_NO_XMLDECLARATION_OPTION && !indent)
 	{
 		/*
 		 * We don't actually need to do anything, so just return the
@@ -697,8 +699,11 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 				 errmsg("not an XML document")));
 	}
 
-	/* If we weren't asked to indent, we're done. */
-	if (!indent)
+	/*
+	 * If we weren't asked to indent or to explicitly hide or show the
+	 * xml declaration, we're done.
+	 */
+	if (!indent && xmldeclaration == XMLSERIALIZE_NO_XMLDECLARATION_OPTION)
 	{
 		xmlFreeDoc(doc);
 		return (text *) data;
@@ -722,17 +727,22 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 		parse_xml_decl(xml_text2xmlChar(data), &decl_len, NULL, NULL, NULL);
 
 		/*
-		 * Emit declaration only if the input had one.  Note: some versions of
-		 * xmlSaveToBuffer leak memory if a non-null encoding argument is
-		 * passed, so don't do that.  We don't want any encoding conversion
-		 * anyway.
-		 */
-		if (decl_len == 0)
-			ctxt = xmlSaveToBuffer(buf, NULL,
-								   XML_SAVE_NO_DECL | XML_SAVE_FORMAT);
-		else
-			ctxt = xmlSaveToBuffer(buf, NULL,
-								   XML_SAVE_FORMAT);
+		* Emit declaration if the input had one or if it was explicitly
+		* requested via INCLUDING XMLDECLARATION. Indent the buffer content
+		* if the flag INDENT was used. Note: some versions of xmlSaveToBuffer
+		* leak memory if a non-null encoding argument is passed, so don't do
+		* that. We don't want any encoding conversion anyway.
+		*/
+		ctxt = xmlSaveToBuffer(buf, NULL,
+			/* remove XML declaration if EXCLUDING XMLDECLARATION was used. */
+			(xmldeclaration == XMLSERIALIZE_EXCLUDING_XMLDECLARATION ? XML_SAVE_NO_DECL : 0) |
+			/*
+				* remove XML declaration if the xml string didn't have one and
+				* INCLUDING XMLDECLARATION was not used
+				*/
+			((decl_len == 0 && xmldeclaration == XMLSERIALIZE_NO_XMLDECLARATION_OPTION) ? XML_SAVE_NO_DECL : 0) |
+			/* indent the xml dump if INDENT was used */
+			(indent ? XML_SAVE_FORMAT : 0));
 
 		if (ctxt == NULL || xmlerrcxt->err_occurred)
 			xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
@@ -754,7 +764,7 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 			 * content nodes, and then iterate over the nodes.
 			 */
 			xmlNodePtr	root;
-			xmlNodePtr	newline;
+			xmlNodePtr	newline = NULL;
 
 			root = xmlNewNode(NULL, (const xmlChar *) "content-root");
 			if (root == NULL || xmlerrcxt->err_occurred)
@@ -772,15 +782,19 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 			 * freeing of this node manually, and pass NULL here to make sure
 			 * there's not a dangling link.
 			 */
-			newline = xmlNewDocText(NULL, (const xmlChar *) "\n");
-			if (newline == NULL || xmlerrcxt->err_occurred)
-				xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
-							"could not allocate xml node");
+			if (indent)
+			{
+				newline = xmlNewDocText(NULL, (const xmlChar *)"\n");
+
+				if (newline == NULL || xmlerrcxt->err_occurred)
+					xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
+								"could not allocate xml node");
+			}
 
 			for (xmlNodePtr node = root->children; node; node = node->next)
 			{
 				/* insert newlines between nodes */
-				if (node->type != XML_TEXT_NODE && node->prev != NULL)
+				if (node->type != XML_TEXT_NODE && node->prev != NULL && newline != NULL)
 				{
 					if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred)
 					{
@@ -792,13 +806,44 @@ xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg, bool indent)
 
 				if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
 				{
-					xmlFreeNode(newline);
+					if(newline != NULL)
+						xmlFreeNode(newline);
 					xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
 								"could not save content to xmlBuffer");
 				}
 			}
 
-			xmlFreeNode(newline);
+			/*
+			 * If the flag INCLUDING XMLDECLARATION is specified, we have
+			 * to manually add the XML declaration here. xmlSaveTree() does
+			 * not include it.
+			 */
+			if (xmldeclaration == XMLSERIALIZE_INCLUDING_XMLDECLARATION)
+			{
+				StringInfoData xmldecl;
+				initStringInfo(&xmldecl);
+				appendStringInfoString(&xmldecl, "<?xml");
+
+				if (doc->version)
+					appendStringInfo(&xmldecl, " version=\"%s\"", doc->version);
+
+				if (doc->encoding)
+					appendStringInfo(&xmldecl, " encoding=\"%s\"", doc->encoding);
+
+				/* We only add "standalone" if the input's XML declaration had one */
+				if (doc->standalone == 1)
+					appendStringInfo(&xmldecl, " standalone=\"yes\"");
+				else if (doc->standalone == 0)
+					appendStringInfo(&xmldecl, " standalone=\"no\"");
+
+				appendStringInfoString(&xmldecl, "?>\n");
+				xmlBufferAddHead(buf, (const xmlChar *)xmldecl.data, xmldecl.len);
+
+				pfree(xmldecl.data);
+			}
+
+			if (newline != NULL)
+				xmlFreeNode(newline);
 		}
 
 		if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 0b208f51bd..7661de3f5e 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -857,6 +857,7 @@ typedef struct XmlSerialize
 	Node	   *expr;
 	TypeName   *typeName;
 	bool		indent;			/* [NO] INDENT */
+	XmlSerializeDeclarationOption	xmldeclaration;	/* INCLUDING or EXCLUDING XMLDECLARATION */
 	ParseLoc	location;		/* token location, or -1 if unknown */
 } XmlSerialize;
 
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 839e71d52f..5d46f8364b 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -1598,6 +1598,13 @@ typedef enum XmlOptionType
 	XMLOPTION_CONTENT,
 } XmlOptionType;
 
+typedef enum XmlSerializeDeclarationOption
+{
+	XMLSERIALIZE_INCLUDING_XMLDECLARATION,     /* Add xml declaration in XMLSERIALIZE output */
+	XMLSERIALIZE_EXCLUDING_XMLDECLARATION,     /* Remove xml declaration in XMLSERIALIZE output */
+	XMLSERIALIZE_NO_XMLDECLARATION_OPTION      /* Add xml declaration only if XMLSERIALIZE input has one */
+} XmlSerializeDeclarationOption;
+
 typedef struct XmlExpr
 {
 	Expr		xpr;
@@ -1620,6 +1627,8 @@ typedef struct XmlExpr
 	int32		typmod pg_node_attr(query_jumble_ignore);
 	/* token location, or -1 if unknown */
 	ParseLoc	location;
+	/* xmlserialize flags INCLUDING and EXCLUDING XMLDECLARATION */
+	XmlSerializeDeclarationOption xmldeclaration pg_node_attr(query_jumble_ignore);
 } XmlExpr;
 
 /*
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 40cf090ce6..7bfabfb147 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -506,6 +506,7 @@ PG_KEYWORD("write", WRITE, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xml", XML_P, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xmlconcat", XMLCONCAT, COL_NAME_KEYWORD, BARE_LABEL)
+PG_KEYWORD("xmldeclaration", XMLDECLARATION, UNRESERVED_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xmlelement", XMLELEMENT, COL_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xmlexists", XMLEXISTS, COL_NAME_KEYWORD, BARE_LABEL)
 PG_KEYWORD("xmlforest", XMLFOREST, COL_NAME_KEYWORD, BARE_LABEL)
diff --git a/src/include/utils/xml.h b/src/include/utils/xml.h
index 0d7a816b9f..748bf7bc17 100644
--- a/src/include/utils/xml.h
+++ b/src/include/utils/xml.h
@@ -78,7 +78,7 @@ extern xmltype *xmlpi(const char *target, text *arg, bool arg_is_null, bool *res
 extern xmltype *xmlroot(xmltype *data, text *version, int standalone);
 extern bool xml_is_document(xmltype *arg);
 extern text *xmltotext_with_options(xmltype *data, XmlOptionType xmloption_arg,
-									bool indent);
+									bool indent, XmlSerializeDeclarationOption xmldeclaration);
 extern char *escape_xml(const char *str);
 
 extern char *map_sql_identifier_to_xml_name(const char *ident, bool fully_escaped, bool escape_period);
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index bcc743f485..812eebb376 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -676,6 +676,200 @@ SELECT xmlserialize(CONTENT  'text node<foo>    <bar></bar>   </foo>' AS text IN
  </foo>
 (1 row)
 
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              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 EXCLUDING XMLDECLARATION);
+       xmlserialize       
+--------------------------
+ <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 INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <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)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ <foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ <foo><bar>42</bar></foo>
+(1 row)
+
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+        xmlserialize         
+-----------------------------
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+        xmlserialize         
+-----------------------------
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration' (DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              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 INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ <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 INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <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 INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ <foo>                                                 +
+   <bar>42</bar>                                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ <foo>                                                  +
+   <bar>42</bar>                                        +
+ </foo>
+(1 row)
+
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt                                   +
+ <foo>                                 +
+   <bar>42</bar>                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ txt            +
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt                                   +
+ <foo>                                 +
+   <bar>42</bar>                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ txt            +
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ txt                                                   +
+ <foo>                                                 +
+   <bar>42</bar>                                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ txt                                                    +
+ <foo>                                                  +
+   <bar>42</bar>                                        +
+ </foo>
+(1 row)
+
 SELECT xml '<foo>bar</foo>' IS DOCUMENT;
  ?column? 
 ----------
@@ -824,6 +1018,12 @@ CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10));
 CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text);
 CREATE VIEW xmlview10 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent);
 CREATE VIEW xmlview11 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS character varying no indent);
+CREATE VIEW xmlview12 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text including xmldeclaration);
+CREATE VIEW xmlview13 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text excluding xmldeclaration);
+CREATE VIEW xmlview14 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent including xmldeclaration);
+CREATE VIEW xmlview15 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent excluding xmldeclaration);
+CREATE VIEW xmlview16 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent including xmldeclaration);
+CREATE VIEW xmlview17 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent excluding xmldeclaration);
 SELECT table_name, view_definition FROM information_schema.views
   WHERE table_name LIKE 'xmlview%' ORDER BY 1;
  table_name |                                                            view_definition                                                            
@@ -831,6 +1031,12 @@ SELECT table_name, view_definition FROM information_schema.views
  xmlview1   |  SELECT xmlcomment('test'::text) AS xmlcomment;
  xmlview10  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT) AS "xmlserialize";
  xmlview11  |  SELECT (XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS character varying NO INDENT))::character varying AS "xmlserialize";
+ xmlview12  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview13  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview14  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview15  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview16  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview17  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
  xmlview2   |  SELECT XMLCONCAT('hello'::xml, 'you'::xml) AS "xmlconcat";
  xmlview3   |  SELECT XMLELEMENT(NAME element, XMLATTRIBUTES(1 AS ":one:", 'deuce' AS two), 'content&') AS "xmlelement";
  xmlview4   |  SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement"                                +
@@ -840,7 +1046,7 @@ SELECT table_name, view_definition FROM information_schema.views
  xmlview7   |  SELECT XMLROOT('<foo/>'::xml, VERSION NO VALUE, STANDALONE YES) AS "xmlroot";
  xmlview8   |  SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10) NO INDENT))::character(10) AS "xmlserialize";
  xmlview9   |  SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text NO INDENT) AS "xmlserialize";
-(11 rows)
+(17 rows)
 
 -- Text XPath expressions evaluation
 SELECT xpath('/value', data) FROM xmltest;
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index a1c5d31417..d887011165 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -454,6 +454,130 @@ ERROR:  unsupported XML feature
 LINE 1: SELECT xmlserialize(CONTENT  'text node<foo>    <bar></bar> ...
                                      ^
 DETAIL:  This functionality requires the server to be built with libxml support.
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::x...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::x...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration' (DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="...
+                                     ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::x...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::x...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+ERROR:  unsupported XML feature
+LINE 1: SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="U...
+                                    ^
+DETAIL:  This functionality requires the server to be built with libxml support.
 SELECT xml '<foo>bar</foo>' IS DOCUMENT;
 ERROR:  unsupported XML feature
 LINE 1: SELECT xml '<foo>bar</foo>' IS DOCUMENT;
@@ -593,6 +717,36 @@ ERROR:  unsupported XML feature
 LINE 1: ...TE VIEW xmlview11 AS SELECT xmlserialize(document '<foo><bar...
                                                              ^
 DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview12 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text including xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview12 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview13 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text excluding xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview13 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview14 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent including xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview14 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview15 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent excluding xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview15 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview16 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent including xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview16 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
+CREATE VIEW xmlview17 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent excluding xmldeclaration);
+ERROR:  unsupported XML feature
+LINE 1: ...TE VIEW xmlview17 AS SELECT xmlserialize(document '<foo><bar...
+                                                             ^
+DETAIL:  This functionality requires the server to be built with libxml support.
 SELECT table_name, view_definition FROM information_schema.views
   WHERE table_name LIKE 'xmlview%' ORDER BY 1;
  table_name |                                view_definition                                 
diff --git a/src/test/regress/expected/xml_2.out b/src/test/regress/expected/xml_2.out
index 045641dae6..f3938b410f 100644
--- a/src/test/regress/expected/xml_2.out
+++ b/src/test/regress/expected/xml_2.out
@@ -662,6 +662,200 @@ SELECT xmlserialize(CONTENT  'text node<foo>    <bar></bar>   </foo>' AS text IN
  </foo>
 (1 row)
 
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              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 EXCLUDING XMLDECLARATION);
+       xmlserialize       
+--------------------------
+ <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 INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <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)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ <foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ <foo><bar>42</bar></foo>
+(1 row)
+
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+        xmlserialize         
+-----------------------------
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+        xmlserialize         
+-----------------------------
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ txt<foo><bar>42</bar></foo>
+(1 row)
+
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration' (DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              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 INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ <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 INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ <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 INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ <foo>                                                 +
+   <bar>42</bar>                                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ <foo>                                                  +
+   <bar>42</bar>                                        +
+ </foo>
+(1 row)
+
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt                                   +
+ <foo>                                 +
+   <bar>42</bar>                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ txt            +
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+              xmlserialize              
+----------------------------------------
+ <?xml version="1.0" encoding="UTF-8"?>+
+ txt                                   +
+ <foo>                                 +
+   <bar>42</bar>                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+  xmlserialize   
+-----------------
+ txt            +
+ <foo>          +
+   <bar>42</bar>+
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                      
+--------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>+
+ txt                                                   +
+ <foo>                                                 +
+   <bar>42</bar>                                       +
+ </foo>
+(1 row)
+
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+                      xmlserialize                       
+---------------------------------------------------------
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>+
+ txt                                                    +
+ <foo>                                                  +
+   <bar>42</bar>                                        +
+ </foo>
+(1 row)
+
 SELECT xml '<foo>bar</foo>' IS DOCUMENT;
  ?column? 
 ----------
@@ -810,6 +1004,12 @@ CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10));
 CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text);
 CREATE VIEW xmlview10 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent);
 CREATE VIEW xmlview11 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS character varying no indent);
+CREATE VIEW xmlview12 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text including xmldeclaration);
+CREATE VIEW xmlview13 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text excluding xmldeclaration);
+CREATE VIEW xmlview14 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent including xmldeclaration);
+CREATE VIEW xmlview15 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent excluding xmldeclaration);
+CREATE VIEW xmlview16 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent including xmldeclaration);
+CREATE VIEW xmlview17 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent excluding xmldeclaration);
 SELECT table_name, view_definition FROM information_schema.views
   WHERE table_name LIKE 'xmlview%' ORDER BY 1;
  table_name |                                                            view_definition                                                            
@@ -817,6 +1017,12 @@ SELECT table_name, view_definition FROM information_schema.views
  xmlview1   |  SELECT xmlcomment('test'::text) AS xmlcomment;
  xmlview10  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT) AS "xmlserialize";
  xmlview11  |  SELECT (XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS character varying NO INDENT))::character varying AS "xmlserialize";
+ xmlview12  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview13  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview14  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview15  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview16  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT INCLUDING XMLDECLARATION) AS "xmlserialize";
+ xmlview17  |  SELECT XMLSERIALIZE(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text NO INDENT EXCLUDING XMLDECLARATION) AS "xmlserialize";
  xmlview2   |  SELECT XMLCONCAT('hello'::xml, 'you'::xml) AS "xmlconcat";
  xmlview3   |  SELECT XMLELEMENT(NAME element, XMLATTRIBUTES(1 AS ":one:", 'deuce' AS two), 'content&') AS "xmlelement";
  xmlview4   |  SELECT XMLELEMENT(NAME employee, XMLFOREST(name AS name, age AS age, salary AS pay)) AS "xmlelement"                                +
@@ -826,7 +1032,7 @@ SELECT table_name, view_definition FROM information_schema.views
  xmlview7   |  SELECT XMLROOT('<foo/>'::xml, VERSION NO VALUE, STANDALONE YES) AS "xmlroot";
  xmlview8   |  SELECT (XMLSERIALIZE(CONTENT 'good'::xml AS character(10) NO INDENT))::character(10) AS "xmlserialize";
  xmlview9   |  SELECT XMLSERIALIZE(CONTENT 'good'::xml AS text NO INDENT) AS "xmlserialize";
-(11 rows)
+(17 rows)
 
 -- Text XPath expressions evaluation
 SELECT xpath('/value', data) FROM xmltest;
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index 4c3520ce89..56aa4317a6 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -172,6 +172,35 @@ SELECT xmlserialize(CONTENT  '<foo><bar><val x="y">42</val></bar></foo>' AS text
 SELECT xmlserialize(DOCUMENT '<foo>   <bar></bar>    </foo>' AS text INDENT);
 SELECT xmlserialize(CONTENT  'text node<foo>    <bar></bar>   </foo>' AS text INDENT);
 
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+-- 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INCLUDING XMLDECLARATION);
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration' (DOCUMENT)
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8"?><foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(DOCUMENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?><foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+-- 'indent' + 'including xmldeclaration' and 'excluding xmldeclaration'(CONTENT)
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT 'txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT EXCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="no"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+SELECT xmlserialize(CONTENT '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>txt<foo><bar>42</bar></foo>'::xml AS text INDENT INCLUDING XMLDECLARATION);
+
 SELECT xml '<foo>bar</foo>' IS DOCUMENT;
 SELECT xml '<foo>bar</foo><bar>foo</bar>' IS DOCUMENT;
 SELECT xml '<abc/>' IS NOT DOCUMENT;
@@ -221,6 +250,13 @@ CREATE VIEW xmlview8 AS SELECT xmlserialize(content 'good' as char(10));
 CREATE VIEW xmlview9 AS SELECT xmlserialize(content 'good' as text);
 CREATE VIEW xmlview10 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent);
 CREATE VIEW xmlview11 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS character varying no indent);
+CREATE VIEW xmlview12 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text including xmldeclaration);
+CREATE VIEW xmlview13 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text excluding xmldeclaration);
+CREATE VIEW xmlview14 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent including xmldeclaration);
+CREATE VIEW xmlview15 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text indent excluding xmldeclaration);
+CREATE VIEW xmlview16 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent including xmldeclaration);
+CREATE VIEW xmlview17 AS SELECT xmlserialize(document '<foo><bar>42</bar></foo>' AS text no indent excluding xmldeclaration);
+
 
 SELECT table_name, view_definition FROM information_schema.views
   WHERE table_name LIKE 'xmlview%' ORDER BY 1;
-- 
2.34.1

Reply via email to