OAI MARC display
[yaz-moved-to-github.git] / util / marcdisp.c
1 /*
2  * Copyright (c) 1995-2002, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: marcdisp.c,v 1.21 2002-10-04 10:19:58 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <ctype.h>
15 #include <yaz/marcdisp.h>
16 #include <yaz/wrbuf.h>
17 #include <yaz/yaz-util.h>
18
19 int yaz_marc_decode (const char *buf, WRBUF wr, int debug, int bsize, int xml)
20 {
21     int entry_p;
22     int record_length;
23     int indicator_length;
24     int identifier_length;
25     int base_address;
26     int length_data_entry;
27     int length_starting;
28     int length_implementation;
29
30     record_length = atoi_n (buf, 5);
31     if (record_length < 25)
32     {
33         if (debug)
34         {
35             char str[40];
36             
37             sprintf (str, "Record length %d - aborting\n", record_length);
38             wrbuf_puts (wr, str);
39         }
40         return -1;
41     }
42     /* ballout if bsize is known and record_length is than that */
43     if (bsize != -1 && record_length > bsize)
44         return -1;
45     if (isdigit(buf[10]))
46         indicator_length = atoi_n (buf+10, 1);
47     else
48         indicator_length = 2;
49     if (isdigit(buf[11]))
50         identifier_length = atoi_n (buf+11, 1);
51     else
52         identifier_length = 2;
53     base_address = atoi_n (buf+12, 5);
54
55     length_data_entry = atoi_n (buf+20, 1);
56     length_starting = atoi_n (buf+21, 1);
57     length_implementation = atoi_n (buf+22, 1);
58
59     if (xml)
60     {
61         char str[80];
62         int i;
63         if (xml > 1)
64         {
65             wrbuf_puts(
66                 wr,
67                 "<sequence xmlns=\"http://www.dlib.vt.edu/projects/OAi/marcxml/container\"\n"
68                 
69                 "  xmlns:xsi=\"http://www.w3.org/2000/10/XMLSchema-instance\"\n"
70                 "    xsi:schemaLocation=\"http://www.openarchives.org/OAI/oai_marc\n"
71                 "    http://www.openarchives.org/OAI/oai_marc.xsd\n"
72                 "    http://www.dlib.vt.edu/projects/OAi/marcxml/container\n"
73                 "    http://www.dlib.vt.edu/projects/OAi/marcxml/container.xsd\"\n"
74                 );
75             wrbuf_puts(
76                 wr,
77                 "<oai_marc xmlns=\"http://www.openarchives.org/OIA/oai_marc\"" );
78             
79             sprintf (str, "status=\"%c\" type=\"%c\" catForm=\"%c\">\n",
80                      buf[5], buf[6], buf[7]);
81             wrbuf_puts (wr, str);
82         }
83         else
84         {
85             wrbuf_puts (wr, "<iso2709\n");
86             sprintf (str, " RecordStatus=\"%c\"\n", buf[5]);
87             wrbuf_puts (wr, str);
88             sprintf (str, " TypeOfRecord=\"%c\"\n", buf[6]);
89             wrbuf_puts (wr, str);
90             for (i = 1; i<=19; i++)
91             {
92                 sprintf (str, " ImplDefined%d=\"%c\"\n", i, buf[6+i]);
93                 wrbuf_puts (wr, str);
94             }
95             wrbuf_puts (wr, ">\n");
96         }
97     }
98     if (debug)
99     {
100         char str[40];
101
102         if (xml)
103             wrbuf_puts (wr, "<!--\n");
104         sprintf (str, "Record length         %5d\n", record_length);
105         wrbuf_puts (wr, str);
106         sprintf (str, "Indicator length      %5d\n", indicator_length);
107         wrbuf_puts (wr, str);
108         sprintf (str, "Identifier length     %5d\n", identifier_length);
109         wrbuf_puts (wr, str);
110         sprintf (str, "Base address          %5d\n", base_address);
111         wrbuf_puts (wr, str);
112         sprintf (str, "Length data entry     %5d\n", length_data_entry);
113         wrbuf_puts (wr, str);
114         sprintf (str, "Length starting       %5d\n", length_starting);
115         wrbuf_puts (wr, str);
116         sprintf (str, "Length implementation %5d\n", length_implementation);
117         wrbuf_puts (wr, str);
118         if (xml)
119             wrbuf_puts (wr, "-->\n");
120     }
121
122     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
123     {
124         entry_p += 3+length_data_entry+length_starting;
125         if (entry_p >= record_length)
126             return -1;
127     }
128     base_address = entry_p+1;
129     for (entry_p = 24; buf[entry_p] != ISO2709_FS; )
130     {
131         int data_length;
132         int data_offset;
133         int end_offset;
134         int i, j;
135         char tag[4];
136         int identifier_flag = 1;
137
138         memcpy (tag, buf+entry_p, 3);
139         entry_p += 3;
140         tag[3] = '\0';
141         data_length = atoi_n (buf+entry_p, length_data_entry);
142         entry_p += length_data_entry;
143         data_offset = atoi_n (buf+entry_p, length_starting);
144         entry_p += length_starting;
145         i = data_offset + base_address;
146         end_offset = i+data_length-1;
147         
148         if (indicator_length < 4 && indicator_length > 0)
149         {
150             if (buf[i + indicator_length] != ISO2709_IDFS)
151                 identifier_flag = 0;
152         }
153         else if (!memcmp (tag, "00", 2))
154             identifier_flag = 0;
155
156
157         if (xml)
158         {
159             if (xml > 1)
160             {
161                 if (identifier_flag)
162                     wrbuf_puts (wr, "<varfield id=\"");
163                 else
164                     wrbuf_puts (wr, "<fixfield id=\"");
165                 wrbuf_puts (wr, tag);
166                 wrbuf_puts (wr, "\"");
167             }
168             else
169             {
170                 wrbuf_puts (wr, "<field tag=\"");
171                 wrbuf_puts (wr, tag);
172                 wrbuf_puts (wr, "\"");
173             }
174         }
175         else
176         {
177             if (debug)
178                 wrbuf_puts (wr, "Tag: ");
179             wrbuf_puts (wr, tag);
180             wrbuf_puts (wr, " ");
181         }
182         
183         if (identifier_flag)
184         {
185             if (debug && !xml)
186                 wrbuf_puts (wr, " Ind: ");
187             for (j = 0; j<indicator_length; j++, i++)
188             {
189                 if (xml)
190                 {
191                     char nostr[30];
192                     if (xml > 1)
193                         sprintf (nostr, " i%d=\"%c\"", j+1, buf[i]);
194                     else
195                         sprintf (nostr, " Indicator%d=\"%c\"", j+1, buf[i]);
196                     wrbuf_puts (wr, nostr);
197                 }
198                 else
199                     wrbuf_putc (wr, buf[i]);
200             }
201         }
202         if (xml)
203         {
204             wrbuf_puts (wr, ">");
205             if (identifier_flag)
206                 wrbuf_puts (wr, "\n");
207         }
208         else
209         {
210             if (debug && !xml)
211                 wrbuf_puts (wr, " Fields: ");
212         }
213         while (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS && i < end_offset)
214         {
215             if (identifier_flag)
216             {
217                 i++;
218                 if (xml)
219                 {
220                     if (xml > 1)
221                         wrbuf_puts (wr, "  <subfield label=\"");
222                     else
223                         wrbuf_puts (wr, "  <subfield code=\"");
224                     for (j = 1; j<identifier_length; j++, i++)
225                         wrbuf_putc (wr, buf[i]);
226                     wrbuf_puts (wr, "\">");
227                 }
228                 else
229                 {
230                     wrbuf_puts (wr, " $"); 
231                     for (j = 1; j<identifier_length; j++, i++)
232                         wrbuf_putc (wr, buf[i]);
233                     wrbuf_putc (wr, ' ');
234                 }
235                 while (buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS &&
236                        buf[i] != ISO2709_FS && i < end_offset)
237                 {
238                     if (xml && buf[i] == '<')
239                         wrbuf_puts(wr, "&lt;");
240                     else if (xml && buf[i] == '&')
241                         wrbuf_puts(wr, "&amp;");
242                     else
243                         wrbuf_putc (wr, buf[i]);
244                     i++;
245                 }
246                 if (xml)
247                     wrbuf_puts (wr, "</subfield>\n");
248             }
249             else
250             {
251                 if (xml && buf[i] == '<')
252                     wrbuf_puts(wr, "&lt;");
253                 else if (xml && buf[i] == '&')
254                     wrbuf_puts(wr, "&amp;");
255                 else if (xml && buf[i] == '"')
256                     wrbuf_puts(wr, "&quot;");
257                 else
258                     wrbuf_putc (wr, buf[i]);
259                 i++;
260             }
261         }
262         if (!xml)
263             wrbuf_putc (wr, '\n');
264         if (i < end_offset)
265             wrbuf_puts (wr, "  <!-- separator but not at end of field -->\n");
266         if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS)
267             wrbuf_puts (wr, "  <!-- no separator at end of field -->\n");
268         if (xml)
269         {
270             if (xml > 1)
271             {
272                 if (identifier_flag)
273                     wrbuf_puts (wr, "</varfield>\n");
274                 else
275                     wrbuf_puts (wr, "</fixfield>\n");
276             }
277             else
278                 wrbuf_puts (wr, "</field>\n");
279         }
280     }
281     if (xml)
282         wrbuf_puts (wr, "</iso2709>\n");
283     wrbuf_puts (wr, "");
284     return record_length;
285 }
286
287 int marc_display_wrbuf (const char *buf, WRBUF wr, int debug,
288                         int bsize)
289 {
290     return yaz_marc_decode (buf, wr, debug, bsize, 0);
291 }
292
293 int marc_display_exl (const char *buf, FILE *outf, int debug, int length)
294 {
295     int record_length;
296
297     WRBUF wrbuf = wrbuf_alloc ();
298     record_length = marc_display_wrbuf (buf, wrbuf, debug, length);
299     if (!outf)
300         outf = stdout;
301     if (record_length > 0)
302         fwrite (wrbuf_buf(wrbuf), 1, wrbuf_len(wrbuf), outf);
303     wrbuf_free (wrbuf, 1);
304     return record_length;
305 }
306
307 int marc_display_ex (const char *buf, FILE *outf, int debug)
308 {
309     return marc_display_exl (buf, outf, debug, -1);
310 }
311
312 int marc_display (const char *buf, FILE *outf)
313 {
314     return marc_display_ex (buf, outf, 0);
315 }
316
317