2 * Copyright (c) 1995-2002, Index Data
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.26 2002-12-16 13:13:53 adam Exp $
15 #include <yaz/marcdisp.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/yaz-util.h>
27 yaz_marc_t yaz_marc_create(void)
29 yaz_marc_t mt = xmalloc(sizeof(*mt));
30 mt->xml = YAZ_MARC_LINE;
33 mt->own_wr = wrbuf_alloc();
38 void yaz_marc_destroy(yaz_marc_t mt)
42 wrbuf_free (mt->own_wr, 1);
46 static void marc_cdata (yaz_marc_t mt, const char *buf, size_t len)
49 for (i = 0; i<len; i++)
55 wrbuf_puts(mt->wr, "<");
58 wrbuf_puts(mt->wr, ">");
61 wrbuf_puts(mt->wr, "&");
64 wrbuf_putc(mt->wr, buf[i]);
68 wrbuf_putc(mt->wr, buf[i]);
73 static void marc_cdata (yaz_marc_t mt, const char *buf, size_t len)
76 marc_cdata2 (mt, buf, len);
80 size_t inbytesleft = len;
81 const char *inp = buf;
85 size_t outbytesleft = sizeof(outbuf);
87 size_t r = yaz_iconv (mt->cd, (char**) &inp, &inbytesleft,
88 &outp, &outbytesleft);
89 if (r == (size_t) (-1))
91 int e = yaz_iconv_error(mt->cd);
92 if (e != YAZ_ICONV_E2BIG)
95 marc_cdata2 (mt, outbuf, outp - outbuf);
101 static int yaz_marc_decode_int (yaz_marc_t mt, const char *buf, int bsize)
105 int indicator_length;
106 int identifier_length;
108 int length_data_entry;
110 int length_implementation;
115 wrbuf_rewind(mt->wr);
117 record_length = atoi_n (buf, 5);
118 if (record_length < 25)
124 sprintf (str, "Record length %d - aborting\n", record_length);
125 wrbuf_puts (mt->wr, str);
129 /* ballout if bsize is known and record_length is than that */
130 if (bsize != -1 && record_length > bsize)
132 if (isdigit(buf[10]))
133 indicator_length = atoi_n (buf+10, 1);
135 indicator_length = 2;
136 if (isdigit(buf[11]))
137 identifier_length = atoi_n (buf+11, 1);
139 identifier_length = 2;
140 base_address = atoi_n (buf+12, 5);
142 length_data_entry = atoi_n (buf+20, 1);
143 length_starting = atoi_n (buf+21, 1);
144 length_implementation = atoi_n (buf+22, 1);
152 case YAZ_MARC_SIMPLEXML:
153 wrbuf_puts (mt->wr, "<iso2709\n");
154 sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
155 wrbuf_puts (mt->wr, str);
156 sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
157 wrbuf_puts (mt->wr, str);
158 for (i = 1; i<=19; i++)
160 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
161 wrbuf_puts (mt->wr, str);
163 wrbuf_puts (mt->wr, ">\n");
165 case YAZ_MARC_OAIMARC:
168 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\""
170 " xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\""
172 " xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc.xsd\""
176 sprintf (str, " status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
177 buf[5], buf[6], buf[7]);
178 wrbuf_puts (mt->wr, str);
180 case YAZ_MARC_MARCXML:
183 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
184 " <leader>%.24s</leader>\n", buf);
193 wrbuf_puts (mt->wr, "<!--\n");
194 sprintf (str, "Record length %5d\n", record_length);
195 wrbuf_puts (mt->wr, str);
196 sprintf (str, "Indicator length %5d\n", indicator_length);
197 wrbuf_puts (mt->wr, str);
198 sprintf (str, "Identifier length %5d\n", identifier_length);
199 wrbuf_puts (mt->wr, str);
200 sprintf (str, "Base address %5d\n", base_address);
201 wrbuf_puts (mt->wr, str);
202 sprintf (str, "Length data entry %5d\n", length_data_entry);
203 wrbuf_puts (mt->wr, str);
204 sprintf (str, "Length starting %5d\n", length_starting);
205 wrbuf_puts (mt->wr, str);
206 sprintf (str, "Length implementation %5d\n", length_implementation);
207 wrbuf_puts (mt->wr, str);
209 wrbuf_puts (mt->wr, "-->\n");
212 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
214 entry_p += 3+length_data_entry+length_starting;
215 if (entry_p >= record_length)
218 base_address = entry_p+1;
219 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
226 int identifier_flag = 1;
228 memcpy (tag, buf+entry_p, 3);
231 data_length = atoi_n (buf+entry_p, length_data_entry);
232 entry_p += length_data_entry;
233 data_offset = atoi_n (buf+entry_p, length_starting);
234 entry_p += length_starting;
235 i = data_offset + base_address;
236 end_offset = i+data_length-1;
238 if (indicator_length < 4 && indicator_length > 0)
240 if (buf[i + indicator_length] != ISO2709_IDFS)
243 else if (!memcmp (tag, "00", 2))
250 wrbuf_puts (mt->wr, "Tag: ");
251 wrbuf_puts (mt->wr, tag);
252 wrbuf_puts (mt->wr, " ");
254 case YAZ_MARC_SIMPLEXML:
255 wrbuf_printf (mt->wr, "<field tag=\"%s\"", tag);
257 case YAZ_MARC_OAIMARC:
259 wrbuf_printf (mt->wr, " <varfield id=\"%s\"", tag);
261 wrbuf_printf (mt->wr, " <fixfield id=\"%s\"", tag);
263 case YAZ_MARC_MARCXML:
265 wrbuf_printf (mt->wr, " <datafield tag=\"%s\"", tag);
267 wrbuf_printf (mt->wr, " <controlfield tag=\"%s\"", tag);
272 for (j = 0; j<indicator_length; j++, i++)
278 wrbuf_puts (mt->wr, " Ind: ");
279 wrbuf_putc (mt->wr, buf[i]);
281 case YAZ_MARC_SIMPLEXML:
282 wrbuf_printf (mt->wr, " Indicator%d=\"%c\"", j+1, buf[i]);
284 case YAZ_MARC_OAIMARC:
285 wrbuf_printf (mt->wr, " i%d=\"%c\"", j+1, buf[i]);
287 case YAZ_MARC_MARCXML:
288 wrbuf_printf (mt->wr, " ind%d=\"%c\"", j+1, buf[i]);
294 wrbuf_puts (mt->wr, ">");
296 wrbuf_puts (mt->wr, "\n");
300 if (mt->debug && !mt->xml)
301 wrbuf_puts (mt->wr, " Fields: ");
305 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
312 wrbuf_puts (mt->wr, " $");
313 for (j = 1; j<identifier_length; j++, i++)
314 wrbuf_putc (mt->wr, buf[i]);
315 wrbuf_putc (mt->wr, ' ');
317 case YAZ_MARC_SIMPLEXML:
318 wrbuf_puts (mt->wr, " <subfield code=\"");
319 for (j = 1; j<identifier_length; j++, i++)
320 wrbuf_putc (mt->wr, buf[i]);
321 wrbuf_puts (mt->wr, "\">");
323 case YAZ_MARC_OAIMARC:
324 wrbuf_puts (mt->wr, " <subfield label=\"");
325 for (j = 1; j<identifier_length; j++, i++)
326 wrbuf_putc (mt->wr, buf[i]);
327 wrbuf_puts (mt->wr, "\">");
329 case YAZ_MARC_MARCXML:
330 wrbuf_puts (mt->wr, " <subfield code=\"");
331 for (j = 1; j<identifier_length; j++, i++)
332 wrbuf_putc (mt->wr, buf[i]);
333 wrbuf_puts (mt->wr, "\">");
337 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
338 buf[i] != ISO2709_FS && i < end_offset)
340 marc_cdata(mt, buf + i0, i - i0);
343 wrbuf_puts (mt->wr, "</subfield>\n");
349 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
351 marc_cdata(mt, buf + i0, i - i0);
354 wrbuf_putc (mt->wr, '\n');
356 wrbuf_puts (mt->wr, " <!-- separator but not at end of field -->\n");
357 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
358 wrbuf_puts (mt->wr, " <!-- no separator at end of field -->\n");
361 case YAZ_MARC_SIMPLEXML:
362 wrbuf_puts (mt->wr, "</field>\n");
364 case YAZ_MARC_OAIMARC:
366 wrbuf_puts (mt->wr, " </varfield>\n");
368 wrbuf_puts (mt->wr, " </fixfield>\n");
370 case YAZ_MARC_MARCXML:
372 wrbuf_puts (mt->wr, " </datafield>\n");
374 wrbuf_puts (mt->wr, " </controlfield>\n");
381 wrbuf_puts (mt->wr, "");
383 case YAZ_MARC_SIMPLEXML:
384 wrbuf_puts (mt->wr, "</iso2709>\n");
386 case YAZ_MARC_OAIMARC:
387 wrbuf_puts (mt->wr, "</oai_marc>\n");
389 case YAZ_MARC_MARCXML:
390 wrbuf_puts (mt->wr, "</record>\n");
393 return record_length;
396 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
397 char **result, int *rsize)
399 int r = yaz_marc_decode_int(mt, buf, bsize);
403 *result = wrbuf_buf(mt->wr);
405 *rsize = wrbuf_len(mt->wr);
410 int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf,
411 int bsize, WRBUF wrbuf)
414 return yaz_marc_decode_int (mt, buf, bsize);
418 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
424 void yaz_marc_debug(yaz_marc_t mt, int level)
431 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
433 yaz_marc_t mt = yaz_marc_create();
439 r = yaz_marc_decode_int(mt, buf, bsize);
440 yaz_marc_destroy(mt);
445 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
447 return yaz_marc_decode(buf, wr, debug, bsize, 0);
451 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
453 yaz_marc_t mt = yaz_marc_create();
457 r = yaz_marc_decode_int (mt, buf, bsize);
461 fwrite (wrbuf_buf(mt->wr), 1, wrbuf_len(mt->wr), outf);
462 yaz_marc_destroy(mt);
467 int marc_display_ex (const char *buf, FILE *outf, int debug)
469 return marc_display_exl (buf, outf, debug, -1);
473 int marc_display (const char *buf, FILE *outf)
475 return marc_display_ex (buf, outf, 0);