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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy