diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 702b9e3..105d2ac 100644
*** a/src/backend/utils/adt/xml.c
--- b/src/backend/utils/adt/xml.c
*************** static bool print_xml_decl(StringInfo bu
*** 109,114 ****
--- 109,116 ----
  static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg,
  		  bool preserve_whitespace, int encoding);
  static text *xml_xmlnodetoxmltype(xmlNodePtr cur);
+ static int xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
+ 								  ArrayBuildState **astate);
  #endif   /* USE_LIBXML */
  
  static StringInfo query_to_xml_internal(const char *query, char *tablename,
*************** xml_xmlnodetoxmltype(xmlNodePtr cur)
*** 3293,3298 ****
--- 3295,3391 ----
  
  	return result;
  }
+ 
+ /*
+  * Convert XML XPath object (the result of evaluating a XPath expression)
+  * to an array of xml values. Nodesets are converted to an array containg
+  * the node's textual representation. Primitive values (float, double, string)
+  * are converted to a single-element array containg the value's string
+  * representation.
+  */
+ static int
+ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj,
+ 					   ArrayBuildState **astate)
+ {
+ 	int			i;
+ 	Datum		datum;
+ 	char*		result_str;
+ 
+ 	if (astate != NULL)
+ 		*astate = NULL;
+ 
+ 	switch (xpathobj->type) {
+ 		/* For node sets, we append all the node's textual representations
+ 		 * to the array
+ 		 */
+ 		case XPATH_NODESET:
+ 			if (xpathobj->nodesetval != NULL)
+ 			{
+ 				int nitems = 0;
+ 				
+ 				for (i = 0; i < xpathobj->nodesetval->nodeNr; i++)
+ 				{
+ 					++nitems;
+ 					if (astate == NULL)
+ 						continue;
+ 						
+ 					datum = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
+ 					*astate = accumArrayResult(*astate, datum,
+ 											   false, XMLOID,
+ 											   CurrentMemoryContext);
+ 				}
+ 				
+ 				return nitems;
+ 			}
+ 			else
+ 			{
+ 				return 0;
+ 			}
+ 		
+ 		/* For scalar values, we encode the value in XML and return a
+ 		 * single-element array
+ 		 */
+ 		
+ 		case XPATH_BOOLEAN:
+ 			if (astate == NULL)
+ 				return 1;
+ 			
+ 			datum = BoolGetDatum(xpathobj->boolval);
+ 			result_str = map_sql_value_to_xml_value(datum, BOOLOID, true);
+ 			goto single;
+ 		
+ 		case XPATH_NUMBER:
+ 			if (astate == NULL)
+ 				return 1;
+ 			
+ 			datum = Float8GetDatum(xpathobj->floatval);
+ 			result_str = map_sql_value_to_xml_value(datum, FLOAT8OID, true);
+ 			goto single;
+ 		
+ 		case XPATH_STRING:
+ 			if (astate == NULL)
+ 				return 1;
+ 
+ 			datum = CStringGetDatum((char *) xpathobj->stringval);
+ 			result_str = map_sql_value_to_xml_value(datum, CSTRINGOID, true);
+ 			goto single;
+ 		
+ 		single:
+ 			datum = PointerGetDatum(cstring_to_xmltype(result_str));
+ 			*astate = accumArrayResult(*astate, datum,
+ 									   false, XMLOID,
+ 									   CurrentMemoryContext);
+ 			return 1;
+ 		
+ 		default:
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_INTERNAL_ERROR),
+ 					 errmsg("xpath expression result type %d is unsupported",
+ 					        xpathobj->type)));
+ 			
+ 			return 0; /* Prevent compiler warning */
+ 	}
+ }
  #endif
  
  
*************** xpath_internal(text *xpath_expr_text, xm
*** 3447,3473 ****
  		if (xpathobj == NULL)	/* TODO: reason? */
  			xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR,
  						"could not create XPath object");
! 
! 		/* return empty array in cases when nothing is found */
! 		if (xpathobj->nodesetval == NULL)
! 			*res_nitems = 0;
  		else
! 			*res_nitems = xpathobj->nodesetval->nodeNr;
! 
! 		if (*res_nitems && astate)
! 		{
! 			*astate = NULL;
! 			for (i = 0; i < xpathobj->nodesetval->nodeNr; i++)
! 			{
! 				Datum		elem;
! 				bool		elemisnull = false;
! 
! 				elem = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
! 				*astate = accumArrayResult(*astate, elem,
! 										   elemisnull, XMLOID,
! 										   CurrentMemoryContext);
! 			}
! 		}
  	}
  	PG_CATCH();
  	{
--- 3540,3550 ----
  		if (xpathobj == NULL)	/* TODO: reason? */
  			xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR,
  						"could not create XPath object");
! 		
! 		if (res_nitems != NULL)
! 			*res_nitems = xml_xpathobjtoxmlarray(xpathobj, astate);
  		else
! 			xml_xpathobjtoxmlarray(xpathobj, astate);
  	}
  	PG_CATCH();
  	{
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index eaa5a74..d279522 100644
*** a/src/test/regress/expected/xml.out
--- b/src/test/regress/expected/xml.out
*************** SELECT xpath('//b', '<a>one <b>two</b> t
*** 502,507 ****
--- 502,543 ----
   {<b>two</b>,<b>etc</b>}
  (1 row)
  
+ SELECT xpath('''<<invalid>>''', '<root/>');
+            xpath           
+ ---------------------------
+  {&lt;&lt;invalid&gt;&gt;}
+ (1 row)
+ 
+ SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
+  xpath 
+ -------
+  {3}
+ (1 row)
+ 
+ SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
+   xpath  
+ ---------
+  {false}
+ (1 row)
+ 
+ SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
+  xpath  
+ --------
+  {true}
+ (1 row)
+ 
+ SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
+  xpath  
+ --------
+  {root}
+ (1 row)
+ 
+ SELECT xpath('/nosuchtag', '<root/>');
+  xpath 
+ -------
+  {}
+ (1 row)
+ 
  -- Test xmlexists and xpath_exists
  SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
   xmlexists 
*************** SELECT xmlexists('//town[text() = ''Cwmb
*** 515,520 ****
--- 551,562 ----
   t
  (1 row)
  
+ SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
+  xmlexists 
+ -----------
+  t
+ (1 row)
+ 
  SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
   xpath_exists 
  --------------
*************** SELECT xpath_exists('//town[text() = ''C
*** 527,532 ****
--- 569,580 ----
   t
  (1 row)
  
+ SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
+  xpath_exists 
+ --------------
+  t
+ (1 row)
+ 
  INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  INSERT INTO xmltest VALUES (6, '<myns:menu xmlns:myns="http://myns.com"><myns:beers><myns:name>Budvar</myns:name><myns:cost>free</myns:cost><myns:name>Carling</myns:name><myns:cost>lots</myns:cost></myns:beers></myns:menu>'::xml);
diff --git a/src/test/regress/expected/xml_1.out b/src/test/regress/expected/xml_1.out
index 711b435..dac98d2 100644
*** a/src/test/regress/expected/xml_1.out
--- b/src/test/regress/expected/xml_1.out
*************** LINE 1: SELECT xpath('//b', '<a>one <b>t
*** 456,461 ****
--- 456,497 ----
                              ^
  DETAIL:  This functionality requires the server to be built with libxml support.
  HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('''<<invalid>>''', '<root/>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('''<<invalid>>''', '<root/>');
+                                         ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
+                                    ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
+                                      ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
+                                      ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
+                                  ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath('/nosuchtag', '<root/>');
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath('/nosuchtag', '<root/>');
+                                    ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
  -- Test xmlexists and xpath_exists
  SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
  ERROR:  unsupported XML feature
*************** LINE 1: ...sts('//town[text() = ''Cwmbra
*** 469,474 ****
--- 505,516 ----
                                                               ^
  DETAIL:  This functionality requires the server to be built with libxml support.
  HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
+ ERROR:  unsupported XML feature
+ LINE 1: ...LECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>')...
+                                                              ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
  SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
  ERROR:  unsupported XML feature
  LINE 1: ...ELECT xpath_exists('//town[text() = ''Toronto'']','<towns><t...
*************** LINE 1: ...ELECT xpath_exists('//town[te
*** 481,486 ****
--- 523,534 ----
                                                               ^
  DETAIL:  This functionality requires the server to be built with libxml support.
  HINT:  You need to rebuild PostgreSQL using --with-libxml.
+ SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
+ ERROR:  unsupported XML feature
+ LINE 1: SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
+                                                  ^
+ DETAIL:  This functionality requires the server to be built with libxml support.
+ HINT:  You need to rebuild PostgreSQL using --with-libxml.
  INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  ERROR:  unsupported XML feature
  LINE 1: INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</n...
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index 717a1e7..fd9c6a7 100644
*** a/src/test/regress/sql/xml.sql
--- b/src/test/regress/sql/xml.sql
*************** SELECT xpath('', '<!-- error -->');
*** 163,174 ****
--- 163,182 ----
  SELECT xpath('//text()', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>');
  SELECT xpath('//loc:piece/@id', '<local:data xmlns:local="http://127.0.0.1"><local:piece id="1">number one</local:piece><local:piece id="2" /></local:data>', ARRAY[ARRAY['loc', 'http://127.0.0.1']]);
  SELECT xpath('//b', '<a>one <b>two</b> three <b>etc</b></a>');
+ SELECT xpath('''<<invalid>>''', '<root/>');
+ SELECT xpath('count(//*)', '<root><sub/><sub/></root>');
+ SELECT xpath('count(//*)=0', '<root><sub/><sub/></root>');
+ SELECT xpath('count(//*)=3', '<root><sub/><sub/></root>');
+ SELECT xpath('name(/*)', '<root><sub/><sub/></root>');
+ SELECT xpath('/nosuchtag', '<root/>');
  
  -- Test xmlexists and xpath_exists
  SELECT xmlexists('//town[text() = ''Toronto'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
  SELECT xmlexists('//town[text() = ''Cwmbran'']' PASSING BY REF '<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>');
+ SELECT xmlexists('count(/nosuchtag)' PASSING BY REF '<root/>');
  SELECT xpath_exists('//town[text() = ''Toronto'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
  SELECT xpath_exists('//town[text() = ''Cwmbran'']','<towns><town>Bidford-on-Avon</town><town>Cwmbran</town><town>Bristol</town></towns>'::xml);
+ SELECT xpath_exists('count(/nosuchtag)', '<root/>'::xml);
  
  INSERT INTO xmltest VALUES (4, '<menu><beers><name>Budvar</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
  INSERT INTO xmltest VALUES (5, '<menu><beers><name>Molson</name><cost>free</cost><name>Carling</name><cost>lots</cost></beers></menu>'::xml);
