2 * Copyright (c) 1995-2004, Index Data
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.4 2004-03-15 21:39:06 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)
48 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
49 else if (mt->xml == YAZ_MARC_LINE)
50 wrbuf_iconv_write(wr, mt->iconv_cd, buf, len);
52 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, buf, len);
55 int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
60 int identifier_length;
62 int length_data_entry;
64 int length_implementation;
68 record_length = atoi_n (buf, 5);
69 if (record_length < 25)
75 sprintf (str, "Record length %d - aborting\n", record_length);
80 /* ballout if bsize is known and record_length is less than that */
81 if (bsize != -1 && record_length > bsize)
84 indicator_length = atoi_n (buf+10, 1);
88 identifier_length = atoi_n (buf+11, 1);
90 identifier_length = 2;
91 base_address = atoi_n (buf+12, 5);
93 length_data_entry = atoi_n (buf+20, 1);
94 length_starting = atoi_n (buf+21, 1);
95 length_implementation = atoi_n (buf+22, 1);
97 if (mt->xml != YAZ_MARC_LINE)
103 case YAZ_MARC_ISO2709:
105 case YAZ_MARC_SIMPLEXML:
106 wrbuf_puts (wr, "<iso2709\n");
107 sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
108 wrbuf_puts (wr, str);
109 sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
110 wrbuf_puts (wr, str);
111 for (i = 1; i<=19; i++)
113 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
114 wrbuf_puts (wr, str);
116 wrbuf_puts (wr, ">\n");
118 case YAZ_MARC_OAIMARC:
121 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\""
123 " xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\""
125 " xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc.xsd\""
129 sprintf (str, " status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
130 buf[5], buf[6], buf[7]);
131 wrbuf_puts (wr, str);
133 case YAZ_MARC_MARCXML:
136 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
138 marc_cdata(mt, buf, 24, wr);
139 wrbuf_printf(wr, "</leader>\n");
148 wrbuf_puts (wr, "<!--\n");
149 sprintf (str, "Record length %5d\n", record_length);
150 wrbuf_puts (wr, str);
151 sprintf (str, "Indicator length %5d\n", indicator_length);
152 wrbuf_puts (wr, str);
153 sprintf (str, "Identifier length %5d\n", identifier_length);
154 wrbuf_puts (wr, str);
155 sprintf (str, "Base address %5d\n", base_address);
156 wrbuf_puts (wr, str);
157 sprintf (str, "Length data entry %5d\n", length_data_entry);
158 wrbuf_puts (wr, str);
159 sprintf (str, "Length starting %5d\n", length_starting);
160 wrbuf_puts (wr, str);
161 sprintf (str, "Length implementation %5d\n", length_implementation);
162 wrbuf_puts (wr, str);
164 wrbuf_puts (wr, "-->\n");
167 /* first pass. determine length of directory & base of data */
168 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
170 entry_p += 3+length_data_entry+length_starting;
171 if (entry_p >= record_length)
174 if (mt->debug && base_address != entry_p+1)
176 wrbuf_printf (wr," <!-- base address not at end of directory "
177 "base=%d end=%d -->\n", base_address, entry_p+1);
179 base_address = entry_p+1;
181 if (mt->xml == YAZ_MARC_ISO2709)
183 WRBUF wr_head = wrbuf_alloc();
184 WRBUF wr_dir = wrbuf_alloc();
185 WRBUF wr_tmp = wrbuf_alloc();
188 /* second pass. create directory for ISO2709 output */
189 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
191 int data_length, data_offset, end_offset;
194 wrbuf_write(wr_dir, buf+entry_p, 3);
197 data_length = atoi_n (buf+entry_p, length_data_entry);
198 entry_p += length_data_entry;
199 data_offset = atoi_n (buf+entry_p, length_starting);
200 entry_p += length_starting;
201 i = data_offset + base_address;
202 end_offset = i+data_length-1;
204 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS &&
207 sz1 = 1+i - (data_offset + base_address);
210 sz2 = wrbuf_iconv_write(wr_tmp, mt->iconv_cd,
211 buf + data_offset+base_address, sz1);
212 wrbuf_rewind(wr_tmp);
216 wrbuf_printf(wr_dir, "%0*d", length_data_entry, sz2);
217 wrbuf_printf(wr_dir, "%0*d", length_starting, data_p);
220 wrbuf_putc(wr_dir, ISO2709_FS);
221 wrbuf_printf(wr_head, "%05d", data_p+1 + base_address);
222 wrbuf_write(wr_head, buf+5, 7);
223 wrbuf_printf(wr_head, "%05d", base_address);
224 wrbuf_write(wr_head, buf+17, 7);
226 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
227 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
228 wrbuf_free(wr_head, 1);
229 wrbuf_free(wr_dir, 1);
230 wrbuf_free(wr_tmp, 1);
232 /* third pass. create data output */
233 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
240 int identifier_flag = 1;
242 memcpy (tag, buf+entry_p, 3);
245 data_length = atoi_n (buf+entry_p, length_data_entry);
246 entry_p += length_data_entry;
247 data_offset = atoi_n (buf+entry_p, length_starting);
248 entry_p += length_starting;
249 i = data_offset + base_address;
250 end_offset = i+data_length-1;
252 if (indicator_length < 4 && indicator_length > 0)
254 if (buf[i + indicator_length] != ISO2709_IDFS)
257 else if (!memcmp (tag, "00", 2))
264 wrbuf_puts (wr, "Tag: ");
265 wrbuf_puts (wr, tag);
266 wrbuf_puts (wr, " ");
268 case YAZ_MARC_SIMPLEXML:
269 wrbuf_printf (wr, "<field tag=\"%s\"", tag);
271 case YAZ_MARC_OAIMARC:
273 wrbuf_printf (wr, " <varfield id=\"%s\"", tag);
275 wrbuf_printf (wr, " <fixfield id=\"%s\"", tag);
277 case YAZ_MARC_MARCXML:
279 wrbuf_printf (wr, " <datafield tag=\"%s\"", tag);
281 wrbuf_printf (wr, " <controlfield tag=\"%s\"", tag);
286 for (j = 0; j<indicator_length; j++, i++)
290 case YAZ_MARC_ISO2709:
291 wrbuf_putc(wr, buf[i]);
295 wrbuf_puts (wr, " Ind: ");
296 wrbuf_putc(wr, buf[i]);
298 case YAZ_MARC_SIMPLEXML:
299 wrbuf_printf(wr, " Indicator%d=\"%c\"", j+1, buf[i]);
301 case YAZ_MARC_OAIMARC:
302 wrbuf_printf(wr, " i%d=\"%c\"", j+1, buf[i]);
304 case YAZ_MARC_MARCXML:
305 wrbuf_printf(wr, " ind%d=\"%c\"", j+1, buf[i]);
309 if (mt->xml == YAZ_MARC_SIMPLEXML || mt->xml == YAZ_MARC_MARCXML
310 || mt->xml == YAZ_MARC_OAIMARC)
312 wrbuf_puts (wr, ">");
314 wrbuf_puts (wr, "\n");
316 if (mt->xml == YAZ_MARC_LINE)
319 wrbuf_puts (wr, " Fields: ");
323 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
329 case YAZ_MARC_ISO2709:
331 wrbuf_iconv_write(wr, mt->iconv_cd,
332 buf+i, identifier_length);
333 i += identifier_length;
336 wrbuf_puts (wr, " $");
337 for (j = 1; j<identifier_length; j++, i++)
338 wrbuf_putc (wr, buf[i]);
339 wrbuf_putc (wr, ' ');
341 case YAZ_MARC_SIMPLEXML:
342 wrbuf_puts (wr, " <subfield code=\"");
343 for (j = 1; j<identifier_length; j++, i++)
344 wrbuf_putc (wr, buf[i]);
345 wrbuf_puts (wr, "\">");
347 case YAZ_MARC_OAIMARC:
348 wrbuf_puts (wr, " <subfield label=\"");
349 for (j = 1; j<identifier_length; j++, i++)
350 wrbuf_putc (wr, buf[i]);
351 wrbuf_puts (wr, "\">");
353 case YAZ_MARC_MARCXML:
354 wrbuf_puts (wr, " <subfield code=\"");
355 for (j = 1; j<identifier_length; j++, i++)
356 wrbuf_putc (wr, buf[i]);
357 wrbuf_puts (wr, "\">");
361 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
362 buf[i] != ISO2709_FS && i < end_offset)
364 marc_cdata(mt, buf + i0, i - i0, wr);
366 if (mt->xml == YAZ_MARC_ISO2709 && buf[i] != ISO2709_IDFS)
367 marc_cdata(mt, buf + i, 1, wr);
369 if (mt->xml == YAZ_MARC_SIMPLEXML ||
370 mt->xml == YAZ_MARC_MARCXML ||
371 mt->xml == YAZ_MARC_OAIMARC)
372 wrbuf_puts (wr, "</subfield>\n");
378 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
380 marc_cdata(mt, buf + i0, i - i0, wr);
381 if (mt->xml == YAZ_MARC_ISO2709)
382 marc_cdata(mt, buf + i, 1, wr);
384 if (mt->xml == YAZ_MARC_LINE)
385 wrbuf_putc (wr, '\n');
387 wrbuf_puts (wr, " <!-- separator but not at end of field -->\n");
388 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
389 wrbuf_puts (wr, " <!-- no separator at end of field -->\n");
392 case YAZ_MARC_SIMPLEXML:
393 wrbuf_puts (wr, "</field>\n");
395 case YAZ_MARC_OAIMARC:
397 wrbuf_puts (wr, " </varfield>\n");
399 wrbuf_puts (wr, " </fixfield>\n");
401 case YAZ_MARC_MARCXML:
403 wrbuf_puts (wr, " </datafield>\n");
405 wrbuf_puts (wr, " </controlfield>\n");
414 case YAZ_MARC_SIMPLEXML:
415 wrbuf_puts (wr, "</iso2709>\n");
417 case YAZ_MARC_OAIMARC:
418 wrbuf_puts (wr, "</oai_marc>\n");
420 case YAZ_MARC_MARCXML:
421 wrbuf_puts (wr, "</record>\n");
423 case YAZ_MARC_ISO2709:
424 wrbuf_putc (wr, ISO2709_RS);
427 return record_length;
430 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
431 char **result, int *rsize)
433 int r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
437 *result = wrbuf_buf(mt->m_wr);
439 *rsize = wrbuf_len(mt->m_wr);
444 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
450 void yaz_marc_debug(yaz_marc_t mt, int level)
456 void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
462 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
464 yaz_marc_t mt = yaz_marc_create();
469 r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr);
470 yaz_marc_destroy(mt);
475 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
477 return yaz_marc_decode(buf, wr, debug, bsize, 0);
481 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
483 yaz_marc_t mt = yaz_marc_create();
487 r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr);
491 fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf);
492 yaz_marc_destroy(mt);
497 int marc_display_ex (const char *buf, FILE *outf, int debug)
499 return marc_display_exl (buf, outf, debug, -1);
503 int marc_display (const char *buf, FILE *outf)
505 return marc_display_ex (buf, outf, 0);