Commit c9cab106 authored by Andrew Dunstan's avatar Andrew Dunstan

Remove munging of xml and xpath params to xpath(). The XML must now be a well formed XML document.

parent 10795649
<!-- $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"> <chapter id="functions">
<title>Functions and Operators</title> <title>Functions and Operators</title>
...@@ -8447,6 +8447,11 @@ SELECT xmlagg(x) FROM (SELECT * FROM test ORDER BY y DESC) AS tab; ...@@ -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. corresponding to the node set produced by the XPath expression.
</para> </para>
<para>
The second argument must be a well formed XML document. In particular,
it must have a single root node element.
</para>
<para> <para>
The third argument of the function is an array of namespace The third argument of the function is an array of namespace
mappings. This array should be a two-dimensional array with the mappings. This array should be a two-dimensional array with the
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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) ...@@ -3182,8 +3182,9 @@ xml_xmlnodetoxmltype(xmlNodePtr cur)
* to be the most useful one (array of XML functions plays a role of * to be the most useful one (array of XML functions plays a role of
* some kind of substitution for XQuery sequences). * some kind of substitution for XQuery sequences).
* *
* Workaround here: we parse XML data in different way to allow XPath for * It is up to the user to ensure that the XML passed is in fact
* fragments (see "XPath for fragment" TODO comment inside). * an XML document - XPath doesn't work easily on fragments without
* a context node being known.
*/ */
Datum Datum
xpath(PG_FUNCTION_ARGS) xpath(PG_FUNCTION_ARGS)
...@@ -3258,41 +3259,13 @@ xpath(PG_FUNCTION_ARGS) ...@@ -3258,41 +3259,13 @@ xpath(PG_FUNCTION_ARGS)
xml_init(); xml_init();
/* string = (xmlChar *) palloc((len + 1) * sizeof(xmlChar));
* To handle both documents and fragments, regardless of the fact whether memcpy(string, datastr, len);
* the XML datum has a single root (XML well-formedness), we wrap the XML string[len] = '\0';
* 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;
xpath_expr = (xmlChar *) palloc((xpath_len + 3) * sizeof(xmlChar)); xpath_expr = (xmlChar *) palloc((xpath_len +1) * sizeof(xmlChar));
memcpy(xpath_expr, "/x", 2); memcpy(xpath_expr, VARDATA(xpath_expr_text), xpath_len);
memcpy(xpath_expr + 2, VARDATA(xpath_expr_text), xpath_len); xpath_expr[xpath_len] = '\0';
xpath_expr[xpath_len + 2] = '\0';
xpath_len += 2;
xmlInitParser(); xmlInitParser();
...@@ -3307,7 +3280,7 @@ xpath(PG_FUNCTION_ARGS) ...@@ -3307,7 +3280,7 @@ xpath(PG_FUNCTION_ARGS)
doc = xmlCtxtReadMemory(ctxt, (char *) string, len, NULL, NULL, 0); doc = xmlCtxtReadMemory(ctxt, (char *) string, len, NULL, NULL, 0);
if (doc == NULL) if (doc == NULL)
xml_ereport(ERROR, ERRCODE_INVALID_XML_DOCUMENT, xml_ereport(ERROR, ERRCODE_INVALID_XML_DOCUMENT,
"could not parse XML data"); "could not parse XML document");
xpathctx = xmlXPathNewContext(doc); xpathctx = xmlXPathNewContext(doc);
if (xpathctx == NULL) if (xpathctx == NULL)
xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY, xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment