diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c
index 359cded..681bbee 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,115 ----
  static xmlDocPtr xml_parse(text *data, XmlOptionType xmloption_arg,
  		  bool preserve_whitespace, int encoding);
  static text *xml_xmlnodetoxmltype(xmlNodePtr cur);
+ static Datum xml_xpathobjtoxmlarray(xmlXPathObjectPtr obj);
  #endif   /* USE_LIBXML */
  
  static StringInfo query_to_xml_internal(const char *query, char *tablename,
*************** xml_xmlnodetoxmltype(xmlNodePtr cur)
*** 3291,3296 ****
--- 3292,3368 ----
  
  	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 Datum
+ xml_xpathobjtoxmlarray(xmlXPathObjectPtr xpathobj)
+ {
+ 	int			i;
+ 	Datum		datum;
+ 	char*		result_str;
+ 	ArrayBuildState *result_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)
+ 			{
+ 				for (i = 0; i < xpathobj->nodesetval->nodeNr; i++)
+ 				{
+ 					datum = PointerGetDatum(xml_xmlnodetoxmltype(xpathobj->nodesetval->nodeTab[i]));
+ 					result_astate = accumArrayResult(result_astate, datum,
+ 													 false, XMLOID,
+ 													 CurrentMemoryContext);
+ 				}
+ 			}
+ 			break;
+ 		
+ 		/* For scalar values, we encode the value in XML and return a
+ 		 * single-element array
+ 		 */
+ 		
+ 		case XPATH_BOOLEAN:
+ 			datum = BoolGetDatum(xpathobj->boolval);
+ 			result_str = map_sql_value_to_xml_value(datum, BOOLOID, true);
+ 			goto single;
+ 		
+ 		case XPATH_NUMBER:
+ 			datum = Float8GetDatum(xpathobj->boolval);
+ 			result_str = map_sql_value_to_xml_value(datum, FLOAT8OID, true);
+ 			goto single;
+ 		
+ 		case XPATH_STRING:
+ 			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));
+ 			result_astate = accumArrayResult(result_astate, datum,
+ 											 false, XMLOID,
+ 											 CurrentMemoryContext);
+ 			break;
+ 		
+ 		default:
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_INTERNAL_ERROR),
+ 					 errmsg("xpath expression result type %d is unsupported",
+ 					        xpathobj->type)));
+ 	}
+ 	
+ 	if (result_astate == NULL)
+ 		return PointerGetDatum(construct_empty_array(XMLOID));
+ 	else
+ 		return makeArrayResult(result_astate, CurrentMemoryContext);
+ }
  #endif
  
  
*************** xpath(PG_FUNCTION_ARGS)
*** 3312,3330 ****
  	text	   *xpath_expr_text = PG_GETARG_TEXT_P(0);
  	xmltype    *data = PG_GETARG_XML_P(1);
  	ArrayType  *namespaces = PG_GETARG_ARRAYTYPE_P(2);
- 	ArrayBuildState *astate = NULL;
  	xmlParserCtxtPtr ctxt = NULL;
  	xmlDocPtr	doc = NULL;
  	xmlXPathContextPtr xpathctx = NULL;
  	xmlXPathCompExprPtr xpathcomp = NULL;
  	xmlXPathObjectPtr xpathobj = NULL;
  	char	   *datastr;
  	int32		len;
  	int32		xpath_len;
  	xmlChar    *string;
  	xmlChar    *xpath_expr;
  	int			i;
- 	int			res_nitems;
  	int			ndim;
  	Datum	   *ns_names_uris;
  	bool	   *ns_names_uris_nulls;
--- 3384,3401 ----
  	text	   *xpath_expr_text = PG_GETARG_TEXT_P(0);
  	xmltype    *data = PG_GETARG_XML_P(1);
  	ArrayType  *namespaces = PG_GETARG_ARRAYTYPE_P(2);
  	xmlParserCtxtPtr ctxt = NULL;
  	xmlDocPtr	doc = NULL;
  	xmlXPathContextPtr xpathctx = NULL;
  	xmlXPathCompExprPtr xpathcomp = NULL;
  	xmlXPathObjectPtr xpathobj = NULL;
+ 	Datum		result = 0;
  	char	   *datastr;
  	int32		len;
  	int32		xpath_len;
  	xmlChar    *string;
  	xmlChar    *xpath_expr;
  	int			i;
  	int			ndim;
  	Datum	   *ns_names_uris;
  	bool	   *ns_names_uris_nulls;
*************** xpath(PG_FUNCTION_ARGS)
*** 3443,3468 ****
  		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)
! 		{
! 			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();
  	{
--- 3514,3521 ----
  		if (xpathobj == NULL)	/* TODO: reason? */
  			xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR,
  						"could not create XPath object");
! 		
! 		result = xml_xpathobjtoxmlarray(xpathobj);
  	}
  	PG_CATCH();
  	{
*************** xpath(PG_FUNCTION_ARGS)
*** 3485,3495 ****
  	xmlXPathFreeContext(xpathctx);
  	xmlFreeDoc(doc);
  	xmlFreeParserCtxt(ctxt);
! 
! 	if (res_nitems == 0)
! 		PG_RETURN_ARRAYTYPE_P(construct_empty_array(XMLOID));
! 	else
! 		PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
  #else
  	NO_XML_SUPPORT();
  	return 0;
--- 3538,3545 ----
  	xmlXPathFreeContext(xpathctx);
  	xmlFreeDoc(doc);
  	xmlFreeParserCtxt(ctxt);
! 	
! 	PG_RETURN_DATUM(result);
  #else
  	NO_XML_SUPPORT();
  	return 0;
diff --git a/src/test/regress/expected/xml.out b/src/test/regress/expected/xml.out
index ecca589..6a588cb 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,504 ****
--- 502,540 ----
   {<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 
+ -------
+  {0}
+ (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)
+ 
diff --git a/src/test/regress/sql/xml.sql b/src/test/regress/sql/xml.sql
index 086eedd..4af879d 100644
*** a/src/test/regress/sql/xml.sql
--- b/src/test/regress/sql/xml.sql
*************** SELECT xpath('', '<!-- error -->');
*** 163,165 ****
--- 163,171 ----
  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/>');
