SRW, CQL, 2003
[yaz-moved-to-github.git] / srw / srw-xslt.c
1 /* $Id: srw-xslt.c,v 1.1 2003-01-06 08:20:28 adam Exp $
2    Copyright (C) 2002-2003
3    Index Data Aps
4
5 This file is part of the YAZ toolkit.
6
7 See the file LICENSE.
8 */
9
10 #if HAVE_XSLT
11 #include <libxml/parser.h>
12 #include <libxml/tree.h>
13 #include <libxslt/xsltutils.h>
14 #include <libxslt/transform.h>
15 #endif
16
17 #include <yaz/srw-util.h>
18
19 struct xslt_maps_info {
20 #if HAVE_XSLT
21     xmlDocPtr doc;
22 #else
23     int dummy;
24 #endif
25 };
26
27 struct xslt_map_result_info {
28 #if HAVE_XSLT
29     xmlChar *buf;
30 #else
31     char *buf;
32 #endif
33     int len;
34     char *schema;
35 };
36
37 xslt_maps xslt_maps_create()
38 {
39     xslt_maps m = malloc(sizeof(*m));
40 #if HAVE_XSLT
41     m->doc = 0;
42 #endif
43     return m;
44 }
45
46 void xslt_maps_free(xslt_maps m)
47 {
48 #if HAVE_XSLT
49     xmlFreeDoc(m->doc);
50 #endif
51     free (m);
52 }
53
54 int xslt_maps_file(xslt_maps m, const char *f)
55 {
56 #if HAVE_XSLT
57     if (m->doc)
58         xmlFreeDoc(m->doc);
59     m->doc = xmlParseFile(f);
60     if (!m->doc)
61         return -1;
62     return 0;
63 #else
64     return -2;
65 #endif
66 }
67
68 void xslt_map_free (xslt_map_result res)
69 {
70     if (res)
71     {
72         free (res->schema);
73 #if HAVE_XSLT
74         xmlFree(res->buf);
75 #endif
76         free (res);
77     }
78 }
79
80 xslt_map_result xslt_map (xslt_maps m, const char *schema_source,
81                           const char *schema_target,
82                           const char *in_buf, int in_len)
83 {
84 #if HAVE_XSLT
85     const char *map_ns = "http://indexdata.dk/srw/schema-mappings/v1.0/";
86     xmlNodePtr ptr;
87
88     if (!m)
89         return 0;
90     ptr = xmlDocGetRootElement(m->doc);
91     while (ptr && ptr->type == XML_ELEMENT_NODE)
92     {
93         if (!strcmp(ptr->name, "schema-mappings"))
94         {
95             ptr = ptr->children;
96             break;
97         }
98     }
99     for (; ptr; ptr = ptr->next)
100     {
101         if (ptr->type == XML_ELEMENT_NODE &&  !strcmp(ptr->name, "map")
102             && !strcmp(ptr->ns->href, map_ns) && ptr->children)
103         {
104             xmlNodePtr src = ptr->children;
105             int source_ok = 0;
106             int target_ok = 0;
107             const char *full_target = 0;
108             const char *filename = 0;
109             
110             for (; src; src = src->next)
111             {
112                 if (src->type == XML_ELEMENT_NODE &&
113                     !strcmp(src->name, "schema") &&
114                     !strcmp(src->ns->href, map_ns))
115                 {
116                     struct _xmlAttr *attr = src->properties;
117                     for (; attr; attr = attr->next)
118                         if (!strcmp(attr->name, "target") &&
119                             attr->children &&
120                             attr->children->type == XML_TEXT_NODE)
121                         {
122                             full_target = attr->children->content;
123                             if (!strcmp(attr->children->content,
124                                         schema_target))
125                                 target_ok = 1;
126                         }
127                         else if (!strcmp(attr->name, "source")
128                                  && attr->children
129                                  && attr->children->type == XML_TEXT_NODE)
130                             
131                         {
132                             if (!strcmp(schema_source,
133                                         attr->children->content))
134                                 source_ok = 1;
135                         }
136                         else if (!strcmp(attr->name, "alias")
137                                  && attr->children
138                                  && attr->children->type == XML_TEXT_NODE)
139                         {
140                             if (!strcmp(attr->children->content, schema_target))
141                                 target_ok = 1;
142                         }
143                 }
144                 if (src->type == XML_ELEMENT_NODE &&
145                     !strcmp(src->name, "stylesheet") &&
146                     !strcmp(src->ns->href, map_ns))
147                 {
148                     struct _xmlAttr *attr = src->properties;
149                     for (; attr; attr = attr->next)
150                         if (!strcmp(attr->name, "filename") &&
151                             attr->children &&
152                             attr->children->type == XML_TEXT_NODE)
153                         {
154                             filename = attr->children->content;
155                         }
156                 }
157             }
158             if (source_ok && target_ok)
159             {
160                 if (filename)
161                 {
162                     xslt_map_result out = malloc(sizeof(*out));
163                     xmlDocPtr res, doc = xmlParseMemory(in_buf, in_len);
164                     xmlDocPtr xslt_doc = xmlParseFile(filename);
165                     xsltStylesheetPtr xsp;
166                     
167                     xsp = xsltParseStylesheetDoc(xslt_doc);
168                     
169                     res = xsltApplyStylesheet(xsp, doc, 0);
170                     
171                     xmlDocDumpMemory (res, &out->buf, &out->len);
172                 
173                     xsltFreeStylesheet(xsp);
174                     
175                     xmlFreeDoc(doc);
176                     xmlFreeDoc(res);
177                     
178                     out->schema = strdup(full_target);
179                     return out;
180                 }
181                 else
182                 {
183                     xslt_map_result out = malloc(sizeof(*out));
184                     out->buf = xmlMalloc(in_len);
185                     memcpy (out->buf, in_buf, in_len);
186                     out->len = in_len;
187                     out->schema = strdup(full_target);
188                     return out; 
189                 }
190             }
191         }
192     }
193 #endif
194     return 0;
195 }
196
197 char *xslt_map_result_buf(xslt_map_result res)
198 {
199     return res->buf;
200 }
201 int xslt_map_result_len(xslt_map_result res)
202 {
203     return res->len;
204 }
205
206 char *xslt_map_result_schema(xslt_map_result res)
207 {
208     return res->schema;
209 }