diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 8fd954e49d..c07d0ce0ad 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,4 +1,4 @@ - + Functions and Operators @@ -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. + + The second argument must be a well formed XML document. In particular, + it must have a single root node element. + + 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 fcfc05ba51..f31cb02b6b 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 (...) and extend the XPath expression - * accordingly. To do it, throw away the XML prolog, if any. - */ - if (len >= 5 && - xmlStrncmp((xmlChar *) datastr, (xmlChar *) "')) - i++; + string = (xmlChar *) palloc((len + 1) * sizeof(xmlChar)); + memcpy(string, datastr, len); + string[len] = '\0'; - 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, "", 3); - memcpy(string + 3, datastr, len); - memcpy(string + 3 + len, "", 5); - len += 7; - - 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,