diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 8fd954e49d6eb53b6ca4ac69cb5cfad171f6dab1..c07d0ce0adddfff2deb98789116947fd5e3dd610 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.472 2009/02/07 14:16:45 momjian Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.473 2009/03/23 21:00:38 adunstan Exp $ --> <chapter id="functions"> <title>Functions and Operators</title> @@ -8447,6 +8447,11 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; corresponding to the node set produced by the XPath expression. </para> + <para> + The second argument must be a well formed XML document. In particular, + it must have a single root node element. + </para> + <para> The third argument of the function is an array of namespace mappings. This array should be a two-dimensional array with the diff --git a/src/backend/utils/adt/xml.c b/src/backend/utils/adt/xml.c index fcfc05ba5155900b7d9821fdfca218029e98d451..f31cb02b6b8b53d2cc11a8e97097fb2ec9629606 100644 --- a/src/backend/utils/adt/xml.c +++ b/src/backend/utils/adt/xml.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.83 2009/01/07 13:44:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.84 2009/03/23 21:00:39 adunstan Exp $ * *------------------------------------------------------------------------- */ @@ -3182,8 +3182,9 @@ xml_xmlnodetoxmltype(xmlNodePtr cur) * to be the most useful one (array of XML functions plays a role of * some kind of substitution for XQuery sequences). * - * Workaround here: we parse XML data in different way to allow XPath for - * fragments (see "XPath for fragment" TODO comment inside). + * It is up to the user to ensure that the XML passed is in fact + * an XML document - XPath doesn't work easily on fragments without + * a context node being known. */ Datum xpath(PG_FUNCTION_ARGS) @@ -3258,41 +3259,13 @@ xpath(PG_FUNCTION_ARGS) xml_init(); - /* - * To handle both documents and fragments, regardless of the fact whether - * the XML datum has a single root (XML well-formedness), we wrap the XML - * datum in a dummy element (<x>...</x>) and extend the XPath expression - * accordingly. To do it, throw away the XML prolog, if any. - */ - if (len >= 5 && - xmlStrncmp((xmlChar *) datastr, (xmlChar *) "<?xml", 5) == 0) - { - i = 5; - while (i < len && - !(datastr[i - 1] == '?' && datastr[i] == '>')) - i++; - - if (i == len) - xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR, - "could not parse XML data"); - - ++i; - - datastr += i; - len -= i; - } - - string = (xmlChar *) palloc((len + 8) * sizeof(xmlChar)); - memcpy(string, "<x>", 3); - memcpy(string + 3, datastr, len); - memcpy(string + 3 + len, "</x>", 5); - len += 7; + string = (xmlChar *) palloc((len + 1) * sizeof(xmlChar)); + memcpy(string, datastr, len); + string[len] = '\0'; - xpath_expr = (xmlChar *) palloc((xpath_len + 3) * sizeof(xmlChar)); - memcpy(xpath_expr, "/x", 2); - memcpy(xpath_expr + 2, VARDATA(xpath_expr_text), xpath_len); - xpath_expr[xpath_len + 2] = '\0'; - xpath_len += 2; + xpath_expr = (xmlChar *) palloc((xpath_len +1) * sizeof(xmlChar)); + memcpy(xpath_expr, VARDATA(xpath_expr_text), xpath_len); + xpath_expr[xpath_len] = '\0'; xmlInitParser(); @@ -3307,7 +3280,7 @@ xpath(PG_FUNCTION_ARGS) doc = xmlCtxtReadMemory(ctxt, (char *) string, len, NULL, NULL, 0); if (doc == NULL) xml_ereport(ERROR, ERRCODE_INVALID_XML_DOCUMENT, - "could not parse XML data"); + "could not parse XML document"); xpathctx = xmlXPathNewContext(doc); if (xpathctx == NULL) xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY,