Hello,

Here is the patch for contrib/xml2 (attached), that:
- renames xml_valid() to xml_is_well_formed()
- adds PG_MODULE_MAGIC; at the beginning of xpath.c
- introduces xpath_array() function
- adds some words about that function and caution about libraries to README

I understand that it's too late, but xpath_array() is pretty simple
function (and, actually, this is a tiny step to XQuery sequences).
Besides that, it is mentioned in the current TODO list and I've told
about this before. Actually, this is at least some [minor] addition for
this module for 8.2.

Let me know if I can help somehow else in this direction.

--
Best regards,
Nikolay
Index: README.xml2
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/xml2/README.xml2,v
retrieving revision 1.6
diff -u -r1.6 README.xml2
--- README.xml2	25 Aug 2006 23:45:02 -0000	1.6
+++ README.xml2	5 Sep 2006 21:51:23 -0000
@@ -21,14 +21,16 @@
 Before you begin, just check the Makefile, and then just 'make' and
 'make install'.
 
-This code requires libxml to be previously installed.
+By default, this module requires both libxml2 and libxslt installed
+on your system. If you do not have libxslt or do not want to use XSLT
+functions, you should edit Makefile to remove mentioning of XSLT.
 
 Description of functions
 ------------------------
 
 The first set of functions are straightforward XML parsing and XPath queries:
 
-xml_valid(document) RETURNS bool
+xml_is_well_formed(document) RETURNS bool
 
 This parses the document text in its parameter and returns true if the
 document is well-formed XML.
@@ -67,6 +69,12 @@
 
 This is a wrapper for the above function that uses ',' as the seperator.
 
+xpath_array(document,query) RETURNS text[]
+
+This function returns array of text values. In common case, XPath
+evaluation produces a set of values (a set of strings, a set of integers
+or a set of XML chunks). Text array returned by this functions corresponds
+to that set of values.
 
 xpath_table
 -----------
Index: pgxml.sql.in
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/xml2/pgxml.sql.in,v
retrieving revision 1.8
diff -u -r1.8 pgxml.sql.in
--- pgxml.sql.in	27 Feb 2006 16:09:49 -0000	1.8
+++ pgxml.sql.in	5 Sep 2006 21:51:23 -0000
@@ -1,6 +1,6 @@
 --SQL for XML parser
 
-CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool
+CREATE OR REPLACE FUNCTION xml_is_well_formed(text) RETURNS bool
 	AS 'MODULE_PATHNAME' LANGUAGE C STRICT IMMUTABLE;
 
 CREATE OR REPLACE FUNCTION xml_encode_special_chars(text) RETURNS text
@@ -24,6 +24,10 @@
 	AS 'MODULE_PATHNAME'
 	LANGUAGE C STRICT IMMUTABLE;
 
+-- Array returning XPath function
+CREATE OR REPLACE FUNCTION xpath_array(text,text) RETURNS _text
+	AS 'MODULE_PATHNAME' LANGUAGE C STRICT IMMUTABLE;
+
 
 CREATE OR REPLACE FUNCTION xpath_list(text,text) RETURNS text 
 AS 'SELECT xpath_list($1,$2,'','')' LANGUAGE SQL STRICT IMMUTABLE;
@@ -46,15 +50,3 @@
 	AS 'MODULE_PATHNAME'
 	LANGUAGE C STRICT STABLE;
 
--- XSLT functions
--- Delete from here to the end of the file if you are not compiling with
--- XSLT support.
-
-
-CREATE OR REPLACE FUNCTION xslt_process(text,text,text) RETURNS text 
-	AS 'MODULE_PATHNAME' LANGUAGE C STRICT VOLATILE;
-
--- the function checks for the correct argument count
-
-CREATE OR REPLACE FUNCTION xslt_process(text,text) RETURNS text 
-	AS 'MODULE_PATHNAME' LANGUAGE C STRICT IMMUTABLE;
Index: xpath.c
===================================================================
RCS file: /projects/cvsroot/pgsql/contrib/xml2/xpath.c,v
retrieving revision 1.11
diff -u -r1.11 xpath.c
--- xpath.c	23 May 2006 15:21:51 -0000	1.11
+++ xpath.c	5 Sep 2006 21:51:24 -0000
@@ -16,6 +16,8 @@
 #include <libxml/xmlerror.h>
 #include <libxml/parserInternals.h>
 
+PG_MODULE_MAGIC;
+
 /* declarations */
 
 static void *pgxml_palloc(size_t size);
@@ -30,6 +32,8 @@
 static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
 				   xmlChar * toptagname, xmlChar * septagname,
 				   xmlChar * plainsep);
+				   
+text *pgxml_node_dump_to_text(xmlNodePtr cur);
 
 text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar * toptag,
 					 xmlChar * septag, xmlChar * plainsep);
@@ -38,14 +42,14 @@
 
 static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar * xpath);
 
-
-Datum		xml_valid(PG_FUNCTION_ARGS);
+Datum		xml_is_well_formed(PG_FUNCTION_ARGS);
 Datum		xml_encode_special_chars(PG_FUNCTION_ARGS);
 Datum		xpath_nodeset(PG_FUNCTION_ARGS);
 Datum		xpath_string(PG_FUNCTION_ARGS);
 Datum		xpath_number(PG_FUNCTION_ARGS);
 Datum		xpath_bool(PG_FUNCTION_ARGS);
 Datum		xpath_list(PG_FUNCTION_ARGS);
+Datum		xpath_array(PG_FUNCTION_ARGS);
 Datum		xpath_table(PG_FUNCTION_ARGS);
 
 /* Global variables */
@@ -163,12 +167,12 @@
 
 /* Returns true if document is well-formed */
 
-PG_FUNCTION_INFO_V1(xml_valid);
+PG_FUNCTION_INFO_V1(xml_is_well_formed);
 
 Datum
-xml_valid(PG_FUNCTION_ARGS)
+xml_is_well_formed(PG_FUNCTION_ARGS)
 {
-	/* called as xml_valid(document) */
+	/* called as xml_is_well_formed(document) */
 	xmlDocPtr	doctree;
 	text	   *t = PG_GETARG_TEXT_P(0);		/* document buffer */
 	int32		docsize = VARSIZE(t) - VARHDRSZ;
@@ -513,7 +517,56 @@
 
 }
 
+/*
+ * Evaluate XPath expression and return array of XML chunks (array of text values)
+ */
+PG_FUNCTION_INFO_V1(xpath_array);
 
+Datum
+xpath_array(PG_FUNCTION_ARGS)
+{
+	xmlXPathObjectPtr 	xpathobj;
+	ArrayBuildState 	*astate = NULL;
+	xmlChar    			*xpath;
+	int					i;
+	int32				pathsize;
+	text				*xpathsupp;
+	
+	/* PG_GETARG_TEXT_P(0) is document buffer */
+	xpathsupp = PG_GETARG_TEXT_P(1);	/* XPath expression */
+	pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
+	xpath = pgxml_texttoxmlchar(xpathsupp);
+
+	xpathobj = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
+	if (xpathobj == NULL 
+		|| xpathobj->nodesetval == NULL 
+		|| xpathobj->nodesetval->nodeNr == 0)
+	{
+		/* Note, that throwing ERROR might be more proper solution
+		here (at least in one of these three cases);
+		meanwhile, keep silence here, as in other xpath_*() functions */
+		xmlCleanupParser();
+		PG_RETURN_NULL();
+	}
+
+	for (i = 0; i < xpathobj->nodesetval->nodeNr; i++)
+	{
+		xmlChar		*str;
+		text		*txt;
+		Datum		elem;
+		bool		elemisnull = false;
+		txt = pgxml_node_dump_to_text(xpathobj->nodesetval->nodeTab[i]);
+		elem = PointerGetDatum(txt);
+		astate = accumArrayResult(astate, elem,
+								  elemisnull, TEXTOID,
+								  CurrentMemoryContext);
+	}
+
+    xmlXPathFreeObject(xpathobj);
+	xmlCleanupParser();
+
+	PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
+}
 
 /* Core function to evaluate XPath query */
 
@@ -623,6 +676,27 @@
 	return xpres;
 }
 
+/* dumps XML node to text (serialization) */
+text *
+pgxml_node_dump_to_text(xmlNodePtr cur)
+{
+	xmlBufferPtr 	buf;
+	xmlChar    		*str;
+	text			*result;
+	size_t			len;
+	
+	buf = xmlBufferCreate();
+	xmlNodeDump(buf, cur->doc, cur, 1, 0);
+	str = xmlStrdup(buf->content);
+	xmlBufferFree(buf);
+	len = strlen(str);
+	result = (text *) palloc(len + VARHDRSZ);
+	VARATT_SIZEP(result) = len + VARHDRSZ;
+	memcpy(VARDATA(result), str, len);
+	
+	return result;
+}
+
 /* xpath_table is a table function. It needs some tidying (as do the
  * other functions here!
  */
---------------------------(end of broadcast)---------------------------
TIP 4: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to