remove-contrib-xml2.patch
text/x-patch
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| configure.in | 0 | 17 |
| contrib/Makefile | 0 | 4 |
| contrib/xml2/Makefile | 0 | 21 |
| contrib/xml2/pgxml.sql.in | 0 | 86 |
| contrib/xml2/uninstall_pgxml.sql | 0 | 33 |
| contrib/xml2/xpath.c | 0 | 933 |
| contrib/xml2/xslt_proc.c | 0 | 179 |
| doc/src/sgml/contrib.sgml | 0 | 1 |
| doc/src/sgml/filelist.sgml | 0 | 1 |
| doc/src/sgml/installation.sgml | 0 | 11 |
| doc/src/sgml/install-win32.sgml | 1 | 2 |
| doc/src/sgml/xml2.sgml | 0 | 425 |
| src/include/pg_config.h.in | 0 | 7 |
| src/Makefile.global.in | 0 | 1 |
| src/tools/msvc/config_default.pl | 0 | 1 |
| src/tools/msvc/Mkvcbuild.pm | 1 | 3 |
| src/tools/msvc/Solution.pm | 2 | 3 |
diff --git a/configure.in b/configure.in
index 5a27d3a..352d7b2 100644
--- a/configure.in
+++ b/configure.in
@@ -732,15 +732,6 @@ fi
AC_SUBST(with_libxml)
#
-# XSLT
-#
-PGAC_ARG_BOOL(with, libxslt, no, [use XSLT support when building contrib/xml2],
- [AC_DEFINE([USE_LIBXSLT], 1, [Define to 1 to use XSLT support when building contrib/xml2. (--with-libxslt)])])
-
-
-AC_SUBST(with_libxslt)
-
-#
# tzdata
#
PGAC_ARG_REQ(with, system-tzdata,
@@ -943,10 +934,6 @@ if test "$with_libxml" = yes ; then
AC_CHECK_LIB(xml2, xmlSaveToBuffer, [], [AC_MSG_ERROR([library 'xml2' (version >= 2.6.23) is required for XML support])])
fi
-if test "$with_libxslt" = yes ; then
- AC_CHECK_LIB(xslt, xsltCleanupGlobals, [], [AC_MSG_ERROR([library 'xslt' is required for XSLT support])])
-fi
-
# for contrib/uuid-ossp
if test "$with_ossp_uuid" = yes ; then
AC_CHECK_LIB(ossp-uuid, uuid_export,
@@ -1051,10 +1038,6 @@ if test "$with_libxml" = yes ; then
AC_CHECK_HEADER(libxml/parser.h, [], [AC_MSG_ERROR([header file <libxml/parser.h> is required for XML support])])
fi
-if test "$with_libxslt" = yes ; then
- AC_CHECK_HEADER(libxslt/xslt.h, [], [AC_MSG_ERROR([header file <libxslt/xslt.h> is required for XSLT support])])
-fi
-
if test "$with_ldap" = yes ; then
if test "$PORTNAME" != "win32"; then
AC_CHECK_HEADERS(ldap.h, [],
diff --git a/contrib/Makefile b/contrib/Makefile
index 19d5c1b..168396c 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -51,10 +51,6 @@ ifeq ($(with_ossp_uuid),yes)
SUBDIRS += uuid-ossp
endif
-ifeq ($(with_libxml),yes)
-SUBDIRS += xml2
-endif
-
# Missing:
# start-scripts \ (does not have a makefile)
diff --git a/contrib/xml2/Makefile b/contrib/xml2/Makefile
deleted file mode 100644
index ea8636a..0000000
--- a/contrib/xml2/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-# $PostgreSQL$
-
-MODULE_big = pgxml
-
-OBJS = $(if $(filter -lxslt, $(LIBS)), xpath.o xslt_proc.o, xpath.o)
-
-SHLIB_LINK += $(filter -lxslt, $(LIBS)) $(filter -lxml2, $(LIBS))
-
-DATA_built = pgxml.sql
-DATA = uninstall_pgxml.sql
-
-ifdef USE_PGXS
-PG_CONFIG = pg_config
-PGXS := $(shell $(PG_CONFIG) --pgxs)
-include $(PGXS)
-else
-subdir = contrib/xml2
-top_builddir = ../..
-include $(top_builddir)/src/Makefile.global
-include $(top_srcdir)/contrib/contrib-global.mk
-endif
diff --git a/contrib/xml2/pgxml.sql.in b/contrib/xml2/pgxml.sql.in
deleted file mode 100644
index 139ca14..0000000
--- a/contrib/xml2/pgxml.sql.in
+++ /dev/null
@@ -1,86 +0,0 @@
-/* $PostgreSQL$ */
-
--- Adjust this setting to control where the objects get created.
-SET search_path = public;
-
---SQL for XML parser
-
-CREATE OR REPLACE FUNCTION xml_is_well_formed(text) RETURNS bool
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
--- deprecated old name for xml_is_well_formed
-CREATE OR REPLACE FUNCTION xml_valid(text) RETURNS bool
-AS 'MODULE_PATHNAME', 'xml_is_well_formed'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xml_encode_special_chars(text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_string(text,text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text,text) RETURNS text
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_number(text,text) RETURNS float4
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION xpath_bool(text,text) RETURNS boolean
-AS 'MODULE_PATHNAME'
-LANGUAGE C STRICT IMMUTABLE;
-
--- List function
-
-CREATE OR REPLACE FUNCTION xpath_list(text,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;
-
-
-
--- Wrapper functions for nodeset where no tags needed
-
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text)
-RETURNS text
-AS 'SELECT xpath_nodeset($1,$2,'''','''')'
-LANGUAGE SQL STRICT IMMUTABLE;
-
-
-CREATE OR REPLACE FUNCTION xpath_nodeset(text,text,text)
-RETURNS text
-AS 'SELECT xpath_nodeset($1,$2,'''',$3)'
-LANGUAGE SQL STRICT IMMUTABLE;
-
--- Table function
-
-CREATE OR REPLACE FUNCTION xpath_table(text,text,text,text,text)
-RETURNS setof record
-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;
diff --git a/contrib/xml2/uninstall_pgxml.sql b/contrib/xml2/uninstall_pgxml.sql
deleted file mode 100644
index ec676dc..0000000
--- a/contrib/xml2/uninstall_pgxml.sql
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $PostgreSQL$ */
-
--- Adjust this setting to control where the objects get dropped.
-SET search_path = public;
-
-DROP FUNCTION xslt_process(text,text);
-
-DROP FUNCTION xslt_process(text,text,text);
-
-DROP FUNCTION xpath_table(text,text,text,text,text);
-
-DROP FUNCTION xpath_nodeset(text,text,text);
-
-DROP FUNCTION xpath_nodeset(text,text);
-
-DROP FUNCTION xpath_list(text,text);
-
-DROP FUNCTION xpath_list(text,text,text);
-
-DROP FUNCTION xpath_bool(text,text);
-
-DROP FUNCTION xpath_number(text,text);
-
-DROP FUNCTION xpath_nodeset(text,text,text,text);
-
-DROP FUNCTION xpath_string(text,text);
-
-DROP FUNCTION xml_encode_special_chars(text);
-
--- deprecated old name for xml_is_well_formed
-DROP FUNCTION xml_valid(text);
-
-DROP FUNCTION xml_is_well_formed(text);
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c
deleted file mode 100644
index dd895b0..0000000
--- a/contrib/xml2/xpath.c
+++ /dev/null
@@ -1,933 +0,0 @@
-/*
- * $PostgreSQL$
- *
- * Parser interface for DOM-based parser (libxml) rather than
- * stream-based SAX-type parser
- */
-#include "postgres.h"
-
-#include "executor/spi.h"
-#include "fmgr.h"
-#include "funcapi.h"
-#include "lib/stringinfo.h"
-#include "miscadmin.h"
-#include "utils/builtins.h"
-
-/* libxml includes */
-
-#include <libxml/xpath.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/xmlerror.h>
-#include <libxml/parserInternals.h>
-
-
-PG_MODULE_MAGIC;
-
-/* declarations */
-
-static void *pgxml_palloc(size_t size);
-static void *pgxml_repalloc(void *ptr, size_t size);
-static void pgxml_pfree(void *ptr);
-static char *pgxml_pstrdup(const char *string);
-static void pgxml_errorHandler(void *ctxt, const char *msg,...);
-
-void elog_error(int level, char *explain, int force);
-void pgxml_parser_init(void);
-
-static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
- xmlChar *toptagname, xmlChar *septagname,
- xmlChar *plainsep);
-
-text *pgxml_result_to_text(xmlXPathObjectPtr res, xmlChar *toptag,
- xmlChar *septag, xmlChar *plainsep);
-
-xmlChar *pgxml_texttoxmlchar(text *textstring);
-
-static xmlXPathObjectPtr pgxml_xpath(text *document, xmlChar *xpath);
-
-
-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_table(PG_FUNCTION_ARGS);
-
-/* Global variables */
-char *errbuf; /* per line error buffer */
-char *pgxml_errorMsg = NULL; /* overall error message */
-
-#define ERRBUF_SIZE 200
-
-/* memory handling passthrough functions (e.g. palloc, pstrdup are
- currently macros, and the others might become so...) */
-
-static void *
-pgxml_palloc(size_t size)
-{
-/* elog(DEBUG1,"Alloc %d in CMC %p",size,CurrentMemoryContext); */
- return palloc(size);
-}
-
-static void *
-pgxml_repalloc(void *ptr, size_t size)
-{
-/* elog(DEBUG1,"ReAlloc in CMC %p",CurrentMemoryContext);*/
- return repalloc(ptr, size);
-}
-
-static void
-pgxml_pfree(void *ptr)
-{
-/* elog(DEBUG1,"Free in CMC %p",CurrentMemoryContext); */
- pfree(ptr);
-}
-
-static char *
-pgxml_pstrdup(const char *string)
-{
- return pstrdup(string);
-}
-
-/* The error handling function. This formats an error message and sets
- * a flag - an ereport will be issued prior to return
- */
-
-static void
-pgxml_errorHandler(void *ctxt, const char *msg,...)
-{
- va_list args;
-
- va_start(args, msg);
- vsnprintf(errbuf, ERRBUF_SIZE, msg, args);
- va_end(args);
- /* Now copy the argument across */
- if (pgxml_errorMsg == NULL)
- pgxml_errorMsg = pstrdup(errbuf);
- else
- {
- int32 xsize = strlen(pgxml_errorMsg);
-
- pgxml_errorMsg = repalloc(pgxml_errorMsg,
- (size_t) (xsize + strlen(errbuf) + 1));
- strncpy(&pgxml_errorMsg[xsize - 1], errbuf, strlen(errbuf));
- pgxml_errorMsg[xsize + strlen(errbuf) - 1] = '\0';
-
- }
- memset(errbuf, 0, ERRBUF_SIZE);
-}
-
-/* This function reports the current message at the level specified */
-void
-elog_error(int level, char *explain, int force)
-{
- if (force || (pgxml_errorMsg != NULL))
- {
- if (pgxml_errorMsg == NULL)
- {
- ereport(level, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
- errmsg("%s", explain)));
- }
- else
- {
- ereport(level, (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION),
- errmsg("%s:%s", explain, pgxml_errorMsg)));
- pfree(pgxml_errorMsg);
- }
- }
-}
-
-void
-pgxml_parser_init()
-{
- /*
- * This code could also set parser settings from user-supplied info.
- * Quite how these settings are made is another matter :)
- */
-
- xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
- xmlInitParser();
-
- xmlSetGenericErrorFunc(NULL, pgxml_errorHandler);
-
- xmlSubstituteEntitiesDefault(1);
- xmlLoadExtDtdDefaultValue = 1;
-
- pgxml_errorMsg = NULL;
-
- errbuf = palloc(200);
- memset(errbuf, 0, 200);
-
-}
-
-
-/* Returns true if document is well-formed */
-
-PG_FUNCTION_INFO_V1(xml_is_well_formed);
-
-Datum
-xml_is_well_formed(PG_FUNCTION_ARGS)
-{
- /* called as xml_is_well_formed(document) */
- xmlDocPtr doctree;
- text *t = PG_GETARG_TEXT_P(0); /* document buffer */
- int32 docsize = VARSIZE(t) - VARHDRSZ;
-
- pgxml_parser_init();
-
- doctree = xmlParseMemory((char *) VARDATA(t), docsize);
- if (doctree == NULL)
- {
- xmlCleanupParser();
- PG_RETURN_BOOL(false); /* i.e. not well-formed */
- }
- xmlCleanupParser();
- xmlFreeDoc(doctree);
- PG_RETURN_BOOL(true);
-}
-
-
-/* Encodes special characters (<, >, &, " and \r) as XML entities */
-
-PG_FUNCTION_INFO_V1(xml_encode_special_chars);
-
-Datum
-xml_encode_special_chars(PG_FUNCTION_ARGS)
-{
- text *tin = PG_GETARG_TEXT_P(0);
- text *tout;
- xmlChar *ts,
- *tt;
-
- ts = pgxml_texttoxmlchar(tin);
-
- tt = xmlEncodeSpecialChars(NULL, ts);
-
- pfree(ts);
-
- tout = cstring_to_text((char *) tt);
-
- xmlFree(tt);
-
- PG_RETURN_TEXT_P(tout);
-}
-
-static xmlChar
- *
-pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
- xmlChar *toptagname,
- xmlChar *septagname,
- xmlChar *plainsep)
-{
- /* Function translates a nodeset into a text representation */
-
- /*
- * iterates over each node in the set and calls xmlNodeDump to write it to
- * an xmlBuffer -from which an xmlChar * string is returned.
- */
-
- /* each representation is surrounded by <tagname> ... </tagname> */
-
- /*
- * plainsep is an ordinary (not tag) seperator - if used, then nodes are
- * cast to string as output method
- */
-
-
- xmlBufferPtr buf;
- xmlChar *result;
- int i;
-
- buf = xmlBufferCreate();
-
- if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
- {
- xmlBufferWriteChar(buf, "<");
- xmlBufferWriteCHAR(buf, toptagname);
- xmlBufferWriteChar(buf, ">");
- }
- if (nodeset != NULL)
- {
- for (i = 0; i < nodeset->nodeNr; i++)
- {
-
- if (plainsep != NULL)
- {
- xmlBufferWriteCHAR(buf,
- xmlXPathCastNodeToString(nodeset->nodeTab[i]));
-
- /* If this isn't the last entry, write the plain sep. */
- if (i < (nodeset->nodeNr) - 1)
- xmlBufferWriteChar(buf, (char *) plainsep);
- }
- else
- {
-
-
- if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
- {
- xmlBufferWriteChar(buf, "<");
- xmlBufferWriteCHAR(buf, septagname);
- xmlBufferWriteChar(buf, ">");
- }
- xmlNodeDump(buf,
- nodeset->nodeTab[i]->doc,
- nodeset->nodeTab[i],
- 1, 0);
-
- if ((septagname != NULL) && (xmlStrlen(septagname) > 0))
- {
- xmlBufferWriteChar(buf, "</");
- xmlBufferWriteCHAR(buf, septagname);
- xmlBufferWriteChar(buf, ">");
- }
- }
- }
- }
-
- if ((toptagname != NULL) && (xmlStrlen(toptagname) > 0))
- {
- xmlBufferWriteChar(buf, "</");
- xmlBufferWriteCHAR(buf, toptagname);
- xmlBufferWriteChar(buf, ">");
- }
- result = xmlStrdup(buf->content);
- xmlBufferFree(buf);
- return result;
-}
-
-
-/* Translate a PostgreSQL "varlena" -i.e. a variable length parameter
- * into the libxml2 representation
- */
-
-xmlChar *
-pgxml_texttoxmlchar(text *textstring)
-{
- return (xmlChar *) text_to_cstring(textstring);
-}
-
-/* Public visible XPath functions */
-
-/* This is a "raw" xpath function. Check that it returns child elements
- * properly
- */
-
-PG_FUNCTION_INFO_V1(xpath_nodeset);
-
-Datum
-xpath_nodeset(PG_FUNCTION_ARGS)
-{
- xmlChar *xpath,
- *toptag,
- *septag;
- int32 pathsize;
- text
- *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
- septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
-
- xpath = pgxml_texttoxmlchar(xpathsupp);
-
- xpres = pgxml_result_to_text(
- pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- toptag, septag, NULL);
-
- /* xmlCleanupParser(); done by result_to_text routine */
- pfree(xpath);
-
- if (xpres == NULL)
- PG_RETURN_NULL();
- PG_RETURN_TEXT_P(xpres);
-}
-
-/* The following function is almost identical, but returns the elements in */
-/* a list. */
-
-PG_FUNCTION_INFO_V1(xpath_list);
-
-Datum
-xpath_list(PG_FUNCTION_ARGS)
-{
- xmlChar *xpath,
- *plainsep;
- int32 pathsize;
- text
- *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- plainsep = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
-
- xpath = pgxml_texttoxmlchar(xpathsupp);
-
- xpres = pgxml_result_to_text(
- pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- NULL, NULL, plainsep);
-
- /* xmlCleanupParser(); done by result_to_text routine */
- pfree(xpath);
-
- if (xpres == NULL)
- PG_RETURN_NULL();
- PG_RETURN_TEXT_P(xpres);
-}
-
-
-PG_FUNCTION_INFO_V1(xpath_string);
-
-Datum
-xpath_string(PG_FUNCTION_ARGS)
-{
- xmlChar *xpath;
- int32 pathsize;
- text
- *xpathsupp,
- *xpres;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
-
- /*
- * We encapsulate the supplied path with "string()" = 8 chars + 1 for NUL
- * at end
- */
- /* We could try casting to string using the libxml function? */
-
- xpath = (xmlChar *) palloc(pathsize + 9);
- memcpy((char *) (xpath + 7), VARDATA(xpathsupp), pathsize);
- strncpy((char *) xpath, "string(", 7);
- xpath[pathsize + 7] = ')';
- xpath[pathsize + 8] = '\0';
-
- xpres = pgxml_result_to_text(
- pgxml_xpath(PG_GETARG_TEXT_P(0), xpath),
- NULL, NULL, NULL);
-
- xmlCleanupParser();
- pfree(xpath);
-
- if (xpres == NULL)
- PG_RETURN_NULL();
- PG_RETURN_TEXT_P(xpres);
-}
-
-
-PG_FUNCTION_INFO_V1(xpath_number);
-
-Datum
-xpath_number(PG_FUNCTION_ARGS)
-{
- xmlChar *xpath;
- int32 pathsize;
- text
- *xpathsupp;
-
- float4 fRes;
-
- xmlXPathObjectPtr res;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
-
- xpath = pgxml_texttoxmlchar(xpathsupp);
-
- res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
- pfree(xpath);
-
- if (res == NULL)
- {
- xmlCleanupParser();
- PG_RETURN_NULL();
- }
-
- fRes = xmlXPathCastToNumber(res);
- xmlCleanupParser();
- if (xmlXPathIsNaN(fRes))
- PG_RETURN_NULL();
-
- PG_RETURN_FLOAT4(fRes);
-
-}
-
-
-PG_FUNCTION_INFO_V1(xpath_bool);
-
-Datum
-xpath_bool(PG_FUNCTION_ARGS)
-{
- xmlChar *xpath;
- int32 pathsize;
- text
- *xpathsupp;
-
- int bRes;
-
- xmlXPathObjectPtr res;
-
- /* PG_GETARG_TEXT_P(0) is document buffer */
- xpathsupp = PG_GETARG_TEXT_P(1); /* XPath expression */
-
- pathsize = VARSIZE(xpathsupp) - VARHDRSZ;
-
- xpath = pgxml_texttoxmlchar(xpathsupp);
-
- res = pgxml_xpath(PG_GETARG_TEXT_P(0), xpath);
- pfree(xpath);
-
- if (res == NULL)
- {
- xmlCleanupParser();
- PG_RETURN_BOOL(false);
- }
-
- bRes = xmlXPathCastToBoolean(res);
- xmlCleanupParser();
- PG_RETURN_BOOL(bRes);
-
-}
-
-
-
-/* Core function to evaluate XPath query */
-
-xmlXPathObjectPtr
-pgxml_xpath(text *document, xmlChar *xpath)
-{
-
- xmlDocPtr doctree;
- xmlXPathContextPtr ctxt;
- xmlXPathObjectPtr res;
-
- xmlXPathCompExprPtr comppath;
-
- int32 docsize;
-
-
- docsize = VARSIZE(document) - VARHDRSZ;
-
- pgxml_parser_init();
-
- doctree = xmlParseMemory((char *) VARDATA(document), docsize);
- if (doctree == NULL)
- { /* not well-formed */
- return NULL;
- }
-
- ctxt = xmlXPathNewContext(doctree);
- ctxt->node = xmlDocGetRootElement(doctree);
-
-
- /* compile the path */
- comppath = xmlXPathCompile(xpath);
- if (comppath == NULL)
- {
- xmlCleanupParser();
- xmlFreeDoc(doctree);
- elog_error(ERROR, "XPath Syntax Error", 1);
-
- return NULL;
- }
-
- /* Now evaluate the path expression. */
- res = xmlXPathCompiledEval(comppath, ctxt);
- xmlXPathFreeCompExpr(comppath);
-
- if (res == NULL)
- {
- xmlXPathFreeContext(ctxt);
- /* xmlCleanupParser(); */
- xmlFreeDoc(doctree);
-
- return NULL;
- }
- /* xmlFreeDoc(doctree); */
- return res;
-}
-
-text
- *
-pgxml_result_to_text(xmlXPathObjectPtr res,
- xmlChar *toptag,
- xmlChar *septag,
- xmlChar *plainsep)
-{
- xmlChar *xpresstr;
- text *xpres;
-
- if (res == NULL)
- {
- xmlCleanupParser();
- return NULL;
- }
- switch (res->type)
- {
- case XPATH_NODESET:
- xpresstr = pgxmlNodeSetToText(res->nodesetval,
- toptag,
- septag, plainsep);
- break;
-
- case XPATH_STRING:
- xpresstr = xmlStrdup(res->stringval);
- break;
-
- default:
- elog(NOTICE, "unsupported XQuery result: %d", res->type);
- xpresstr = xmlStrdup((const xmlChar *) "<unsupported/>");
- }
-
-
- /* Now convert this result back to text */
- xpres = cstring_to_text((char *) xpresstr);
-
- /* Free various storage */
- xmlCleanupParser();
- /* xmlFreeDoc(doctree); -- will die at end of tuple anyway */
-
- xmlFree(xpresstr);
-
- elog_error(ERROR, "XPath error", 0);
-
-
- return xpres;
-}
-
-/* xpath_table is a table function. It needs some tidying (as do the
- * other functions here!
- */
-
-PG_FUNCTION_INFO_V1(xpath_table);
-
-Datum
-xpath_table(PG_FUNCTION_ARGS)
-{
-/* SPI (input tuple) support */
- SPITupleTable *tuptable;
- HeapTuple spi_tuple;
- TupleDesc spi_tupdesc;
-
-/* Output tuple (tuplestore) support */
- Tuplestorestate *tupstore = NULL;
- TupleDesc ret_tupdesc;
- HeapTuple ret_tuple;
-
- ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- AttInMetadata *attinmeta;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
-/* Function parameters */
- char *pkeyfield = text_to_cstring(PG_GETARG_TEXT_PP(0));
- char *xmlfield = text_to_cstring(PG_GETARG_TEXT_PP(1));
- char *relname = text_to_cstring(PG_GETARG_TEXT_PP(2));
- char *xpathset = text_to_cstring(PG_GETARG_TEXT_PP(3));
- char *condition = text_to_cstring(PG_GETARG_TEXT_PP(4));
-
- char **values;
- xmlChar **xpaths;
- char *pos;
- const char *pathsep = "|";
-
- int numpaths;
- int ret;
- int proc;
- int i;
- int j;
- int rownr; /* For issuing multiple rows from one original
- * document */
- int had_values; /* To determine end of nodeset results */
-
- StringInfoData query_buf;
-
- /* We only have a valid tuple description in table function mode */
- if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (rsinfo->expectedDesc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("xpath_table must be called as a table function")));
-
- /*
- * We want to materialise because it means that we don't have to carry
- * libxml2 parser state between invocations of this function
- */
- if (!(rsinfo->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("xpath_table requires Materialize mode, but it is not "
- "allowed in this context")));
-
- /*
- * The tuplestore must exist in a higher context than this function call
- * (per_query_ctx is used)
- */
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- /*
- * Create the tuplestore - work_mem is the max in-memory size before a
- * file is created on disk to hold it.
- */
- tupstore =
- tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
-
- MemoryContextSwitchTo(oldcontext);
-
- /* get the requested return tuple description */
- ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
-
- /*
- * At the moment we assume that the returned attributes make sense for the
- * XPath specififed (i.e. we trust the caller). It's not fatal if they get
- * it wrong - the input function for the column type will raise an error
- * if the path result can't be converted into the correct binary
- * representation.
- */
-
- attinmeta = TupleDescGetAttInMetadata(ret_tupdesc);
-
- /* Set return mode and allocate value space. */
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setDesc = ret_tupdesc;
-
- values = (char **) palloc(ret_tupdesc->natts * sizeof(char *));
-
- xpaths = (xmlChar **) palloc(ret_tupdesc->natts * sizeof(xmlChar *));
-
- /* Split XPaths. xpathset is a writable CString. */
-
- /* Note that we stop splitting once we've done all needed for tupdesc */
-
- numpaths = 0;
- pos = xpathset;
- do
- {
- xpaths[numpaths] = (xmlChar *) pos;
- pos = strstr(pos, pathsep);
- if (pos != NULL)
- {
- *pos = '\0';
- pos++;
- }
- numpaths++;
- } while ((pos != NULL) && (numpaths < (ret_tupdesc->natts - 1)));
-
- /* Now build query */
- initStringInfo(&query_buf);
-
- /* Build initial sql statement */
- appendStringInfo(&query_buf, "SELECT %s, %s FROM %s WHERE %s",
- pkeyfield,
- xmlfield,
- relname,
- condition
- );
-
-
- if ((ret = SPI_connect()) < 0)
- elog(ERROR, "xpath_table: SPI_connect returned %d", ret);
-
- if ((ret = SPI_exec(query_buf.data, 0)) != SPI_OK_SELECT)
- elog(ERROR, "xpath_table: SPI execution failed for query %s", query_buf.data);
-
- proc = SPI_processed;
- /* elog(DEBUG1,"xpath_table: SPI returned %d rows",proc); */
- tuptable = SPI_tuptable;
- spi_tupdesc = tuptable->tupdesc;
-
-/* Switch out of SPI context */
- MemoryContextSwitchTo(oldcontext);
-
-
-/* Check that SPI returned correct result. If you put a comma into one of
- * the function parameters, this will catch it when the SPI query returns
- * e.g. 3 columns.
- */
-
- if (spi_tupdesc->natts != 2)
- {
- ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("expression returning multiple columns is not valid in parameter list"),
- errdetail("Expected two columns in SPI result, got %d.", spi_tupdesc->natts)));
- }
-
-/* Setup the parser. Beware that this must happen in the same context as the
- * cleanup - which means that any error from here on must do cleanup to
- * ensure that the entity table doesn't get freed by being out of context.
- */
- pgxml_parser_init();
-
- /* For each row i.e. document returned from SPI */
- for (i = 0; i < proc; i++)
- {
- char *pkey;
- char *xmldoc;
-
- xmlDocPtr doctree;
- xmlXPathContextPtr ctxt;
- xmlXPathObjectPtr res;
- xmlChar *resstr;
-
-
- xmlXPathCompExprPtr comppath;
-
- /* Extract the row data as C Strings */
- spi_tuple = tuptable->vals[i];
- pkey = SPI_getvalue(spi_tuple, spi_tupdesc, 1);
- xmldoc = SPI_getvalue(spi_tuple, spi_tupdesc, 2);
-
- /*
- * Clear the values array, so that not-well-formed documents return
- * NULL in all columns.
- */
-
- /* Note that this also means that spare columns will be NULL. */
- for (j = 0; j < ret_tupdesc->natts; j++)
- values[j] = NULL;
-
- /* Insert primary key */
- values[0] = pkey;
-
- /* Parse the document */
- if (xmldoc)
- doctree = xmlParseMemory(xmldoc, strlen(xmldoc));
- else /* treat NULL as not well-formed */
- doctree = NULL;
-
- if (doctree == NULL)
- {
- /* not well-formed, so output all-NULL tuple */
- ret_tuple = BuildTupleFromCStrings(attinmeta, values);
- tuplestore_puttuple(tupstore, ret_tuple);
- heap_freetuple(ret_tuple);
- }
- else
- {
- /* New loop here - we have to deal with nodeset results */
- rownr = 0;
-
- do
- {
- /* Now evaluate the set of xpaths. */
- had_values = 0;
- for (j = 0; j < numpaths; j++)
- {
-
- ctxt = xmlXPathNewContext(doctree);
- ctxt->node = xmlDocGetRootElement(doctree);
- xmlSetGenericErrorFunc(ctxt, pgxml_errorHandler);
-
- /* compile the path */
- comppath = xmlXPathCompile(xpaths[j]);
- if (comppath == NULL)
- {
- xmlCleanupParser();
- xmlFreeDoc(doctree);
-
- elog_error(ERROR, "XPath Syntax Error", 1);
-
- PG_RETURN_NULL(); /* Keep compiler happy */
- }
-
- /* Now evaluate the path expression. */
- res = xmlXPathCompiledEval(comppath, ctxt);
- xmlXPathFreeCompExpr(comppath);
-
- if (res != NULL)
- {
- switch (res->type)
- {
- case XPATH_NODESET:
- /* We see if this nodeset has enough nodes */
- if ((res->nodesetval != NULL) && (rownr < res->nodesetval->nodeNr))
- {
- resstr =
- xmlXPathCastNodeToString(res->nodesetval->nodeTab[rownr]);
- had_values = 1;
- }
- else
- resstr = NULL;
-
- break;
-
- case XPATH_STRING:
- resstr = xmlStrdup(res->stringval);
- break;
-
- default:
- elog(NOTICE, "unsupported XQuery result: %d", res->type);
- resstr = xmlStrdup((const xmlChar *) "<unsupported/>");
- }
-
-
- /*
- * Insert this into the appropriate column in the
- * result tuple.
- */
- values[j + 1] = (char *) resstr;
- }
- xmlXPathFreeContext(ctxt);
- }
- /* Now add the tuple to the output, if there is one. */
- if (had_values)
- {
- ret_tuple = BuildTupleFromCStrings(attinmeta, values);
- tuplestore_puttuple(tupstore, ret_tuple);
- heap_freetuple(ret_tuple);
- }
-
- rownr++;
-
- } while (had_values);
-
- }
-
- xmlFreeDoc(doctree);
-
- if (pkey)
- pfree(pkey);
- if (xmldoc)
- pfree(xmldoc);
- }
-
- xmlCleanupParser();
-/* Needed to flag completeness in 7.3.1. 7.4 defines it as a no-op. */
- tuplestore_donestoring(tupstore);
-
- SPI_finish();
-
- rsinfo->setResult = tupstore;
-
- /*
- * SFRM_Materialize mode expects us to return a NULL Datum. The actual
- * tuples are in our tuplestore and passed back through rsinfo->setResult.
- * rsinfo->setDesc is set to the tuple description that we actually used
- * to build our tuples with, so the caller can verify we did what it was
- * expecting.
- */
- return (Datum) 0;
-
-}
diff --git a/contrib/xml2/xslt_proc.c b/contrib/xml2/xslt_proc.c
deleted file mode 100644
index 798e688..0000000
--- a/contrib/xml2/xslt_proc.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * $PostgreSQL$
- *
- * XSLT processing functions (requiring libxslt)
- *
- * John Gray, for Torchbox 2003-04-01
- */
-#include "postgres.h"
-
-#include "executor/spi.h"
-#include "fmgr.h"
-#include "funcapi.h"
-#include "miscadmin.h"
-#include "utils/builtins.h"
-
-/* libxml includes */
-
-#include <libxml/xpath.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-/* libxslt includes */
-
-#include <libxslt/xslt.h>
-#include <libxslt/xsltInternals.h>
-#include <libxslt/transform.h>
-#include <libxslt/xsltutils.h>
-
-
-/* declarations to come from xpath.c */
-extern void elog_error(int level, char *explain, int force);
-extern void pgxml_parser_init();
-extern xmlChar *pgxml_texttoxmlchar(text *textstring);
-
-/* local defs */
-static void parse_params(const char **params, text *paramstr);
-
-Datum xslt_process(PG_FUNCTION_ARGS);
-
-
-#define MAXPARAMS 20 /* must be even, see parse_params() */
-
-
-PG_FUNCTION_INFO_V1(xslt_process);
-
-Datum
-xslt_process(PG_FUNCTION_ARGS)
-{
- text *doct = PG_GETARG_TEXT_P(0);
- text *ssheet = PG_GETARG_TEXT_P(1);
- text *paramstr;
- const char *params[MAXPARAMS + 1]; /* +1 for the terminator */
- xsltStylesheetPtr stylesheet = NULL;
- xmlDocPtr doctree;
- xmlDocPtr restree;
- xmlDocPtr ssdoc = NULL;
- xmlChar *resstr;
- int resstat;
- int reslen;
-
- if (fcinfo->nargs == 3)
- {
- paramstr = PG_GETARG_TEXT_P(2);
- parse_params(params, paramstr);
- }
- else
- /* No parameters */
- params[0] = NULL;
-
- /* Setup parser */
- pgxml_parser_init();
-
- /* Check to see if document is a file or a literal */
-
- if (VARDATA(doct)[0] == '<')
- doctree = xmlParseMemory((char *) VARDATA(doct), VARSIZE(doct) - VARHDRSZ);
- else
- doctree = xmlParseFile(text_to_cstring(doct));
-
- if (doctree == NULL)
- {
- xmlCleanupParser();
- elog_error(ERROR, "error parsing XML document", 0);
-
- PG_RETURN_NULL();
- }
-
- /* Same for stylesheet */
- if (VARDATA(ssheet)[0] == '<')
- {
- ssdoc = xmlParseMemory((char *) VARDATA(ssheet),
- VARSIZE(ssheet) - VARHDRSZ);
- if (ssdoc == NULL)
- {
- xmlFreeDoc(doctree);
- xmlCleanupParser();
- elog_error(ERROR, "error parsing stylesheet as XML document", 0);
- PG_RETURN_NULL();
- }
-
- stylesheet = xsltParseStylesheetDoc(ssdoc);
- }
- else
- stylesheet = xsltParseStylesheetFile((xmlChar *) text_to_cstring(ssheet));
-
-
- if (stylesheet == NULL)
- {
- xmlFreeDoc(doctree);
- xsltCleanupGlobals();
- xmlCleanupParser();
- elog_error(ERROR, "failed to parse stylesheet", 0);
- PG_RETURN_NULL();
- }
-
- restree = xsltApplyStylesheet(stylesheet, doctree, params);
- resstat = xsltSaveResultToString(&resstr, &reslen, restree, stylesheet);
-
- xsltFreeStylesheet(stylesheet);
- xmlFreeDoc(restree);
- xmlFreeDoc(doctree);
-
- xsltCleanupGlobals();
- xmlCleanupParser();
-
- if (resstat < 0)
- PG_RETURN_NULL();
-
- PG_RETURN_TEXT_P(cstring_to_text_with_len((char *) resstr, reslen));
-}
-
-
-static void
-parse_params(const char **params, text *paramstr)
-{
- char *pos;
- char *pstr;
- int i;
- char *nvsep = "=";
- char *itsep = ",";
-
- pstr = text_to_cstring(paramstr);
-
- pos = pstr;
-
- for (i = 0; i < MAXPARAMS; i++)
- {
- params[i] = pos;
- pos = strstr(pos, nvsep);
- if (pos != NULL)
- {
- *pos = '\0';
- pos++;
- }
- else
- {
- /* No equal sign, so ignore this "parameter" */
- /* We'll reset params[i] to NULL below the loop */
- break;
- }
- /* Value */
- i++;
- /* since MAXPARAMS is even, we still have i < MAXPARAMS */
- params[i] = pos;
- pos = strstr(pos, itsep);
- if (pos != NULL)
- {
- *pos = '\0';
- pos++;
- }
- else
- {
- i++;
- break;
- }
- }
-
- params[i] = NULL;
-}
diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml
index cd8775d..00b2ce5 100644
--- a/doc/src/sgml/contrib.sgml
+++ b/doc/src/sgml/contrib.sgml
@@ -117,6 +117,5 @@ psql -d dbname -f <replaceable>SHAREDIR</>/contrib/<replaceable>module</>.sql
&unaccent;
&uuid-ossp;
&vacuumlo;
- &xml2;
</appendix>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 4d2a0d7..204daba 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -130,7 +130,6 @@
<!entity unaccent SYSTEM "unaccent.sgml">
<!entity uuid-ossp SYSTEM "uuid-ossp.sgml">
<!entity vacuumlo SYSTEM "vacuumlo.sgml">
-<!entity xml2 SYSTEM "xml2.sgml">
<!-- appendixes -->
<!entity contacts SYSTEM "contacts.sgml">
diff --git a/doc/src/sgml/install-win32.sgml b/doc/src/sgml/install-win32.sgml
index a6b97f4..28814be 100644
--- a/doc/src/sgml/install-win32.sgml
+++ b/doc/src/sgml/install-win32.sgml
@@ -212,8 +212,7 @@
</varlistentry>
<varlistentry>
- <term><productname>libxml2</productname> and
- <productname>libxslt</productname></term>
+ <term><productname>libxml2</productname></term>
<listitem><para>
Required for XML support. Binaries can be downloaded from
<ulink url="http://zlatkovic.com/pub/libxml"></> or source from
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index 30041ad..4d5a427 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1027,17 +1027,6 @@ su - postgres
</varlistentry>
<varlistentry>
- <term><option>--with-libxslt</option></term>
- <listitem>
- <para>
- Use libxslt when building <filename>contrib/xml2</>.
- <filename>contrib/xml2</> relies on this library to perform
- XSL transformations of XML.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
<term><option>--disable-integer-datetimes</option></term>
<listitem>
<para>
diff --git a/doc/src/sgml/xml2.sgml b/doc/src/sgml/xml2.sgml
deleted file mode 100644
index 3507684..0000000
--- a/doc/src/sgml/xml2.sgml
+++ /dev/null
@@ -1,425 +0,0 @@
-<!-- $PostgreSQL$ -->
-
-<sect1 id="xml2">
- <title>xml2</title>
-
- <indexterm zone="xml2">
- <primary>xml2</primary>
- </indexterm>
-
- <para>
- The <filename>xml2</> module provides XPath querying and
- XSLT functionality.
- </para>
-
- <sect2>
- <title>Deprecation notice</title>
-
- <para>
- From <productname>PostgreSQL</> 8.3 on, there is XML-related
- functionality based on the SQL/XML standard in the core server.
- That functionality covers XML syntax checking and XPath queries,
- which is what this module does, and more, but the API is
- not at all compatible. It is planned that this module will be
- removed in PostgreSQL 8.4 in favor of the newer standard API, so
- you are encouraged to try converting your applications. If you
- find that some of the functionality of this module is not
- available in an adequate form with the newer API, please explain
- your issue to pgsql-hackers@postgresql.org so that the deficiency
- can be addressed.
- </para>
- </sect2>
-
- <sect2>
- <title>Description of functions</title>
-
- <para>
- <xref linkend="xml2-functions-table"> shows the functions provided by this module.
- These functions provide straightforward XML parsing and XPath queries.
- All arguments are of type <type>text</>, so for brevity that is not shown.
- </para>
-
- <table id="xml2-functions-table">
- <title>Functions</title>
- <tgroup cols="2">
- <tbody>
- <row>
- <entry>
- <synopsis>
- xml_is_well_formed(document) returns bool
- </synopsis>
- </entry>
- <entry>
- <para>
- This parses the document text in its parameter and returns true if the
- document is well-formed XML. (Note: before PostgreSQL 8.2, this
- function was called <function>xml_valid()</>. That is the wrong name
- since validity and well-formedness have different meanings in XML.
- The old name is still available, but is deprecated.)
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_string(document,query) returns text
- xpath_number(document,query) returns float4
- xpath_bool(document,query) returns bool
- </synopsis>
- </entry>
- <entry>
- <para>
- These functions evaluate the XPath query on the supplied document, and
- cast the result to the specified type.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_nodeset(document,query,toptag,itemtag) returns text
- </synopsis>
- </entry>
- <entry>
- <para>
- This evaluates query on document and wraps the result in XML tags. If
- the result is multivalued, the output will look like:
- </para>
- <literal>
- <toptag>
- <itemtag>Value 1 which could be an XML fragment</itemtag>
- <itemtag>Value 2....</itemtag>
- </toptag>
- </literal>
- <para>
- If either toptag or itemtag is an empty string, the relevant tag is omitted.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_nodeset(document,query) returns text
- </synopsis>
- </entry>
- <entry>
- <para>
- Like xpath_nodeset(document,query,toptag,itemtag) but result omits both tags.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_nodeset(document,query,itemtag) returns text
- </synopsis>
- </entry>
- <entry>
- <para>
- Like xpath_nodeset(document,query,toptag,itemtag) but result omits toptag.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_list(document,query,separator) returns text
- </synopsis>
- </entry>
- <entry>
- <para>
- This function returns multiple values separated by the specified
- separator, for example <literal>Value 1,Value 2,Value 3</> if
- separator is <literal>,</>.
- </para>
- </entry>
- </row>
- <row>
- <entry>
- <synopsis>
- xpath_list(document,query) returns text
- </synopsis>
- </entry>
- <entry>
- This is a wrapper for the above function that uses <literal>,</>
- as the separator.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
- </sect2>
-
- <sect2>
- <title><literal>xpath_table</literal></title>
-
- <synopsis>
- xpath_table(text key, text document, text relation, text xpaths, text criteria) returns setof record
- </synopsis>
-
- <para>
- <function>xpath_table</> is a table function that evaluates a set of XPath
- queries on each of a set of documents and returns the results as a
- table. The primary key field from the original document table is returned
- as the first column of the result so that the result set
- can readily be used in joins.
- </para>
-
- <table>
- <title>Parameters</title>
- <tgroup cols="2">
- <tbody>
- <row>
- <entry><parameter>key</parameter></entry>
- <entry>
- <para>
- the name of the <quote>key</> field — this is just a field to be used as
- the first column of the output table, i.e., it identifies the record from
- which each output row came (see note below about multiple values)
- </para>
- </entry>
- </row>
- <row>
- <entry><parameter>document</parameter></entry>
- <entry>
- <para>
- the name of the field containing the XML document
- </para>
- </entry>
- </row>
- <row>
- <entry><parameter>relation</parameter></entry>
- <entry>
- <para>
- the name of the table or view containing the documents
- </para>
- </entry>
- </row>
- <row>
- <entry><parameter>xpaths</parameter></entry>
- <entry>
- <para>
- one or more XPath expressions, separated by <literal>|</literal>
- </para>
- </entry>
- </row>
- <row>
- <entry><parameter>criteria</parameter></entry>
- <entry>
- <para>
- the contents of the WHERE clause. This cannot be omitted, so use
- <literal>true</literal> or <literal>1=1</literal> if you want to
- process all the rows in the relation
- </para>
- </entry>
- </row>
- </tbody>
- </tgroup>
- </table>
-
- <para>
- These parameters (except the XPath strings) are just substituted
- into a plain SQL SELECT statement, so you have some flexibility — the
- statement is
- </para>
-
- <para>
- <literal>
- SELECT <key>, <document> FROM <relation> WHERE <criteria>
- </literal>
- </para>
-
- <para>
- so those parameters can be <emphasis>anything</> valid in those particular
- locations. The result from this SELECT needs to return exactly two
- columns (which it will unless you try to list multiple fields for key
- or document). Beware that this simplistic approach requires that you
- validate any user-supplied values to avoid SQL injection attacks.
- </para>
-
- <para>
- The function has to be used in a <literal>FROM</> expression, with an
- <literal>AS</> clause to specify the output columns; for example
- </para>
-
- <programlisting>
-SELECT * FROM
-xpath_table('article_id',
- 'article_xml',
- 'articles',
- '/article/author|/article/pages|/article/title',
- 'date_entered > ''2003-01-01'' ')
-AS t(article_id integer, author text, page_count integer, title text);
- </programlisting>
-
- <para>
- The <literal>AS</> clause defines the names and types of the columns in the
- output table. The first is the <quote>key</> field and the rest correspond
- to the XPath queries.
- If there are more XPath queries than result columns,
- the extra queries will be ignored. If there are more result columns
- than XPath queries, the extra columns will be NULL.
- </para>
-
- <para>
- Notice that this example defines the <structname>page_count</> result
- column as an integer. The function deals internally with string
- representations, so when you say you want an integer in the output, it will
- take the string representation of the XPath result and use PostgreSQL input
- functions to transform it into an integer (or whatever type the <type>AS</>
- clause requests). An error will result if it can't do this — for
- example if the result is empty — so you may wish to just stick to
- <type>text</> as the column type if you think your data has any problems.
- </para>
-
- <para>
- The calling <command>SELECT</> statement doesn't necessarily have be
- be just <literal>SELECT *</> — it can reference the output
- columns by name or join them to other tables. The function produces a
- virtual table with which you can perform any operation you wish (e.g.
- aggregation, joining, sorting etc). So we could also have:
- </para>
-
- <programlisting>
-SELECT t.title, p.fullname, p.email
-FROM xpath_table('article_id', 'article_xml', 'articles',
- '/article/title|/article/author/@id',
- 'xpath_string(article_xml,''/article/@date'') > ''2003-03-20'' ')
- AS t(article_id integer, title text, author_id integer),
- tblPeopleInfo AS p
-WHERE t.author_id = p.person_id;
- </programlisting>
-
- <para>
- as a more complicated example. Of course, you could wrap all
- of this in a view for convenience.
- </para>
-
- <sect3>
- <title>Multivalued results</title>
-
- <para>
- The <function>xpath_table</> function assumes that the results of each XPath query
- might be multi-valued, so the number of rows returned by the function
- may not be the same as the number of input documents. The first row
- returned contains the first result from each query, the second row the
- second result from each query. If one of the queries has fewer values
- than the others, NULLs will be returned instead.
- </para>
-
- <para>
- In some cases, a user will know that a given XPath query will return
- only a single result (perhaps a unique document identifier) — if used
- alongside an XPath query returning multiple results, the single-valued
- result will appear only on the first row of the result. The solution
- to this is to use the key field as part of a join against a simpler
- XPath query. As an example:
- </para>
-
- <programlisting>
- CREATE TABLE test (
- id int4 NOT NULL,
- xml text,
- CONSTRAINT pk PRIMARY KEY (id)
- );
-
- INSERT INTO test VALUES (1, '<doc num="C1">
- <line num="L1"><a>1</a><b>2</b><c>3</c></line>
- <line num="L2"><a>11</a><b>22</b><c>33</c></line>
- </doc>');
-
- INSERT INTO test VALUES (2, '<doc num="C2">
- <line num="L1"><a>111</a><b>222</b><c>333</c></line>
- <line num="L2"><a>111</a><b>222</b><c>333</c></line>
- </doc>');
-
- SELECT * FROM
- xpath_table('id','xml','test',
- '/doc/@num|/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c',
- 'true')
- AS t(id int4, doc_num varchar(10), line_num varchar(10), val1 int4, val2 int4, val3 int4)
- WHERE id = 1 ORDER BY doc_num, line_num
-
- id | doc_num | line_num | val1 | val2 | val3
- ----+---------+----------+------+------+------
- 1 | C1 | L1 | 1 | 2 | 3
- 1 | | L2 | 11 | 22 | 33
- </programlisting>
-
- <para>
- To get doc_num on every line, the solution is to use two invocations
- of xpath_table and join the results:
- </para>
-
- <programlisting>
- SELECT t.*,i.doc_num FROM
- xpath_table('id', 'xml', 'test',
- '/doc/line/@num|/doc/line/a|/doc/line/b|/doc/line/c',
- 'true')
- AS t(id int4, line_num varchar(10), val1 int4, val2 int4, val3 int4),
- xpath_table('id', 'xml', 'test', '/doc/@num', 'true')
- AS i(id int4, doc_num varchar(10))
- WHERE i.id=t.id AND i.id=1
- ORDER BY doc_num, line_num;
-
- id | line_num | val1 | val2 | val3 | doc_num
- ----+----------+------+------+------+---------
- 1 | L1 | 1 | 2 | 3 | C1
- 1 | L2 | 11 | 22 | 33 | C1
- (2 rows)
- </programlisting>
- </sect3>
- </sect2>
-
- <sect2>
- <title>XSLT functions</title>
-
- <para>
- The following functions are available if libxslt is installed:
- </para>
-
- <sect3>
- <title><literal>xslt_process</literal></title>
-
- <synopsis>
- xslt_process(text document, text stylesheet, text paramlist) returns text
- </synopsis>
-
- <para>
- This function appplies the XSL stylesheet to the document and returns
- the transformed result. The paramlist is a list of parameter
- assignments to be used in the transformation, specified in the form
- <literal>a=1,b=2</>. Note that the
- parameter parsing is very simple-minded: parameter values cannot
- contain commas!
- </para>
-
- <para>
- Also note that if either the document or stylesheet values do not
- begin with a < then they will be treated as URLs and libxslt will
- fetch them. It follows that you can use <function>xslt_process</> as a
- means to fetch the contents of URLs — you should be aware of the
- security implications of this.
- </para>
-
- <para>
- There is also a two-parameter version of <function>xslt_process</> which
- does not pass any parameters to the transformation.
- </para>
- </sect3>
- </sect2>
-
- <sect2>
- <title>Author</title>
-
- <para>
- John Gray <email>jgray@azuli.co.uk</email>
- </para>
-
- <para>
- Development of this module was sponsored by Torchbox Ltd. (www.torchbox.com).
- It has the same BSD licence as PostgreSQL.
- </para>
- </sect2>
-
-</sect1>
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 7a6e3a9..813a824 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -155,7 +155,6 @@ with_tcl = @with_tcl@
with_openssl = @with_openssl@
with_ossp_uuid = @with_ossp_uuid@
with_libxml = @with_libxml@
-with_libxslt = @with_libxslt@
with_system_tzdata = @with_system_tzdata@
with_zlib = @with_zlib@
enable_shared = @enable_shared@
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 69799a5..d851c6a 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -317,9 +317,6 @@
/* Define to 1 if you have the `xml2' library (-lxml2). */
#undef HAVE_LIBXML2
-/* Define to 1 if you have the `xslt' library (-lxslt). */
-#undef HAVE_LIBXSLT
-
/* Define to 1 if you have the `z' library (-lz). */
#undef HAVE_LIBZ
@@ -759,10 +756,6 @@
/* Define to 1 to build with XML support. (--with-libxml) */
#undef USE_LIBXML
-/* Define to 1 to use XSLT support when building contrib/xml2.
- (--with-libxslt) */
-#undef USE_LIBXSLT
-
/* Define to select named POSIX semaphores. */
#undef USE_NAMED_POSIX_SEMAPHORES
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index b0164bb..0d9fbb4 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -286,13 +286,11 @@ sub mkvcbuild
{
$contrib_extraincludes->{'pgxml'} = [
$solution->{options}->{xml} . '\include',
- $solution->{options}->{xslt} . '\include',
$solution->{options}->{iconv} . '\include'
];
$contrib_extralibs->{'pgxml'} = [
- $solution->{options}->{xml} . '\lib\libxml2.lib',
- $solution->{options}->{xslt} . '\lib\libxslt.lib'
+ $solution->{options}->{xml} . '\lib\libxml2.lib'
];
}
else
diff --git a/src/tools/msvc/Solution.pm b/src/tools/msvc/Solution.pm
index 850ad5a..801874c 100644
--- a/src/tools/msvc/Solution.pm
+++ b/src/tools/msvc/Solution.pm
@@ -29,9 +29,9 @@ sub new
unless exists $options->{float4byval};
if ($options->{xml})
{
- if (!($options->{xslt} && $options->{iconv}))
+ if (! $options->{iconv})
{
- die "XML requires both XSLT and ICONV\n";
+ die "XML requires ICONV\n";
}
}
$options->{blocksize} = 8
@@ -515,7 +515,6 @@ sub GetFakeConfigure
$cfg .= ' --with-openssl' if ($self->{options}->{ssl});
$cfg .= ' --with-ossp-uuid' if ($self->{options}->{uuid});
$cfg .= ' --with-libxml' if ($self->{options}->{xml});
- $cfg .= ' --with-libxslt' if ($self->{options}->{xslt});
$cfg .= ' --with-krb5' if ($self->{options}->{krb5});
$cfg .= ' --with-tcl' if ($self->{options}->{tcl});
$cfg .= ' --with-perl' if ($self->{options}->{perl});
diff --git a/src/tools/msvc/config_default.pl b/src/tools/msvc/config_default.pl
index eea4a70..9677b52 100644
--- a/src/tools/msvc/config_default.pl
+++ b/src/tools/msvc/config_default.pl
@@ -19,7 +19,6 @@ our $config = {
openssl=>undef, # --with-ssl=<path>
uuid=>undef, # --with-ossp-uuid
xml=>undef, # --with-libxml=<path>
- xslt=>undef, # --with-libxslt=<path>
iconv=>undef, # (not in configure, path to iconv)
zlib=>undef # --with-zlib=<path>
};