pazpar2  1.14.1
normalize_record.c
Go to the documentation of this file.
1 /* This file is part of Pazpar2.
2  Copyright (C) Index Data
3 
4 Pazpar2 is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8 
9 Pazpar2 is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 
18 */
19 
20 #include <string.h>
21 
22 #include <yaz/yaz-util.h>
23 #include <yaz/nmem.h>
24 
25 #if HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include "normalize_record.h"
30 
31 #include "pazpar2_config.h"
32 #include "service_xslt.h"
33 #include "marcmap.h"
34 #include <libxslt/xslt.h>
35 #include <libxslt/transform.h>
36 
39  xsltStylesheet *stylesheet1; /* created by normalize_record */
40  xsltStylesheet *stylesheet2; /* external stylesheet (service) */
41  struct marcmap *marcmap;
42 };
43 
46  NMEM nmem;
47 };
48 
50  const char *spec)
51 {
52  NMEM nmem = nmem_create();
53  normalize_record_t nt = nmem_malloc(nmem, sizeof(*nt));
54  struct normalize_step **m = &nt->steps;
55  int no_errors = 0;
56  int embed = 0;
57 
58  if (*spec == '<')
59  embed = 1;
60 
61  nt->nmem = nmem;
62 
63  if (embed)
64  {
65  xmlDoc *xsp_doc = xmlParseMemory(spec, strlen(spec));
66 
67  if (!xsp_doc)
68  no_errors++;
69  else
70  {
71  *m = nmem_malloc(nt->nmem, sizeof(**m));
72  (*m)->marcmap = NULL;
73  (*m)->stylesheet1 = NULL;
74  (*m)->stylesheet2 = NULL;
75 
76 
77  (*m)->stylesheet1 = xsltParseStylesheetDoc(xsp_doc);
78  if (!(*m)->stylesheet1)
79  no_errors++;
80  m = &(*m)->next;
81  }
82  }
83  else
84  {
85  struct conf_config *conf = service->server->config;
86  int i, num;
87  char **stylesheets;
88  nmem_strsplit(nt->nmem, ",", spec, &stylesheets, &num);
89 
90  for (i = 0; i < num; i++)
91  {
92  *m = nmem_malloc(nt->nmem, sizeof(**m));
93  (*m)->marcmap = NULL;
94  (*m)->stylesheet1 = NULL;
95  (*m)->stylesheet2 = service_xslt_get(service, stylesheets[i]);
96  if ((*m)->stylesheet2)
97  ;
98  else if (!strcmp(&stylesheets[i][strlen(stylesheets[i])-4], ".xsl"))
99  {
100  WRBUF fname = conf_get_fname(conf, stylesheets[i]);
101  if (!((*m)->stylesheet1 =
102  xsltParseStylesheetFile((xmlChar *) wrbuf_cstr(fname))))
103  {
104  yaz_log(YLOG_FATAL|YLOG_ERRNO, "Unable to load stylesheet: %s",
105  stylesheets[i]);
106  no_errors++;
107  }
108  wrbuf_destroy(fname);
109  }
110  else if (!strcmp(&stylesheets[i][strlen(stylesheets[i])-5], ".mmap"))
111  {
112  WRBUF fname = conf_get_fname(conf, stylesheets[i]);
113  if (!((*m)->marcmap = marcmap_load(wrbuf_cstr(fname), nt->nmem)))
114  {
115  yaz_log(YLOG_FATAL|YLOG_ERRNO, "Unable to load marcmap: %s",
116  stylesheets[i]);
117  no_errors++;
118  }
119  wrbuf_destroy(fname);
120  }
121  else
122  {
123  yaz_log(YLOG_FATAL, "Cannot handle stylesheet: %s", stylesheets[i]);
124  no_errors++;
125  }
126  m = &(*m)->next;
127  }
128  }
129  *m = 0; /* terminate list of steps */
130 
131  if (no_errors)
132  {
134  nt = 0;
135  }
136  return nt;
137 }
138 
140 {
141  if (nt)
142  {
143  struct normalize_step *m;
144  for (m = nt->steps; m; m = m->next)
145  {
146  if (m->stylesheet1)
147  xsltFreeStylesheet(m->stylesheet1);
148  }
149  nmem_destroy(nt->nmem);
150  }
151 }
152 
154  const char **parms)
155 {
156  if (nt)
157  {
158  struct normalize_step *m;
159  for (m = nt->steps; m; m = m->next)
160  {
161  xmlNodePtr root = 0;
162  xmlDoc *ndoc;
163  if (m->stylesheet1)
164  ndoc = xsltApplyStylesheet(m->stylesheet1, *doc, parms);
165  else if (m->stylesheet2)
166  ndoc = xsltApplyStylesheet(m->stylesheet2, *doc, parms);
167  else if (m->marcmap)
168  ndoc = marcmap_apply(m->marcmap, *doc);
169  else
170  ndoc = 0;
171  xmlFreeDoc(*doc);
172  *doc = 0;
173 
174  if (ndoc)
175  root = xmlDocGetRootElement(ndoc);
176 
177  if (ndoc && root && root->children)
178  *doc = ndoc;
179  else
180  {
181  if (!ndoc)
182  yaz_log(YLOG_WARN, "XSLT produced no document");
183  else if (!root)
184  yaz_log(YLOG_WARN, "XSLT produced XML with no root node");
185  else if (!root->children)
186  yaz_log(YLOG_WARN, "XSLT produced XML with no root children nodes");
187  if (ndoc)
188  xmlFreeDoc(ndoc);
189  return -1;
190  }
191  }
192  }
193  return 0;
194 }
195 
196 /*
197  * Local variables:
198  * c-basic-offset: 4
199  * c-file-style: "Stroustrup"
200  * indent-tabs-mode: nil
201  * End:
202  * vim: shiftwidth=4 tabstop=8 expandtab
203  */
204 
struct marcmap * marcmap_load(const char *filename, NMEM nmem)
Definition: marcmap.c:40
xmlDoc * marcmap_apply(struct marcmap *marcmap, xmlDoc *xml_in)
Definition: marcmap.c:112
int normalize_record_transform(normalize_record_t nt, xmlDoc **doc, const char **parms)
void normalize_record_destroy(normalize_record_t nt)
normalize_record_t normalize_record_create(struct conf_service *service, const char *spec)
WRBUF conf_get_fname(struct conf_config *config, const char *fname)
xsltStylesheetPtr service_xslt_get(struct conf_service *service, const char *id)
Definition: service_xslt.c:45
struct conf_config * config
struct conf_server * server
struct normalize_step * steps
xsltStylesheet * stylesheet1
struct normalize_step * next
xsltStylesheet * stylesheet2
struct marcmap * marcmap