Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4859219

Browse files
committed
Add 0.2 version XML files.
1 parent f00caec commit 4859219

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

contrib/xml/pgxml_dom.c

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
/* Parser interface for DOM-based parser (libxml) rather than
2+
stream-based SAX-type parser */
3+
4+
#include "postgres.h"
5+
#include "fmgr.h"
6+
7+
/* libxml includes */
8+
9+
#include <libxml/xpath.h>
10+
#include <libxml/tree.h>
11+
#include <libxml/xmlmemory.h>
12+
13+
/* declarations */
14+
15+
static void *pgxml_palloc(size_t size);
16+
static void *pgxml_repalloc(void *ptr, size_t size);
17+
static void pgxml_pfree(void *ptr);
18+
static char *pgxml_pstrdup(const char* string);
19+
20+
static void pgxml_parser_init();
21+
22+
static xmlChar *pgxmlNodeSetToText(xmlNodeSetPtr nodeset, xmlDocPtr doc,
23+
xmlChar *toptagname, xmlChar *septagname,
24+
int format);
25+
26+
static xmlChar *pgxml_texttoxmlchar(text *textstring);
27+
28+
29+
Datum pgxml_parse(PG_FUNCTION_ARGS);
30+
Datum pgxml_xpath(PG_FUNCTION_ARGS);
31+
32+
/* memory handling passthrough functions (e.g. palloc, pstrdup are
33+
currently macros, and the others might become so...) */
34+
35+
static void *pgxml_palloc(size_t size)
36+
{
37+
return palloc(size);
38+
}
39+
40+
static void *pgxml_repalloc(void *ptr, size_t size)
41+
{
42+
return repalloc(ptr,size);
43+
}
44+
45+
static void pgxml_pfree(void *ptr)
46+
{
47+
return pfree(ptr);
48+
}
49+
50+
static char *pgxml_pstrdup(const char *string)
51+
{
52+
return pstrdup(string);
53+
}
54+
55+
static void pgxml_parser_init()
56+
{
57+
/* This code should also set parser settings from user-supplied
58+
info. Quite how these settings are made is another matter :) */
59+
60+
xmlMemSetup(pgxml_pfree, pgxml_palloc, pgxml_repalloc, pgxml_pstrdup);
61+
xmlInitParser();
62+
63+
}
64+
65+
66+
/* Returns true if document is well-formed */
67+
68+
PG_FUNCTION_INFO_V1(pgxml_parse);
69+
70+
Datum
71+
pgxml_parse(PG_FUNCTION_ARGS)
72+
{
73+
/* called as pgxml_parse(document) */
74+
xmlDocPtr doctree;
75+
text *t = PG_GETARG_TEXT_P(0); /*document buffer */
76+
int32 docsize = VARSIZE(t) - VARHDRSZ;
77+
78+
pgxml_parser_init();
79+
80+
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
81+
if (doctree == NULL) {
82+
/* xmlCleanupParser(); */
83+
PG_RETURN_BOOL(false); /* i.e. not well-formed */
84+
}
85+
/* xmlCleanupParser(); */
86+
xmlFreeDoc(doctree);
87+
PG_RETURN_BOOL(true);
88+
}
89+
90+
static xmlChar
91+
*pgxmlNodeSetToText(xmlNodeSetPtr nodeset,
92+
xmlDocPtr doc,
93+
xmlChar *toptagname,
94+
xmlChar *septagname,
95+
int format)
96+
{
97+
/* Function translates a nodeset into a text representation */
98+
/* iterates over each node in the set and calls xmlNodeDump to write
99+
it to an xmlBuffer -from which an xmlChar * string is returned. */
100+
/* each representation is surrounded by <tagname> ... </tagname> */
101+
/* if format==0, add a newline between nodes?? */
102+
103+
xmlBufferPtr buf;
104+
xmlChar *result;
105+
int i;
106+
107+
buf =xmlBufferCreate();
108+
109+
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) {
110+
xmlBufferWriteChar(buf,"<");
111+
xmlBufferWriteCHAR(buf,toptagname);
112+
xmlBufferWriteChar(buf,">");
113+
}
114+
if (nodeset != NULL) {
115+
for (i=0; i < nodeset->nodeNr; i++) {
116+
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
117+
xmlBufferWriteChar(buf,"<");
118+
xmlBufferWriteCHAR(buf,septagname);
119+
xmlBufferWriteChar(buf,">");
120+
}
121+
xmlNodeDump(buf, doc, nodeset->nodeTab[i],1,(format==2));
122+
123+
if ((septagname != NULL) && (xmlStrlen(septagname)>0)) {
124+
xmlBufferWriteChar(buf,"</");
125+
xmlBufferWriteCHAR(buf,septagname);
126+
xmlBufferWriteChar(buf,">");
127+
}
128+
if (format) {
129+
xmlBufferWriteChar(buf,"\n");
130+
}
131+
}
132+
}
133+
134+
if ((toptagname != NULL) && (xmlStrlen(toptagname)>0)) {
135+
xmlBufferWriteChar(buf,"</");
136+
xmlBufferWriteCHAR(buf,toptagname);
137+
xmlBufferWriteChar(buf,">");
138+
}
139+
result = xmlStrdup(buf->content);
140+
xmlBufferFree(buf);
141+
return result;
142+
}
143+
144+
static xmlChar *pgxml_texttoxmlchar(text *textstring) {
145+
xmlChar *res;
146+
int32 txsize;
147+
148+
txsize=VARSIZE(textstring)-VARHDRSZ;
149+
res = (xmlChar *) palloc(txsize+1);
150+
memcpy((char *)res, VARDATA(textstring), txsize);
151+
res[txsize]='\0';
152+
return res;
153+
}
154+
155+
156+
PG_FUNCTION_INFO_V1(pgxml_xpath);
157+
158+
Datum
159+
pgxml_xpath(PG_FUNCTION_ARGS)
160+
{
161+
xmlDocPtr doctree;
162+
xmlXPathContextPtr ctxt;
163+
xmlXPathObjectPtr res;
164+
xmlChar *xpath, *xpresstr, *toptag, *septag;
165+
xmlXPathCompExprPtr comppath;
166+
167+
int32 docsize,ressize;
168+
text *t, *xpres;
169+
170+
t = PG_GETARG_TEXT_P(0); /*document buffer */
171+
xpath = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(1)); /* XPath expression */
172+
toptag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(2));
173+
septag = pgxml_texttoxmlchar(PG_GETARG_TEXT_P(3));
174+
175+
docsize = VARSIZE(t) - VARHDRSZ;
176+
177+
pgxml_parser_init();
178+
179+
doctree = xmlParseMemory((char *) VARDATA(t), docsize);
180+
if (doctree == NULL) { /* not well-formed */
181+
PG_RETURN_NULL();
182+
}
183+
184+
ctxt = xmlXPathNewContext(doctree);
185+
ctxt->node = xmlDocGetRootElement(doctree);
186+
187+
/* compile the path */
188+
comppath = xmlXPathCompile(xpath);
189+
if (comppath == NULL) {
190+
elog(NOTICE, "XPath syntax error");
191+
xmlFreeDoc(doctree);
192+
pfree((void *) xpath);
193+
PG_RETURN_NULL();
194+
}
195+
196+
/* Now evaluate the path expression. */
197+
res = xmlXPathCompiledEval(comppath,ctxt);
198+
xmlXPathFreeCompExpr(comppath);
199+
200+
if (res==NULL) {
201+
xmlFreeDoc(doctree);
202+
pfree((void *)xpath);
203+
PG_RETURN_NULL(); /* seems appropriate */
204+
}
205+
/* now we dump this node, ?surrounding by tags? */
206+
/* To do this, we look first at the type */
207+
switch(res->type) {
208+
case XPATH_NODESET:
209+
xpresstr = pgxmlNodeSetToText(res->nodesetval,
210+
doctree,
211+
toptag, septag, 0);
212+
break;
213+
case XPATH_STRING:
214+
xpresstr = xmlStrdup(res->stringval);
215+
break;
216+
default:
217+
elog(NOTICE,"Unsupported XQuery result: %d",res->type);
218+
xpresstr = xmlStrdup("<unsupported/>");
219+
}
220+
221+
222+
/* Now convert this result back to text */
223+
ressize = strlen(xpresstr);
224+
xpres = (text *) palloc(ressize+VARHDRSZ);
225+
memcpy(VARDATA(xpres),xpresstr,ressize);
226+
VARATT_SIZEP(xpres)=ressize + VARHDRSZ;
227+
228+
/* Free various storage */
229+
xmlFreeDoc(doctree);
230+
pfree((void *) xpath);
231+
xmlFree(xpresstr);
232+
233+
PG_RETURN_TEXT_P(xpres);
234+
}
235+
236+
237+
238+

contrib/xml/pgxml_dom.source

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
--SQL for XML parser
2+
3+
CREATE FUNCTION pgxml_parse(text) RETURNS bool
4+
AS '_OBJWD_/pgxml_dom_DLSUFFIX_' LANGUAGE 'c' WITH (isStrict);
5+
6+
CREATE FUNCTION pgxml_xpath(text,text,text,text) RETURNS text
7+
AS '_OBJWD_/pgxml_dom_DLSUFFIX_' LANGUAGE 'c' WITH (isStrict);

0 commit comments

Comments
 (0)