diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 00f661df9d..e9c9496801 100644
--- a/src/backend/utils/adt/xml.c
+++ b/src/backend/utils/adt/xml.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.36 2007/03/22 20:14:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.37 2007/03/22 20:26:30 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -91,7 +91,7 @@ static xmlChar *xml_text2xmlChar(text *in);
static int parse_xml_decl(const xmlChar *str, size_t *lenp, xmlChar **version, xmlChar **encoding, int *standalone);
static bool print_xml_decl(StringInfo buf, const xmlChar *version, pg_enc encoding, int standalone);
static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, xmlChar *encoding);
-static text *xml_xmlnodetotext(xmlNodePtr cur);
+static text *xml_xmlnodetoxmltype(xmlNodePtr cur);
#endif /* USE_LIBXML */
@@ -2414,20 +2414,31 @@ SPI_sql_row_to_xmlelement(int rownum, StringInfo result, char *tablename, bool n
#ifdef USE_LIBXML
/*
- * Convert XML node to text (return value only, it's not dumping)
+ * Convert XML node to text (dump subtree in case of element, return value otherwise)
*/
text *
-xml_xmlnodetotext(xmlNodePtr cur)
+xml_xmlnodetoxmltype(xmlNodePtr cur)
{
- xmlChar *str;
- text *result;
- size_t len;
+ xmlChar *str;
+ xmltype *result;
+ size_t len;
+ xmlBufferPtr buf;
- str = xmlXPathCastNodeToString(cur);
- len = strlen((char *) str);
- result = (text *) palloc(len + VARHDRSZ);
- SET_VARSIZE(result, len + VARHDRSZ);
- memcpy(VARDATA(result), str, len);
+ if (cur->type == XML_ELEMENT_NODE)
+ {
+ buf = xmlBufferCreate();
+ xmlNodeDump(buf, NULL, cur, 0, 1);
+ result = xmlBuffer_to_xmltype(buf);
+ xmlBufferFree(buf);
+ }
+ else
+ {
+ str = xmlXPathCastNodeToString(cur);
+ len = strlen((char *) str);
+ result = (text *) palloc(len + VARHDRSZ);
+ SET_VARSIZE(result, len + VARHDRSZ);
+ memcpy(VARDATA(result), str, len);
+ }
return result;
}
@@ -2607,7 +2618,7 @@ xmlpath(PG_FUNCTION_ARGS)
{
Datum elem;
bool elemisnull = false;
- elem = PointerGetDatum(xml_xmlnodetotext(xpathobj->nodesetval->nodeTab[i]));
+ elem = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
astate = accumArrayResult(astate, elem,
elemisnull, XMLOID,
CurrentMemoryContext);
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index 189c22113b..20520d9760 100644
--- a/src/test/regress/expected/xml.out
+++ b/src/test/regress/expected/xml.out
@@ -403,10 +403,10 @@ SELECT table_name, view_definition FROM information_schema.views
-- Text XPath expressions evaluation
SELECT xmlpath('/value', data) FROM xmltest;
- xmlpath
----------
- {one}
- {two}
+ xmlpath
+----------------------
+ {one}
+ {two}
(2 rows)
SELECT xmlpath(NULL, NULL) IS NULL FROM xmltest;
@@ -431,3 +431,9 @@ SELECT xmlpath('//loc:piece/@id', 'one two three etc');
+ xmlpath
+-------------------------
+ {two,etc}
+(1 row)
+
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index 3ba6e58d2d..3709088dfd 100644
--- a/src/test/regress/expected/xml_1.out
+++ b/src/test/regress/expected/xml_1.out
@@ -212,3 +212,5 @@ SELECT xmlpath('//text()', 'number one', ARRAY[ARRAY['loc'], ARRAY['http://127.0.0.1']]);
ERROR: no XML support in this installation
+SELECT xmlpath('//b', 'one two three etc');
+ERROR: no XML support in this installation
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index 32ac15610c..1658a38036 100644
--- a/src/test/regress/sql/xml.sql
+++ b/src/test/regress/sql/xml.sql
@@ -152,3 +152,4 @@ SELECT xmlpath(NULL, NULL) IS NULL FROM xmltest;
SELECT xmlpath('', '');
SELECT xmlpath('//text()', 'number one');
SELECT xmlpath('//loc:piece/@id', 'number one', ARRAY[ARRAY['loc'], ARRAY['http://127.0.0.1']]);
+SELECT xmlpath('//b', 'one two three etc');