YAZ  5.34.0
xml_to_opac.c
Go to the documentation of this file.
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12 
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 
17 #include <yaz/proto.h>
18 #include <yaz/marcdisp.h>
19 #include <yaz/wrbuf.h>
20 #include <yaz/oid_db.h>
21 
22 #if YAZ_HAVE_XML2
23 #include "sru-p.h"
24 
25 static int match_element_next(xmlNode **ptr, const char *elem, NMEM nmem,
26  char **val)
27 {
28  while (*ptr && (*ptr)->type != XML_ELEMENT_NODE)
29  (*ptr) = (*ptr)->next;
30  if (yaz_match_xsd_string_n_nmem(*ptr, elem, nmem, val, 0))
31  {
32  *ptr = (*ptr)->next;
33  return 1;
34  }
35  *val = 0;
36  return 0;
37 }
38 
39 static int match_v_next(xmlNode **ptr, const char *elem, NMEM nmem,
40  Odr_bool **val)
41 {
42  while (*ptr && (*ptr)->type != XML_ELEMENT_NODE)
43  (*ptr) = (*ptr)->next;
44  *val = nmem_booldup(nmem, 0);
45  if (yaz_match_xsd_element(*ptr, elem))
46  {
47  struct _xmlAttr *attr = (*ptr)->properties;
48 
49  *ptr = (*ptr)->next;
50  for (; attr; attr = attr->next)
51  {
52  if (!strcmp((const char *) attr->name, "value"))
53  {
54  if (attr->children->type == XML_TEXT_NODE)
55  {
56  if (attr->children->content[0] == '0')
57  return 1;
58  else if (attr->children->content[0] == '1')
59  {
60  **val = 1;
61  return 1;
62  }
63  }
64  }
65  }
66  }
67  return 0;
68 }
69 
70 static int bibliographicRecord(yaz_marc_t mt, xmlNode *ptr, Z_External **ext,
71  NMEM nmem, const Odr_oid *syntax)
72 {
73  int ret = 0;
74  if (yaz_marc_read_xml(mt, ptr) == 0)
75  {
76  WRBUF wr = wrbuf_alloc();
77  if (yaz_marc_write_iso2709(mt, wr) == 0)
78  {
79  *ext = z_ext_record_oid_nmem(
80  nmem, syntax ? syntax : yaz_oid_recsyn_usmarc,
81  wrbuf_buf(wr), wrbuf_len(wr));
82  ret = 1;
83  }
84  wrbuf_destroy(wr);
85  }
86  return ret;
87 }
88 
89 static int volume(xmlNode *ptr, Z_Volume **volp, NMEM nmem)
90 {
91  *volp = (Z_Volume *) nmem_malloc(nmem, sizeof(Z_Volume));
92 
93  match_element_next(&ptr, "enumeration", nmem, &(*volp)->enumeration);
94  match_element_next(&ptr, "chronology", nmem, &(*volp)->chronology);
95  match_element_next(&ptr, "enumAndChron", nmem, &(*volp)->enumAndChron);
96  return 1;
97 }
98 
99 static int volumes(xmlNode *ptr, Z_Volume ***volp, int *num, NMEM nmem)
100 {
101  int i;
102  xmlNode *ptr0 = ptr;
103 
104  for (i = 0; ptr; i++)
105  {
106  while (ptr && ptr->type != XML_ELEMENT_NODE)
107  ptr = ptr->next;
108  if (!ptr)
109  break;
110  if (!yaz_match_xsd_element(ptr, "volume"))
111  return 0;
112  ptr = ptr->next;
113  }
114  *num = i;
115  *volp = (Z_Volume **) nmem_malloc(nmem, sizeof(**volp) * i);
116  ptr = ptr0;
117  for (i = 0; ptr; i++)
118  {
119  while (ptr && ptr->type != XML_ELEMENT_NODE)
120  ptr = ptr->next;
121  if (!ptr)
122  break;
123  if (!yaz_match_xsd_element(ptr, "volume"))
124  return 0;
125  volume(ptr->children, (*volp) + i, nmem);
126  ptr = ptr->next;
127  }
128  return 1;
129 }
130 
131 static int circulation(xmlNode *ptr, Z_CircRecord **circp, NMEM nmem)
132 {
133  *circp = (Z_CircRecord *) nmem_malloc(nmem, sizeof(Z_CircRecord));
134 
135  match_v_next(&ptr, "availableNow", nmem, &(*circp)->availableNow);
136  /* note the spelling of the ASN.1 member below */
137  match_element_next(&ptr, "availabilityDate", nmem,
138  &(*circp)->availablityDate);
139  match_element_next(&ptr, "availableThru", nmem, &(*circp)->availableThru);
140  match_element_next(&ptr, "restrictions", nmem, &(*circp)->restrictions);
141  match_element_next(&ptr, "itemId", nmem, &(*circp)->itemId);
142  match_v_next(&ptr, "renewable", nmem, &(*circp)->renewable);
143  match_v_next(&ptr, "onHold", nmem, &(*circp)->onHold);
144  match_element_next(&ptr, "enumAndChron", nmem, &(*circp)->enumAndChron);
145  match_element_next(&ptr, "midspine", nmem, &(*circp)->midspine);
146  match_element_next(&ptr, "temporaryLocation", nmem,
147  &(*circp)->temporaryLocation);
148  return 1;
149 }
150 
151 static int circulations(xmlNode *ptr, Z_CircRecord ***circp,
152  int *num, NMEM nmem)
153 {
154  int i;
155  xmlNode *ptr0 = ptr;
156 
157  for (i = 0; ptr; i++)
158  {
159  while (ptr && ptr->type != XML_ELEMENT_NODE)
160  ptr = ptr->next;
161  if (!ptr)
162  break;
163  if (!yaz_match_xsd_element(ptr, "circulation"))
164  return 0;
165  ptr = ptr->next;
166  }
167  *num = i;
168  *circp = (Z_CircRecord **) nmem_malloc(nmem, sizeof(**circp) * i);
169  ptr = ptr0;
170  for (i = 0; ptr; i++)
171  {
172  while (ptr && ptr->type != XML_ELEMENT_NODE)
173  ptr = ptr->next;
174  if (!ptr)
175  break;
176  if (!yaz_match_xsd_element(ptr, "circulation"))
177  return 0;
178  circulation(ptr->children, (*circp) + i, nmem);
179  ptr = ptr->next;
180  }
181  return 1;
182 }
183 
184 static int holdingsRecord(xmlNode *ptr, Z_HoldingsRecord **r, NMEM nmem)
185 {
187 
188  *r = (Z_HoldingsRecord *)
189  nmem_malloc(nmem, sizeof(**r));
190  (*r)->which = Z_HoldingsRecord_holdingsAndCirc;
191  h = (*r)->u.holdingsAndCirc = (Z_HoldingsAndCircData *)
192  nmem_malloc(nmem, sizeof(*h));
193 
194  match_element_next(&ptr, "typeOfRecord", nmem, &h->typeOfRecord);
195  match_element_next(&ptr, "encodingLevel", nmem, &h->encodingLevel);
196  match_element_next(&ptr, "format", nmem, &h->format);
197  match_element_next(&ptr, "receiptAcqStatus", nmem, &h->receiptAcqStatus);
198  match_element_next(&ptr, "generalRetention", nmem, &h->generalRetention);
199  match_element_next(&ptr, "completeness", nmem, &h->completeness);
200  match_element_next(&ptr, "dateOfReport", nmem, &h->dateOfReport);
201  match_element_next(&ptr, "nucCode", nmem, &h->nucCode);
202  match_element_next(&ptr, "localLocation", nmem, &h->localLocation);
203  match_element_next(&ptr, "shelvingLocation", nmem, &h->shelvingLocation);
204  match_element_next(&ptr, "callNumber", nmem, &h->callNumber);
205  match_element_next(&ptr, "shelvingData", nmem, &h->shelvingData);
206  match_element_next(&ptr, "copyNumber", nmem, &h->copyNumber);
207  match_element_next(&ptr, "publicNote", nmem, &h->publicNote);
208  match_element_next(&ptr, "reproductionNote", nmem, &h->reproductionNote);
209  match_element_next(&ptr, "termsUseRepro", nmem, &h->termsUseRepro);
210  match_element_next(&ptr, "enumAndChron", nmem, &h->enumAndChron);
211 
212  h->num_volumes = 0;
213  h->volumes = 0;
214  while (ptr && ptr->type != XML_ELEMENT_NODE)
215  ptr = ptr->next;
216  if (yaz_match_xsd_element(ptr, "volumes"))
217  {
218  volumes(ptr->children, &h->volumes, &h->num_volumes, nmem);
219  ptr = ptr->next;
220  }
221 
222  h->num_circulationData = 0;
223  h->circulationData = 0;
224  while (ptr && ptr->type != XML_ELEMENT_NODE)
225  ptr = ptr->next;
226  if (yaz_match_xsd_element(ptr, "circulations"))
227  {
228  circulations(ptr->children, &h->circulationData,
229  &h->num_circulationData, nmem);
230  ptr = ptr->next;
231  }
232  return 1;
233 }
234 
235 static int yaz_xml_to_opac_ptr(yaz_marc_t mt, xmlNode *ptr,
236  Z_OPACRecord **dst,
237  NMEM nmem,
238  const Odr_oid *syntax)
239 {
240  int i;
241  Z_External *ext = 0;
242  Z_OPACRecord *opac;
243  xmlNode *ptr0;
244 
245  if (!nmem)
246  nmem = yaz_marc_get_nmem(mt);
247  if (!yaz_match_xsd_element(ptr, "opacRecord"))
248  return 0;
249  ptr = ptr->children;
250  while (ptr && ptr->type != XML_ELEMENT_NODE)
251  ptr = ptr->next;
252  if (!yaz_match_xsd_element(ptr, "bibliographicRecord"))
253  return 0;
254  if (!bibliographicRecord(mt, ptr->children, &ext, nmem, syntax))
255  return 0;
256  *dst = opac = (Z_OPACRecord *) nmem_malloc(nmem, sizeof(*opac));
257  opac->num_holdingsData = 0;
258  opac->holdingsData = 0;
259  opac->bibliographicRecord = ext;
260 
261  ptr = ptr->next;
262  while (ptr && ptr->type != XML_ELEMENT_NODE)
263  ptr = ptr->next;
264  if (!yaz_match_xsd_element(ptr, "holdings"))
265  return 0;
266 
267  ptr = ptr->children;
268  ptr0 = ptr;
269 
270  for (i = 0; ptr; i++)
271  {
272  while (ptr && ptr->type != XML_ELEMENT_NODE)
273  ptr = ptr->next;
274  if (!ptr)
275  break;
276  if (!yaz_match_xsd_element(ptr, "holding"))
277  return 0;
278  ptr = ptr->next;
279  }
280  opac->num_holdingsData = i;
281  opac->holdingsData = (Z_HoldingsRecord **)
282  nmem_malloc(nmem, sizeof(*opac->holdingsData) * i);
283  ptr = ptr0;
284  for (i = 0; ptr; i++)
285  {
286  while (ptr && ptr->type != XML_ELEMENT_NODE)
287  ptr = ptr->next;
288  if (!ptr)
289  break;
290  if (!yaz_match_xsd_element(ptr, "holding"))
291  return 0;
292  if (!holdingsRecord(ptr->children, opac->holdingsData + i, nmem))
293  return 0;
294  ptr = ptr->next;
295  }
296  return 1;
297 }
298 
299 int yaz_xml_to_opac(yaz_marc_t mt, const char *buf_in, size_t size_in,
300  Z_OPACRecord **dst, yaz_iconv_t cd, NMEM nmem,
301  const Odr_oid *syntax)
302 {
303  xmlDocPtr doc = xmlParseMemory(buf_in, size_in);
304  int r = 0;
305  if (doc)
306  {
307  yaz_marc_iconv(mt, cd);
308  r = yaz_xml_to_opac_ptr(mt, xmlDocGetRootElement(doc), dst, nmem,
309  syntax);
310  xmlFreeDoc(doc);
311  }
312  return r;
313 }
314 
315 
316 #endif
317 
318 /*
319  * Local variables:
320  * c-basic-offset: 4
321  * c-file-style: "Stroustrup"
322  * indent-tabs-mode: nil
323  * End:
324  * vim: shiftwidth=4 tabstop=8 expandtab
325  */
326 
int yaz_marc_read_xml(yaz_marc_t mt, const xmlNode *ptr)
parses MARCXML/MarcXchange/TurboMARC record from xmlNode pointer
int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
writes record in ISO2709 format
Definition: marcdisp.c:1119
void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
set iconv handle for character set conversion
Definition: marcdisp.c:1387
NMEM yaz_marc_get_nmem(yaz_marc_t mt)
returns memory for MARC handle
Definition: marcdisp.c:130
MARC conversion.
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition: nmem.c:145
nmem_bool_t * nmem_booldup(NMEM mem, nmem_bool_t v)
allocates and sets boolean for NMEM
Definition: nmemsdup.c:48
nmem_bool_t Odr_bool
Definition: odr.h:48
Header for OID database.
const Odr_oid yaz_oid_recsyn_usmarc[]
Definition: oid_std.c:43
short Odr_oid
Definition: oid_util.h:42
Header for Z39.50 Protocol.
Z_External * z_ext_record_oid_nmem(NMEM nmem, const Odr_oid *oid, const char *buf, int len)
encodes EXTERNAL record based on OID (NULL if not known)
Definition: prt-ext.c:262
SRU private header.
int yaz_match_xsd_element(xmlNodePtr ptr, const char *elem)
Definition: xml_match.c:17
int yaz_match_xsd_string_n_nmem(xmlNodePtr ptr, const char *elem, NMEM nmem, char **val, int *len)
Definition: xml_match.c:29
structure for all known EXTERNALs
Definition: prt-ext.h:59
Z_InternationalString * completeness
Definition: z-opac.h:58
Z_InternationalString * format
Definition: z-opac.h:55
Z_InternationalString * generalRetention
Definition: z-opac.h:57
Z_InternationalString * nucCode
Definition: z-opac.h:60
Z_InternationalString * termsUseRepro
Definition: z-opac.h:68
Z_InternationalString * copyNumber
Definition: z-opac.h:65
Z_InternationalString * encodingLevel
Definition: z-opac.h:54
Z_Volume ** volumes
Definition: z-opac.h:71
Z_CircRecord ** circulationData
Definition: z-opac.h:73
Z_InternationalString * dateOfReport
Definition: z-opac.h:59
Z_InternationalString * callNumber
Definition: z-opac.h:63
Z_InternationalString * typeOfRecord
Definition: z-opac.h:53
Z_InternationalString * localLocation
Definition: z-opac.h:61
Z_InternationalString * shelvingLocation
Definition: z-opac.h:62
Z_InternationalString * receiptAcqStatus
Definition: z-opac.h:56
Z_InternationalString * shelvingData
Definition: z-opac.h:64
Z_InternationalString * publicNote
Definition: z-opac.h:66
Z_InternationalString * reproductionNote
Definition: z-opac.h:67
Z_InternationalString * enumAndChron
Definition: z-opac.h:69
Z_HoldingsRecord ** holdingsData
Definition: z-opac.h:39
Z_External * bibliographicRecord
Definition: z-opac.h:37
int num_holdingsData
Definition: z-opac.h:38
string buffer
Definition: wrbuf.h:43
the internals of a yaz_marc_t handle
Definition: marcdisp.c:86
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition: wrbuf.c:38
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition: wrbuf.c:25
Header for WRBUF (growing buffer)
#define wrbuf_buf(b)
Definition: wrbuf.h:251
#define wrbuf_len(b)
Definition: wrbuf.h:250
static int match_element_next(xmlNode **ptr, const char *elem, NMEM nmem, char **val)
Definition: xml_to_opac.c:25
static int holdingsRecord(xmlNode *ptr, Z_HoldingsRecord **r, NMEM nmem)
Definition: xml_to_opac.c:184
static int circulation(xmlNode *ptr, Z_CircRecord **circp, NMEM nmem)
Definition: xml_to_opac.c:131
static int yaz_xml_to_opac_ptr(yaz_marc_t mt, xmlNode *ptr, Z_OPACRecord **dst, NMEM nmem, const Odr_oid *syntax)
Definition: xml_to_opac.c:235
static int match_v_next(xmlNode **ptr, const char *elem, NMEM nmem, Odr_bool **val)
Definition: xml_to_opac.c:39
static int volumes(xmlNode *ptr, Z_Volume ***volp, int *num, NMEM nmem)
Definition: xml_to_opac.c:99
static int volume(xmlNode *ptr, Z_Volume **volp, NMEM nmem)
Definition: xml_to_opac.c:89
static int circulations(xmlNode *ptr, Z_CircRecord ***circp, int *num, NMEM nmem)
Definition: xml_to_opac.c:151
int yaz_xml_to_opac(yaz_marc_t mt, const char *buf_in, size_t size_in, Z_OPACRecord **dst, yaz_iconv_t cd, NMEM nmem, const Odr_oid *syntax)
Converts XML to OPAC.
Definition: xml_to_opac.c:299
static int bibliographicRecord(yaz_marc_t mt, xmlNode *ptr, Z_External **ext, NMEM nmem, const Odr_oid *syntax)
Definition: xml_to_opac.c:70
#define Z_HoldingsRecord_holdingsAndCirc
Definition: z-opac.h:48