3de8d7631375c77609e324f7a226e58932570a21
[yaz-moved-to-github.git] / util / marcdump.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: marcdump.c,v 1.26 2005-01-15 19:47:15 adam Exp $
6  */
7
8 #if HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #if HAVE_XML2
13 #include <libxml/parser.h>
14 #include <libxml/tree.h>
15
16 #include <libxml/xpath.h>
17 #include <libxml/xpathInternals.h>
18
19 #endif
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
26
27 #if HAVE_LOCALE_H
28 #include <locale.h>
29 #endif
30 #if HAVE_LANGINFO_H
31 #include <langinfo.h>
32 #endif
33
34 #include <yaz/marcdisp.h>
35 #include <yaz/yaz-util.h>
36 #include <yaz/xmalloc.h>
37 #include <yaz/options.h>
38
39 #ifndef SEEK_SET
40 #define SEEK_SET 0
41 #endif
42 #ifndef SEEK_END
43 #define SEEK_END 2
44 #endif
45
46 static void usage(const char *prog)
47 {
48     fprintf (stderr, "Usage: %s [-c cfile] [-f from] [-t to] [-x] [-O] [-X] [-I] [-v] file...\n",
49              prog);
50
51
52 #if HAVE_XML2
53 void print_xpath_nodes(xmlNodeSetPtr nodes, FILE* output) {
54     xmlNodePtr cur;
55     int size;
56     int i;
57     
58     assert(output);
59     size = (nodes) ? nodes->nodeNr : 0;
60     
61     fprintf(output, "Result (%d nodes):\n", size);
62     for(i = 0; i < size; ++i) {
63         assert(nodes->nodeTab[i]);
64         
65         if(nodes->nodeTab[i]->type == XML_NAMESPACE_DECL)
66         {
67             xmlNsPtr ns;
68             
69             ns = (xmlNsPtr)nodes->nodeTab[i];
70             cur = (xmlNodePtr)ns->next;
71             if(cur->ns) { 
72                 fprintf(output, "= namespace \"%s\"=\"%s\" for node %s:%s\n", 
73                     ns->prefix, ns->href, cur->ns->href, cur->name);
74             } else {
75                 fprintf(output, "= namespace \"%s\"=\"%s\" for node %s\n", 
76                     ns->prefix, ns->href, cur->name);
77             }
78         } 
79         else if(nodes->nodeTab[i]->type == XML_ELEMENT_NODE)
80         {
81             cur = nodes->nodeTab[i];        
82             if(cur->ns) { 
83                 fprintf(output, "= element node \"%s:%s\"\n", 
84                     cur->ns->href, cur->name);
85             } 
86             else
87             {
88                 fprintf(output, "= element node \"%s\"\n", 
89                     cur->name);
90             }
91         }
92         else
93         {
94             cur = nodes->nodeTab[i];    
95             fprintf(output, "= node \"%s\": type %d\n", cur->name, cur->type);
96         }
97     }
98 }
99 #endif
100
101 int main (int argc, char **argv)
102 {
103     int r;
104     int libxml_dom_test = 0;
105     int print_offset = 0;
106     char *arg;
107     int verbose = 0;
108     FILE *inf;
109     char buf[100001];
110     char *prog = *argv;
111     int no = 0;
112     int xml = 0;
113     FILE *cfile = 0;
114     char *from = 0, *to = 0;
115     int num = 1;
116     
117 #if HAVE_LOCALE_H
118     setlocale(LC_CTYPE, "");
119 #endif
120 #if HAVE_LANGINFO_H
121 #ifdef CODESET
122     to = nl_langinfo(CODESET);
123 #endif
124 #endif
125
126     while ((r = options("pvc:xOXIf:t:2", argv, argc, &arg)) != -2)
127     {
128         int count;
129         no++;
130         switch (r)
131         {
132         case 'f':
133             from = arg;
134             break;
135         case 't':
136             to = arg;
137             break;
138         case 'c':
139             if (cfile)
140                 fclose (cfile);
141             cfile = fopen (arg, "w");
142             break;
143         case 'x':
144             xml = YAZ_MARC_SIMPLEXML;
145             break;
146         case 'O':
147             xml = YAZ_MARC_OAIMARC;
148             break;
149         case 'X':
150             xml = YAZ_MARC_MARCXML;
151             break;
152         case 'I':
153             xml = YAZ_MARC_ISO2709;
154             break;
155         case 'p':
156             print_offset = 1;
157             break;
158         case '2':
159             libxml_dom_test = 1;
160             break;
161         case 0:
162             inf = fopen (arg, "rb");
163             count = 0;
164             if (!inf)
165             {
166                 fprintf (stderr, "%s: cannot open %s:%s\n",
167                          prog, arg, strerror (errno));
168                 exit(1);
169             }
170             if (cfile)
171                 fprintf (cfile, "char *marc_records[] = {\n");
172             if (1)
173             {
174                 yaz_marc_t mt = yaz_marc_create();
175                 yaz_iconv_t cd = 0;
176
177                 if (from && to)
178                 {
179                     cd = yaz_iconv_open(to, from);
180                     if (!cd)
181                     {
182                         fprintf(stderr, "conversion from %s to %s "
183                                 "unsupported\n", from, to);
184                         exit(2);
185                     }
186                     yaz_marc_iconv(mt, cd);
187                 }
188                 yaz_marc_xml(mt, xml);
189                 yaz_marc_debug(mt, verbose);
190                 while (1)
191                 {
192                     int len;
193                     char *result;
194                     int rlen;
195                     
196                     r = fread (buf, 1, 5, inf);
197                     if (r < 5)
198                     {
199                         if (r && print_offset)
200                             printf ("Extra %d bytes", r);
201                         break;
202                     }
203                     if (print_offset)
204                     {
205                         long off = ftell(inf);
206                         printf ("Record %d offset %ld\n", num, (long) off);
207                     }
208                     len = atoi_n(buf, 5);
209                     if (len < 25 || len > 100000)
210                         break;
211                     len = len - 5;
212                     r = fread (buf + 5, 1, len, inf);
213                     if (r < len)
214                         break;
215                     r = yaz_marc_decode_buf (mt, buf, -1, &result, &rlen);
216                     if (r <= 0)
217                         break;
218                     fwrite (result, rlen, 1, stdout);
219 #if HAVE_XML2
220                     if (libxml_dom_test)
221                     {
222                         xmlDocPtr doc = xmlParseMemory(result, rlen);
223                         if (!doc)
224                             fprintf(stderr, "xmLParseMemory failed\n");
225                         else
226                         {
227                             int i;
228                             xmlXPathContextPtr xpathCtx; 
229                             xmlXPathObjectPtr xpathObj; 
230                             static const char *xpathExpr[] = {
231                                 "/record/datafield[@tag='245']/subfield[@code='a']",
232                                 "/record/datafield[@tag='100']/subfield",
233                                 "/record/datafield[@tag='245']/subfield[@code='a']",
234                                 "/record/datafield[@tag='650']/subfield",
235                                 "/record/datafield[@tag='650']",
236                                 0};
237                             
238                             xpathCtx = xmlXPathNewContext(doc);
239
240                             for (i = 0; xpathExpr[i]; i++) {
241                                 xpathObj = xmlXPathEvalExpression(xpathExpr[i], xpathCtx);
242                                 if(xpathObj == NULL) {
243                                     fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr[i]);
244                                 }
245                                 else
246                                 {
247                                     print_xpath_nodes(xpathObj->nodesetval, stdout);
248                                     xmlXPathFreeObject(xpathObj);
249                                 }
250                             }
251                             xmlXPathFreeContext(xpathCtx); 
252                             xmlFreeDoc(doc);
253                         }
254                     }
255 #endif
256                     if (cfile)
257                     {
258                         char *p = buf;
259                         int i;
260                         if (count)
261                             fprintf (cfile, ",");
262                         fprintf (cfile, "\n");
263                         for (i = 0; i < r; i++)
264                         {
265                             if ((i & 15) == 0)
266                                 fprintf (cfile, "  \"");
267                             fprintf (cfile, "\\x%02X", p[i] & 255);
268                             
269                             if (i < r - 1 && (i & 15) == 15)
270                                 fprintf (cfile, "\"\n");
271                             
272                         }
273                         fprintf (cfile, "\"\n");
274                     }
275                     num++;
276                 }
277                 count++;
278                 if (cd)
279                     yaz_iconv_close(cd);
280                 yaz_marc_destroy(mt);
281             }
282             if (cfile)
283                 fprintf (cfile, "};\n");
284             fclose(inf);
285             break;
286         case 'v':
287             verbose++;
288             break;
289         default:
290             usage(prog);
291             exit (1);
292         }
293     }
294     if (cfile)
295         fclose (cfile);
296     if (!no)
297     {
298         usage(prog);
299         exit (1);
300     }
301     exit (0);
302 }