2 * Copyright (c) 1995-2003, Index Data
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.3 2003-12-17 12:28:07 adam Exp $
15 #include <yaz/marcdisp.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/yaz-util.h>
26 yaz_marc_t yaz_marc_create(void)
28 yaz_marc_t mt = (yaz_marc_t) xmalloc(sizeof(*mt));
29 mt->xml = YAZ_MARC_LINE;
31 mt->m_wr = wrbuf_alloc();
36 void yaz_marc_destroy(yaz_marc_t mt)
40 wrbuf_free (mt->m_wr, 1);
44 static void marc_cdata (yaz_marc_t mt, const char *buf, size_t len, WRBUF wr)
47 if (mt->xml == YAZ_MARC_ISO2709)
49 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
51 else if (mt->xml == YAZ_MARC_LINE)
53 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
58 for (i = 0; i<len; i++)
63 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
64 wrbuf_puts(wr, "<");
69 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
70 wrbuf_puts(wr, ">");
75 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
76 wrbuf_puts(wr, "&");
81 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
82 wrbuf_puts(wr, """);
87 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
88 wrbuf_puts(wr, "'");
94 wrbuf_iconv_write(wr, mt->iconv_cd, buf+j, i-j);
98 int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
102 int indicator_length;
103 int identifier_length;
105 int length_data_entry;
107 int length_implementation;
111 record_length = atoi_n (buf, 5);
112 if (record_length < 25)
118 sprintf (str, "Record length %d - aborting\n", record_length);
119 wrbuf_puts (wr, str);
123 /* ballout if bsize is known and record_length is less than that */
124 if (bsize != -1 && record_length > bsize)
126 if (isdigit(buf[10]))
127 indicator_length = atoi_n (buf+10, 1);
129 indicator_length = 2;
130 if (isdigit(buf[11]))
131 identifier_length = atoi_n (buf+11, 1);
133 identifier_length = 2;
134 base_address = atoi_n (buf+12, 5);
136 length_data_entry = atoi_n (buf+20, 1);
137 length_starting = atoi_n (buf+21, 1);
138 length_implementation = atoi_n (buf+22, 1);
140 if (mt->xml != YAZ_MARC_LINE)
146 case YAZ_MARC_ISO2709:
148 case YAZ_MARC_SIMPLEXML:
149 wrbuf_puts (wr, "<iso2709\n");
150 sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
151 wrbuf_puts (wr, str);
152 sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
153 wrbuf_puts (wr, str);
154 for (i = 1; i<=19; i++)
156 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
157 wrbuf_puts (wr, str);
159 wrbuf_puts (wr, ">\n");
161 case YAZ_MARC_OAIMARC:
164 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\""
166 " xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\""
168 " xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc.xsd\""
172 sprintf (str, " status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
173 buf[5], buf[6], buf[7]);
174 wrbuf_puts (wr, str);
176 case YAZ_MARC_MARCXML:
179 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
180 " <leader>%.24s</leader>\n", buf);
189 wrbuf_puts (wr, "<!--\n");
190 sprintf (str, "Record length %5d\n", record_length);
191 wrbuf_puts (wr, str);
192 sprintf (str, "Indicator length %5d\n", indicator_length);
193 wrbuf_puts (wr, str);
194 sprintf (str, "Identifier length %5d\n", identifier_length);
195 wrbuf_puts (wr, str);
196 sprintf (str, "Base address %5d\n", base_address);
197 wrbuf_puts (wr, str);
198 sprintf (str, "Length data entry %5d\n", length_data_entry);
199 wrbuf_puts (wr, str);
200 sprintf (str, "Length starting %5d\n", length_starting);
201 wrbuf_puts (wr, str);
202 sprintf (str, "Length implementation %5d\n", length_implementation);
203 wrbuf_puts (wr, str);
205 wrbuf_puts (wr, "-->\n");
208 /* first pass. determine length of directory & base of data */
209 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
211 entry_p += 3+length_data_entry+length_starting;
212 if (entry_p >= record_length)
215 if (mt->debug && base_address != entry_p+1)
217 wrbuf_printf (wr," <!-- base address not at end of directory "
218 "base=%d end=%d -->\n", base_address, entry_p+1);
220 base_address = entry_p+1;
222 if (mt->xml == YAZ_MARC_ISO2709)
224 WRBUF wr_head = wrbuf_alloc();
225 WRBUF wr_dir = wrbuf_alloc();
226 WRBUF wr_tmp = wrbuf_alloc();
229 /* second pass. create directory for ISO2709 output */
230 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
232 int data_length, data_offset, end_offset;
235 wrbuf_write(wr_dir, buf+entry_p, 3);
238 data_length = atoi_n (buf+entry_p, length_data_entry);
239 entry_p += length_data_entry;
240 data_offset = atoi_n (buf+entry_p, length_starting);
241 entry_p += length_starting;
242 i = data_offset + base_address;
243 end_offset = i+data_length-1;
245 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS &&
248 sz1 = 1+i - (data_offset + base_address);
251 sz2 = wrbuf_iconv_write(wr_tmp, mt->iconv_cd,
252 buf + data_offset+base_address, sz1);
253 wrbuf_rewind(wr_tmp);
257 wrbuf_printf(wr_dir, "%0*d", length_data_entry, sz2);
258 wrbuf_printf(wr_dir, "%0*d", length_starting, data_p);
261 wrbuf_putc(wr_dir, ISO2709_FS);
262 wrbuf_printf(wr_head, "%05d", data_p+1 + base_address);
263 wrbuf_write(wr_head, buf+5, 7);
264 wrbuf_printf(wr_head, "%05d", base_address);
265 wrbuf_write(wr_head, buf+17, 7);
267 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
268 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
269 wrbuf_free(wr_head, 1);
270 wrbuf_free(wr_dir, 1);
271 wrbuf_free(wr_tmp, 1);
273 /* third pass. create data output */
274 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
281 int identifier_flag = 1;
283 memcpy (tag, buf+entry_p, 3);
286 data_length = atoi_n (buf+entry_p, length_data_entry);
287 entry_p += length_data_entry;
288 data_offset = atoi_n (buf+entry_p, length_starting);
289 entry_p += length_starting;
290 i = data_offset + base_address;
291 end_offset = i+data_length-1;
293 if (indicator_length < 4 && indicator_length > 0)
295 if (buf[i + indicator_length] != ISO2709_IDFS)
298 else if (!memcmp (tag, "00", 2))
305 wrbuf_puts (wr, "Tag: ");
306 wrbuf_puts (wr, tag);
307 wrbuf_puts (wr, " ");
309 case YAZ_MARC_SIMPLEXML:
310 wrbuf_printf (wr, "<field tag=\"%s\"", tag);
312 case YAZ_MARC_OAIMARC:
314 wrbuf_printf (wr, " <varfield id=\"%s\"", tag);
316 wrbuf_printf (wr, " <fixfield id=\"%s\"", tag);
318 case YAZ_MARC_MARCXML:
320 wrbuf_printf (wr, " <datafield tag=\"%s\"", tag);
322 wrbuf_printf (wr, " <controlfield tag=\"%s\"", tag);
327 for (j = 0; j<indicator_length; j++, i++)
331 case YAZ_MARC_ISO2709:
332 wrbuf_putc(wr, buf[i]);
336 wrbuf_puts (wr, " Ind: ");
337 wrbuf_putc(wr, buf[i]);
339 case YAZ_MARC_SIMPLEXML:
340 wrbuf_printf(wr, " Indicator%d=\"%c\"", j+1, buf[i]);
342 case YAZ_MARC_OAIMARC:
343 wrbuf_printf(wr, " i%d=\"%c\"", j+1, buf[i]);
345 case YAZ_MARC_MARCXML:
346 wrbuf_printf(wr, " ind%d=\"%c\"", j+1, buf[i]);
350 if (mt->xml == YAZ_MARC_SIMPLEXML || mt->xml == YAZ_MARC_MARCXML
351 || mt->xml == YAZ_MARC_OAIMARC)
353 wrbuf_puts (wr, ">");
355 wrbuf_puts (wr, "\n");
357 if (mt->xml == YAZ_MARC_LINE)
360 wrbuf_puts (wr, " Fields: ");
364 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
370 case YAZ_MARC_ISO2709:
372 wrbuf_iconv_write(wr, mt->iconv_cd,
373 buf+i, identifier_length);
374 i += identifier_length;
377 wrbuf_puts (wr, " $");
378 for (j = 1; j<identifier_length; j++, i++)
379 wrbuf_putc (wr, buf[i]);
380 wrbuf_putc (wr, ' ');
382 case YAZ_MARC_SIMPLEXML:
383 wrbuf_puts (wr, " <subfield code=\"");
384 for (j = 1; j<identifier_length; j++, i++)
385 wrbuf_putc (wr, buf[i]);
386 wrbuf_puts (wr, "\">");
388 case YAZ_MARC_OAIMARC:
389 wrbuf_puts (wr, " <subfield label=\"");
390 for (j = 1; j<identifier_length; j++, i++)
391 wrbuf_putc (wr, buf[i]);
392 wrbuf_puts (wr, "\">");
394 case YAZ_MARC_MARCXML:
395 wrbuf_puts (wr, " <subfield code=\"");
396 for (j = 1; j<identifier_length; j++, i++)
397 wrbuf_putc (wr, buf[i]);
398 wrbuf_puts (wr, "\">");
402 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
403 buf[i] != ISO2709_FS && i < end_offset)
405 marc_cdata(mt, buf + i0, i - i0, wr);
407 if (mt->xml == YAZ_MARC_ISO2709 && buf[i] != ISO2709_IDFS)
408 marc_cdata(mt, buf + i, 1, wr);
410 if (mt->xml == YAZ_MARC_SIMPLEXML ||
411 mt->xml == YAZ_MARC_MARCXML ||
412 mt->xml == YAZ_MARC_OAIMARC)
413 wrbuf_puts (wr, "</subfield>\n");
419 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
421 marc_cdata(mt, buf + i0, i - i0, wr);
422 if (mt->xml == YAZ_MARC_ISO2709)
423 marc_cdata(mt, buf + i, 1, wr);
425 if (mt->xml == YAZ_MARC_LINE)
426 wrbuf_putc (wr, '\n');
428 wrbuf_puts (wr, " <!-- separator but not at end of field -->\n");
429 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
430 wrbuf_puts (wr, " <!-- no separator at end of field -->\n");
433 case YAZ_MARC_SIMPLEXML:
434 wrbuf_puts (wr, "</field>\n");
436 case YAZ_MARC_OAIMARC:
438 wrbuf_puts (wr, " </varfield>\n");
440 wrbuf_puts (wr, " </fixfield>\n");
442 case YAZ_MARC_MARCXML:
444 wrbuf_puts (wr, " </datafield>\n");
446 wrbuf_puts (wr, " </controlfield>\n");
455 case YAZ_MARC_SIMPLEXML:
456 wrbuf_puts (wr, "</iso2709>\n");
458 case YAZ_MARC_OAIMARC:
459 wrbuf_puts (wr, "</oai_marc>\n");
461 case YAZ_MARC_MARCXML:
462 wrbuf_puts (wr, "</record>\n");
464 case YAZ_MARC_ISO2709:
465 wrbuf_putc (wr, ISO2709_RS);
468 return record_length;
471 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
472 char **result, int *rsize)
474 int r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
478 *result = wrbuf_buf(mt->m_wr);
480 *rsize = wrbuf_len(mt->m_wr);
485 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
491 void yaz_marc_debug(yaz_marc_t mt, int level)
497 void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
503 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
505 yaz_marc_t mt = yaz_marc_create();
510 r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr);
511 yaz_marc_destroy(mt);
516 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
518 return yaz_marc_decode(buf, wr, debug, bsize, 0);
522 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
524 yaz_marc_t mt = yaz_marc_create();
528 r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr);
532 fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf);
533 yaz_marc_destroy(mt);
538 int marc_display_ex (const char *buf, FILE *outf, int debug)
540 return marc_display_exl (buf, outf, debug, -1);
544 int marc_display (const char *buf, FILE *outf)
546 return marc_display_ex (buf, outf, 0);