2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.7 2004-10-01 11:45:48 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)
46 if (mt->xml == YAZ_MARC_ISO2709)
47 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
48 else if (mt->xml == YAZ_MARC_LINE)
49 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
51 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, buf, len);
54 int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
59 int identifier_length;
61 int length_data_entry;
63 int length_implementation;
67 record_length = atoi_n (buf, 5);
68 if (record_length < 25)
74 sprintf (str, "Record length %d - aborting\n", record_length);
79 /* ballout if bsize is known and record_length is less than that */
80 if (bsize != -1 && record_length > bsize)
83 indicator_length = atoi_n (buf+10, 1);
87 identifier_length = atoi_n (buf+11, 1);
89 identifier_length = 2;
90 base_address = atoi_n (buf+12, 5);
92 length_data_entry = atoi_n (buf+20, 1);
93 length_starting = atoi_n (buf+21, 1);
94 length_implementation = atoi_n (buf+22, 1);
96 if (mt->xml != YAZ_MARC_LINE)
102 case YAZ_MARC_ISO2709:
104 case YAZ_MARC_SIMPLEXML:
105 wrbuf_puts (wr, "<iso2709\n");
106 sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
107 wrbuf_puts (wr, str);
108 sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
109 wrbuf_puts (wr, str);
110 for (i = 1; i<=19; i++)
112 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
113 wrbuf_puts (wr, str);
115 wrbuf_puts (wr, ">\n");
117 case YAZ_MARC_OAIMARC:
120 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\""
122 " xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\""
124 " xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc.xsd\""
128 sprintf (str, " status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
129 buf[5], buf[6], buf[7]);
130 wrbuf_puts (wr, str);
132 case YAZ_MARC_MARCXML:
135 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
138 marc_cdata(mt, buf, 9, wr);
139 marc_cdata(mt, "a", 1, wr); /* set leader to signal unicode */
140 marc_cdata(mt, buf+10, 14, wr);
142 marc_cdata(mt, buf, 24, wr); /* leave header as is .. */
144 wrbuf_printf(wr, "</leader>\n");
153 wrbuf_puts (wr, "<!--\n");
154 sprintf (str, "Record length %5d\n", record_length);
155 wrbuf_puts (wr, str);
156 sprintf (str, "Indicator length %5d\n", indicator_length);
157 wrbuf_puts (wr, str);
158 sprintf (str, "Identifier length %5d\n", identifier_length);
159 wrbuf_puts (wr, str);
160 sprintf (str, "Base address %5d\n", base_address);
161 wrbuf_puts (wr, str);
162 sprintf (str, "Length data entry %5d\n", length_data_entry);
163 wrbuf_puts (wr, str);
164 sprintf (str, "Length starting %5d\n", length_starting);
165 wrbuf_puts (wr, str);
166 sprintf (str, "Length implementation %5d\n", length_implementation);
167 wrbuf_puts (wr, str);
169 wrbuf_puts (wr, "-->\n");
172 /* first pass. determine length of directory & base of data */
173 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
175 entry_p += 3+length_data_entry+length_starting;
176 if (entry_p >= record_length)
179 if (mt->debug && base_address != entry_p+1)
181 wrbuf_printf (wr," <!-- base address not at end of directory "
182 "base=%d end=%d -->\n", base_address, entry_p+1);
184 base_address = entry_p+1;
186 if (mt->xml == YAZ_MARC_ISO2709)
188 WRBUF wr_head = wrbuf_alloc();
189 WRBUF wr_dir = wrbuf_alloc();
190 WRBUF wr_tmp = wrbuf_alloc();
193 /* second pass. create directory for ISO2709 output */
194 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
196 int data_length, data_offset, end_offset;
199 wrbuf_write(wr_dir, buf+entry_p, 3);
202 data_length = atoi_n (buf+entry_p, length_data_entry);
203 entry_p += length_data_entry;
204 data_offset = atoi_n (buf+entry_p, length_starting);
205 entry_p += length_starting;
206 i = data_offset + base_address;
207 end_offset = i+data_length-1;
209 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS &&
212 sz1 = 1+i - (data_offset + base_address);
215 sz2 = wrbuf_iconv_write(wr_tmp, mt->iconv_cd,
216 buf + data_offset+base_address, sz1);
217 wrbuf_rewind(wr_tmp);
221 wrbuf_printf(wr_dir, "%0*d", length_data_entry, sz2);
222 wrbuf_printf(wr_dir, "%0*d", length_starting, data_p);
225 wrbuf_putc(wr_dir, ISO2709_FS);
226 wrbuf_printf(wr_head, "%05d", data_p+1 + base_address);
227 wrbuf_write(wr_head, buf+5, 7);
228 wrbuf_printf(wr_head, "%05d", base_address);
229 wrbuf_write(wr_head, buf+17, 7);
231 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
232 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
233 wrbuf_free(wr_head, 1);
234 wrbuf_free(wr_dir, 1);
235 wrbuf_free(wr_tmp, 1);
237 /* third pass. create data output */
238 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
245 int identifier_flag = 1;
247 memcpy (tag, buf+entry_p, 3);
250 data_length = atoi_n (buf+entry_p, length_data_entry);
251 entry_p += length_data_entry;
252 data_offset = atoi_n (buf+entry_p, length_starting);
253 entry_p += length_starting;
254 i = data_offset + base_address;
255 end_offset = i+data_length-1;
257 if (indicator_length < 4 && indicator_length > 0)
259 if (buf[i + indicator_length] != ISO2709_IDFS)
262 else if (!memcmp (tag, "00", 2))
269 wrbuf_puts (wr, "Tag: ");
270 wrbuf_puts (wr, tag);
271 wrbuf_puts (wr, " ");
273 case YAZ_MARC_SIMPLEXML:
274 wrbuf_printf (wr, "<field tag=\"");
275 marc_cdata(mt, tag, strlen(tag), wr);
276 wrbuf_printf(wr, "\"");
278 case YAZ_MARC_OAIMARC:
280 wrbuf_printf (wr, " <varfield id=\"");
282 wrbuf_printf (wr, " <fixfield id=\"");
283 marc_cdata(mt, tag, strlen(tag), wr);
284 wrbuf_printf(wr, "\"");
286 case YAZ_MARC_MARCXML:
288 wrbuf_printf (wr, " <datafield tag=\"");
290 wrbuf_printf (wr, " <controlfield tag=\"");
291 marc_cdata(mt, tag, strlen(tag), wr);
292 wrbuf_printf(wr, "\"");
297 for (j = 0; j<indicator_length; j++, i++)
301 case YAZ_MARC_ISO2709:
302 wrbuf_putc(wr, buf[i]);
306 wrbuf_puts (wr, " Ind: ");
307 wrbuf_putc(wr, buf[i]);
309 case YAZ_MARC_SIMPLEXML:
310 wrbuf_printf(wr, " Indicator%d=\"", j+1);
311 marc_cdata(mt, buf+i, 1, wr);
312 wrbuf_printf(wr, "\"");
314 case YAZ_MARC_OAIMARC:
315 wrbuf_printf(wr, " i%d=\"", j+1);
316 marc_cdata(mt, buf+i, 1, wr);
317 wrbuf_printf(wr, "\"");
319 case YAZ_MARC_MARCXML:
320 wrbuf_printf(wr, " ind%d=\"", j+1);
321 marc_cdata(mt, buf+i, 1, wr);
322 wrbuf_printf(wr, "\"");
326 if (mt->xml == YAZ_MARC_SIMPLEXML || mt->xml == YAZ_MARC_MARCXML
327 || mt->xml == YAZ_MARC_OAIMARC)
329 wrbuf_puts (wr, ">");
331 wrbuf_puts (wr, "\n");
333 if (mt->xml == YAZ_MARC_LINE)
336 wrbuf_puts (wr, " Fields: ");
340 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
346 case YAZ_MARC_ISO2709:
348 wrbuf_iconv_write(wr, mt->iconv_cd,
349 buf+i, identifier_length);
350 i += identifier_length;
353 wrbuf_puts (wr, " $");
354 marc_cdata(mt, buf+i, identifier_length-1, wr);
355 i = i+identifier_length-1;
356 wrbuf_putc (wr, ' ');
358 case YAZ_MARC_SIMPLEXML:
359 wrbuf_puts (wr, " <subfield code=\"");
360 marc_cdata(mt, buf+i, identifier_length-1, wr);
361 i = i+identifier_length-1;
362 wrbuf_puts (wr, "\">");
364 case YAZ_MARC_OAIMARC:
365 wrbuf_puts (wr, " <subfield label=\"");
366 marc_cdata(mt, buf+i, identifier_length-1, wr);
367 i = i+identifier_length-1;
368 wrbuf_puts (wr, "\">");
370 case YAZ_MARC_MARCXML:
371 wrbuf_puts (wr, " <subfield code=\"");
372 marc_cdata(mt, buf+i, identifier_length-1, wr);
373 i = i+identifier_length-1;
374 wrbuf_puts (wr, "\">");
378 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
379 buf[i] != ISO2709_FS && i < end_offset)
381 marc_cdata(mt, buf + i0, i - i0, wr);
383 if (mt->xml == YAZ_MARC_ISO2709 && buf[i] != ISO2709_IDFS)
384 marc_cdata(mt, buf + i, 1, wr);
386 if (mt->xml == YAZ_MARC_SIMPLEXML ||
387 mt->xml == YAZ_MARC_MARCXML ||
388 mt->xml == YAZ_MARC_OAIMARC)
389 wrbuf_puts (wr, "</subfield>\n");
395 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
397 marc_cdata(mt, buf + i0, i - i0, wr);
398 if (mt->xml == YAZ_MARC_ISO2709)
399 marc_cdata(mt, buf + i, 1, wr);
401 if (mt->xml == YAZ_MARC_LINE)
402 wrbuf_putc (wr, '\n');
404 wrbuf_puts (wr, " <!-- separator but not at end of field -->\n");
405 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
406 wrbuf_puts (wr, " <!-- no separator at end of field -->\n");
409 case YAZ_MARC_SIMPLEXML:
410 wrbuf_puts (wr, "</field>\n");
412 case YAZ_MARC_OAIMARC:
414 wrbuf_puts (wr, " </varfield>\n");
416 wrbuf_puts (wr, " </fixfield>\n");
418 case YAZ_MARC_MARCXML:
420 wrbuf_puts (wr, " </datafield>\n");
422 wrbuf_puts (wr, " </controlfield>\n");
431 case YAZ_MARC_SIMPLEXML:
432 wrbuf_puts (wr, "</iso2709>\n");
434 case YAZ_MARC_OAIMARC:
435 wrbuf_puts (wr, "</oai_marc>\n");
437 case YAZ_MARC_MARCXML:
438 wrbuf_puts (wr, "</record>\n");
440 case YAZ_MARC_ISO2709:
441 wrbuf_putc (wr, ISO2709_RS);
444 return record_length;
447 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
448 char **result, int *rsize)
450 int r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
454 *result = wrbuf_buf(mt->m_wr);
456 *rsize = wrbuf_len(mt->m_wr);
461 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
467 void yaz_marc_debug(yaz_marc_t mt, int level)
473 void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
479 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
481 yaz_marc_t mt = yaz_marc_create();
486 r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr);
487 yaz_marc_destroy(mt);
492 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
494 return yaz_marc_decode(buf, wr, debug, bsize, 0);
498 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
500 yaz_marc_t mt = yaz_marc_create();
504 r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr);
508 fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf);
509 yaz_marc_destroy(mt);
514 int marc_display_ex (const char *buf, FILE *outf, int debug)
516 return marc_display_exl (buf, outf, debug, -1);
520 int marc_display (const char *buf, FILE *outf)
522 return marc_display_ex (buf, outf, 0);