2 * Copyright (c) 1995-2003, Index Data
3 * See the file LICENSE for details.
5 * $Id: marcdisp.c,v 1.28 2003-01-06 08:20:28 adam Exp $
15 #include <yaz/marcdisp.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/yaz-util.h>
25 yaz_marc_t yaz_marc_create(void)
27 yaz_marc_t mt = xmalloc(sizeof(*mt));
28 mt->xml = YAZ_MARC_LINE;
30 mt->m_wr = wrbuf_alloc();
34 void yaz_marc_destroy(yaz_marc_t mt)
38 wrbuf_free (mt->m_wr, 1);
42 static void marc_cdata (yaz_marc_t mt, const char *buf, size_t len, WRBUF wr)
45 for (i = 0; i<len; i++)
51 wrbuf_puts(wr, "<");
54 wrbuf_puts(wr, ">");
57 wrbuf_puts(wr, "&");
60 wrbuf_putc(wr, buf[i]);
64 wrbuf_putc(wr, buf[i]);
69 static void marc_cdata (yaz_marc_t mt, const char *buf, size_t len)
72 marc_cdata2 (mt, buf, len);
76 size_t inbytesleft = len;
77 const char *inp = buf;
81 size_t outbytesleft = sizeof(outbuf);
83 size_t r = yaz_iconv (mt->cd, (char**) &inp, &inbytesleft,
84 &outp, &outbytesleft);
85 if (r == (size_t) (-1))
87 int e = yaz_iconv_error(mt->cd);
88 if (e != YAZ_ICONV_E2BIG)
91 marc_cdata2 (mt, outbuf, outp - outbuf);
97 int yaz_marc_decode_wrbuf (yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
101 int indicator_length;
102 int identifier_length;
104 int length_data_entry;
106 int length_implementation;
110 record_length = atoi_n (buf, 5);
111 if (record_length < 25)
117 sprintf (str, "Record length %d - aborting\n", record_length);
118 wrbuf_puts (wr, str);
122 /* ballout if bsize is known and record_length is than that */
123 if (bsize != -1 && record_length > bsize)
125 if (isdigit(buf[10]))
126 indicator_length = atoi_n (buf+10, 1);
128 indicator_length = 2;
129 if (isdigit(buf[11]))
130 identifier_length = atoi_n (buf+11, 1);
132 identifier_length = 2;
133 base_address = atoi_n (buf+12, 5);
135 length_data_entry = atoi_n (buf+20, 1);
136 length_starting = atoi_n (buf+21, 1);
137 length_implementation = atoi_n (buf+22, 1);
145 case YAZ_MARC_SIMPLEXML:
146 wrbuf_puts (wr, "<iso2709\n");
147 sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
148 wrbuf_puts (wr, str);
149 sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
150 wrbuf_puts (wr, str);
151 for (i = 1; i<=19; i++)
153 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
154 wrbuf_puts (wr, str);
156 wrbuf_puts (wr, ">\n");
158 case YAZ_MARC_OAIMARC:
161 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\""
163 " xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\""
165 " xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc.xsd\""
169 sprintf (str, " status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
170 buf[5], buf[6], buf[7]);
171 wrbuf_puts (wr, str);
173 case YAZ_MARC_MARCXML:
176 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
177 " <leader>%.24s</leader>\n", buf);
186 wrbuf_puts (wr, "<!--\n");
187 sprintf (str, "Record length %5d\n", record_length);
188 wrbuf_puts (wr, str);
189 sprintf (str, "Indicator length %5d\n", indicator_length);
190 wrbuf_puts (wr, str);
191 sprintf (str, "Identifier length %5d\n", identifier_length);
192 wrbuf_puts (wr, str);
193 sprintf (str, "Base address %5d\n", base_address);
194 wrbuf_puts (wr, str);
195 sprintf (str, "Length data entry %5d\n", length_data_entry);
196 wrbuf_puts (wr, str);
197 sprintf (str, "Length starting %5d\n", length_starting);
198 wrbuf_puts (wr, str);
199 sprintf (str, "Length implementation %5d\n", length_implementation);
200 wrbuf_puts (wr, str);
202 wrbuf_puts (wr, "-->\n");
205 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
207 entry_p += 3+length_data_entry+length_starting;
208 if (entry_p >= record_length)
211 base_address = entry_p+1;
212 for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
219 int identifier_flag = 1;
221 memcpy (tag, buf+entry_p, 3);
224 data_length = atoi_n (buf+entry_p, length_data_entry);
225 entry_p += length_data_entry;
226 data_offset = atoi_n (buf+entry_p, length_starting);
227 entry_p += length_starting;
228 i = data_offset + base_address;
229 end_offset = i+data_length-1;
231 if (indicator_length < 4 && indicator_length > 0)
233 if (buf[i + indicator_length] != ISO2709_IDFS)
236 else if (!memcmp (tag, "00", 2))
243 wrbuf_puts (wr, "Tag: ");
244 wrbuf_puts (wr, tag);
245 wrbuf_puts (wr, " ");
247 case YAZ_MARC_SIMPLEXML:
248 wrbuf_printf (wr, "<field tag=\"%s\"", tag);
250 case YAZ_MARC_OAIMARC:
252 wrbuf_printf (wr, " <varfield id=\"%s\"", tag);
254 wrbuf_printf (wr, " <fixfield id=\"%s\"", tag);
256 case YAZ_MARC_MARCXML:
258 wrbuf_printf (wr, " <datafield tag=\"%s\"", tag);
260 wrbuf_printf (wr, " <controlfield tag=\"%s\"", tag);
265 for (j = 0; j<indicator_length; j++, i++)
271 wrbuf_puts (wr, " Ind: ");
272 wrbuf_putc (wr, buf[i]);
274 case YAZ_MARC_SIMPLEXML:
275 wrbuf_printf (wr, " Indicator%d=\"%c\"", j+1, buf[i]);
277 case YAZ_MARC_OAIMARC:
278 wrbuf_printf (wr, " i%d=\"%c\"", j+1, buf[i]);
280 case YAZ_MARC_MARCXML:
281 wrbuf_printf (wr, " ind%d=\"%c\"", j+1, buf[i]);
287 wrbuf_puts (wr, ">");
289 wrbuf_puts (wr, "\n");
293 if (mt->debug && !mt->xml)
294 wrbuf_puts (wr, " Fields: ");
298 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
305 wrbuf_puts (wr, " $");
306 for (j = 1; j<identifier_length; j++, i++)
307 wrbuf_putc (wr, buf[i]);
308 wrbuf_putc (wr, ' ');
310 case YAZ_MARC_SIMPLEXML:
311 wrbuf_puts (wr, " <subfield code=\"");
312 for (j = 1; j<identifier_length; j++, i++)
313 wrbuf_putc (wr, buf[i]);
314 wrbuf_puts (wr, "\">");
316 case YAZ_MARC_OAIMARC:
317 wrbuf_puts (wr, " <subfield label=\"");
318 for (j = 1; j<identifier_length; j++, i++)
319 wrbuf_putc (wr, buf[i]);
320 wrbuf_puts (wr, "\">");
322 case YAZ_MARC_MARCXML:
323 wrbuf_puts (wr, " <subfield code=\"");
324 for (j = 1; j<identifier_length; j++, i++)
325 wrbuf_putc (wr, buf[i]);
326 wrbuf_puts (wr, "\">");
330 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
331 buf[i] != ISO2709_FS && i < end_offset)
333 marc_cdata(mt, buf + i0, i - i0, wr);
336 wrbuf_puts (wr, "</subfield>\n");
342 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
344 marc_cdata(mt, buf + i0, i - i0, wr);
347 wrbuf_putc (wr, '\n');
349 wrbuf_puts (wr, " <!-- separator but not at end of field -->\n");
350 if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
351 wrbuf_puts (wr, " <!-- no separator at end of field -->\n");
354 case YAZ_MARC_SIMPLEXML:
355 wrbuf_puts (wr, "</field>\n");
357 case YAZ_MARC_OAIMARC:
359 wrbuf_puts (wr, " </varfield>\n");
361 wrbuf_puts (wr, " </fixfield>\n");
363 case YAZ_MARC_MARCXML:
365 wrbuf_puts (wr, " </datafield>\n");
367 wrbuf_puts (wr, " </controlfield>\n");
376 case YAZ_MARC_SIMPLEXML:
377 wrbuf_puts (wr, "</iso2709>\n");
379 case YAZ_MARC_OAIMARC:
380 wrbuf_puts (wr, "</oai_marc>\n");
382 case YAZ_MARC_MARCXML:
383 wrbuf_puts (wr, "</record>\n");
386 return record_length;
389 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
390 char **result, int *rsize)
392 int r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
396 *result = wrbuf_buf(mt->m_wr);
398 *rsize = wrbuf_len(mt->m_wr);
403 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
409 void yaz_marc_debug(yaz_marc_t mt, int level)
416 int yaz_marc_decode(const char *buf, WRBUF wr, int debug, int bsize, int xml)
418 yaz_marc_t mt = yaz_marc_create();
423 r = yaz_marc_decode_wrbuf(mt, buf, bsize, wr);
424 yaz_marc_destroy(mt);
429 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug, int bsize)
431 return yaz_marc_decode(buf, wr, debug, bsize, 0);
435 int marc_display_exl (const char *buf, FILE *outf, int debug, int bsize)
437 yaz_marc_t mt = yaz_marc_create();
441 r = yaz_marc_decode_wrbuf (mt, buf, bsize, mt->m_wr);
445 fwrite (wrbuf_buf(mt->m_wr), 1, wrbuf_len(mt->m_wr), outf);
446 yaz_marc_destroy(mt);
451 int marc_display_ex (const char *buf, FILE *outf, int debug)
453 return marc_display_exl (buf, outf, debug, -1);
457 int marc_display (const char *buf, FILE *outf)
459 return marc_display_ex (buf, outf, 0);