1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 #if HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8 
9 #include <yaz/record_conv.h>
10 #include <yaz/test.h>
11 #include <yaz/wrbuf.h>
12 #include <string.h>
13 #include <yaz/log.h>
14 #include <yaz/proto.h>
15 #include <yaz/prt-ext.h>
16 #include <yaz/oid_db.h>
17 #if YAZ_HAVE_XML2
18 
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
21 
22 #if YAZ_HAVE_XSLT
23 #include <libxslt/xslt.h>
24 #endif
25 
conv_configure(const char * xmlstring,WRBUF w)26 yaz_record_conv_t conv_configure(const char *xmlstring, WRBUF w)
27 {
28     xmlDocPtr doc = xmlParseMemory(xmlstring, strlen(xmlstring));
29     if (!doc)
30     {
31         wrbuf_printf(w, "xmlParseMemory");
32         return 0;
33     }
34     else
35     {
36         xmlNodePtr ptr = xmlDocGetRootElement(doc);
37         yaz_record_conv_t p = yaz_record_conv_create();
38 
39         if (p)
40         {
41             const char *srcdir = getenv("srcdir");
42             if (srcdir)
43                 yaz_record_conv_set_path(p, srcdir);
44         }
45         if (!ptr)
46         {
47             wrbuf_printf(w, "xmlDocGetRootElement");
48             yaz_record_conv_destroy(p);
49             p = 0;
50         }
51         else if (!p)
52         {
53             wrbuf_printf(w, "yaz_record_conv_create");
54         }
55         else
56         {
57 
58 
59             int r = yaz_record_conv_configure(p, ptr);
60 
61             if (r)
62             {
63                 wrbuf_puts(w, yaz_record_conv_get_error(p));
64                 yaz_record_conv_destroy(p);
65                 p = 0;
66             }
67         }
68         xmlFreeDoc(doc);
69         return p;
70     }
71 }
72 
conv_configure_test(const char * xmlstring,const char * expect_error,yaz_record_conv_t * pt)73 int conv_configure_test(const char *xmlstring, const char *expect_error,
74                         yaz_record_conv_t *pt)
75 {
76     WRBUF w = wrbuf_alloc();
77     int ret;
78 
79     yaz_record_conv_t p = conv_configure(xmlstring, w);
80 
81     if (!p)
82     {
83         if (expect_error && !strcmp(wrbuf_cstr(w), expect_error))
84             ret = 1;
85         else
86         {
87             ret = 0;
88             printf("%s\n", wrbuf_cstr(w));
89         }
90     }
91     else
92     {
93         if (expect_error)
94             ret = 0;
95         else
96             ret = 1;
97     }
98 
99     if (pt)
100         *pt = p;
101     else
102         if (p)
103             yaz_record_conv_destroy(p);
104 
105     wrbuf_destroy(w);
106     return ret;
107 }
108 
tst_configure(void)109 static void tst_configure(void)
110 {
111 
112 
113 
114     YAZ_CHECK(conv_configure_test("<bad", "xmlParseMemory", 0));
115 
116 
117     YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
118                                   "<bad/></backend>",
119                                   "Element <backend>: "
120                                   "unsupported element <bad>", 0));
121 
122 #if YAZ_HAVE_XSLT
123     YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
124                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
125                                   "<marc"
126                                   " inputcharset=\"marc-8\""
127                                   " outputcharset=\"marc-8\""
128                                   "/>"
129                                   "</backend>",
130                                   "Element <marc>: attribute 'inputformat' "
131                                   "required", 0));
132     YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
133                                   "<xslt/>"
134                                   "</backend>",
135                                   "Element <xslt>: attribute 'stylesheet' "
136                                   "expected", 0));
137 #endif
138     YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
139                                   "<marc"
140                                   " inputcharset=\"utf-8\""
141                                   " outputcharset=\"marc-8\""
142                                   " inputformat=\"xml\""
143                                   " outputformat=\"marc\""
144                                   "/>"
145                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
146                                   "</backend>",
147 #if YAZ_HAVE_XSLT
148                                   0
149 #else
150                                   "Element <backend>: unsupported element <xslt>"
151 #endif
152 				  , 0));
153 }
154 
conv_convert_test(yaz_record_conv_t p,const char * input_record,const char * output_expect_record)155 static int conv_convert_test(yaz_record_conv_t p,
156                              const char *input_record,
157                              const char *output_expect_record)
158 {
159     int ret = 0;
160     if (!p)
161     {
162         YAZ_CHECK(ret);
163     }
164     else
165     {
166         WRBUF output_record = wrbuf_alloc();
167         int r = yaz_record_conv_record(p, input_record, strlen(input_record),
168                                        output_record);
169         if (r)
170         {
171             if (output_expect_record)
172             {
173                 printf("yaz_record_conv error=%s\n",
174                        yaz_record_conv_get_error(p));
175                 ret = 0;
176             }
177             else
178                 ret = 1;
179         }
180         else
181         {
182             if (!output_expect_record)
183             {
184                 ret = 0;
185             }
186             else if (strcmp(output_expect_record, wrbuf_cstr(output_record)))
187             {
188                 ret = 0;
189                 printf("got-output_record len=%ld: %s\n",
190                        (long) wrbuf_len(output_record),
191                        wrbuf_cstr(output_record));
192                 printf("output_expect_record len=%ld %s\n",
193                        (long) strlen(output_expect_record),
194                        output_expect_record);
195             }
196             else
197             {
198                 ret = 1;
199             }
200         }
201         wrbuf_destroy(output_record);
202     }
203     return ret;
204 }
205 
conv_convert_test_iter(yaz_record_conv_t p,const char * input_record,const char * output_expect_record,int num_iter)206 static int conv_convert_test_iter(yaz_record_conv_t p,
207                                   const char *input_record,
208                                   const char *output_expect_record,
209                                   int num_iter)
210 {
211     int i;
212     int ret;
213     for (i = 0; i < num_iter; i++)
214     {
215         ret = conv_convert_test(p, input_record, output_expect_record);
216         if (!ret)
217             break;
218     }
219     return ret;
220 }
221 
tst_convert1(void)222 static void tst_convert1(void)
223 {
224     yaz_record_conv_t p = 0;
225     const char *marcxml_rec =
226         "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
227         "  <leader>00080nam a22000498a 4500</leader>\n"
228         "  <controlfield tag=\"001\">   11224466 </controlfield>\n"
229         "  <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
230         "    <subfield code=\"a\">   11224466 </subfield>\n"
231         "  </datafield>\n"
232         "</record>\n";
233     const char *tmarcxml_rec =
234         "<r xmlns=\"http://www.indexdata.com/MARC21/turboxml\">\n"
235         "  <l>00080nam a22000498a 4500</l>\n"
236         "  <c001>   11224466 </c001>\n"
237         "  <d010 i1=\" \" i2=\" \">\n"
238         "    <sa>   11224466 </sa>\n"
239         "  </d010>\n"
240         "</r>\n";
241     const char *iso2709_rec =
242         "\x30\x30\x30\x38\x30\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
243         "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
244         "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x37\x30\x30\x30\x31\x33"
245         "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
246         "\x1F\x61\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x1D";
247 
248     const char *solrmarc_rec =
249         "\x30\x30\x30\x38\x30\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
250         "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
251         "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x37\x30\x30\x30\x31\x33"
252         "#30;\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20#30;\x20\x20"
253         "#31;\x61\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20#30;#29;";
254     const char *raw_rec = /* raw is xml-string of marcxml_rec */
255         "<raw>&lt;record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
256         "  &lt;leader>00080nam a22000498a 4500&lt;/leader>\n"
257         "  &lt;controlfield tag=\"001\">   11224466 &lt;/controlfield>\n"
258         "  &lt;datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
259         "    &lt;subfield code=\"a\">   11224466 &lt;/subfield>\n"
260         "  &lt;/datafield>\n"
261         "&lt;/record>\n</raw>\n";
262 
263     YAZ_CHECK(conv_configure_test("<backend>"
264                                   "<marc"
265                                   " inputcharset=\"utf-8\""
266                                   " outputcharset=\"marc-8\""
267                                   " inputformat=\"xml\""
268                                   " outputformat=\"marc\""
269                                   "/>"
270                                   "</backend>",
271                                   0, &p));
272     YAZ_CHECK(conv_convert_test(p, marcxml_rec, iso2709_rec));
273     YAZ_CHECK(conv_convert_test(p, tmarcxml_rec, iso2709_rec));
274     yaz_record_conv_destroy(p);
275 
276     YAZ_CHECK(conv_configure_test("<backend>"
277                                   "<marc"
278                                   " outputcharset=\"utf-8\""
279                                   " inputcharset=\"marc-8\""
280                                   " outputformat=\"marcxml\""
281                                   " inputformat=\"marc\""
282                                   "/>"
283                                   "</backend>",
284                                   0, &p));
285     YAZ_CHECK(conv_convert_test(p, iso2709_rec, marcxml_rec));
286     yaz_record_conv_destroy(p);
287 
288     YAZ_CHECK(conv_configure_test("<backend>"
289                                   "<solrmarc/>"
290                                   "<marc"
291                                   " outputcharset=\"utf-8\""
292                                   " inputcharset=\"marc-8\""
293                                   " outputformat=\"marcxml\""
294                                   " inputformat=\"marc\""
295                                   "/>"
296                                   "</backend>",
297                                   0, &p));
298     YAZ_CHECK(conv_convert_test(p, solrmarc_rec, marcxml_rec));
299     yaz_record_conv_destroy(p);
300 
301     YAZ_CHECK(conv_configure_test("<backend>"
302                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
303                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
304                                   "<marc"
305                                   " inputcharset=\"utf-8\""
306                                   " outputcharset=\"marc-8\""
307                                   " inputformat=\"xml\""
308                                   " outputformat=\"marc\""
309                                   "/>"
310                                   "<marc"
311                                   " outputcharset=\"utf-8\""
312                                   " inputcharset=\"marc-8\""
313                                   " outputformat=\"marcxml\""
314                                   " inputformat=\"marc\""
315                                   "/>"
316                                   "</backend>",
317                                   0, &p));
318     YAZ_CHECK(conv_convert_test(p, marcxml_rec, marcxml_rec));
319     yaz_record_conv_destroy(p);
320 
321 
322     YAZ_CHECK(conv_configure_test("<backend>"
323                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
324                                   "<xslt stylesheet=\"test_record_conv.xsl\"/>"
325                                   "<marc"
326                                   " outputcharset=\"marc-8\""
327                                   " inputformat=\"xml\""
328                                   " outputformat=\"marc\""
329                                   "/>"
330                                   "<marc"
331                                   " inputcharset=\"marc-8\""
332                                   " outputformat=\"marcxml\""
333                                   " inputformat=\"marc\""
334                                   "/>"
335                                   "</backend>",
336                                   0, &p));
337     YAZ_CHECK(conv_convert_test(p, marcxml_rec, marcxml_rec));
338     yaz_record_conv_destroy(p);
339 
340     YAZ_CHECK(conv_configure_test("<backend>"
341                                   "<select path=\"/raw\"/>"
342                                   "</backend>",
343                                   0, &p));
344     YAZ_CHECK(conv_convert_test(p, raw_rec, marcxml_rec));
345     yaz_record_conv_destroy(p);
346 }
347 
tst_convert2(void)348 static void tst_convert2(void)
349 {
350     yaz_record_conv_t p = 0;
351     const char *marcxml_rec =
352         "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
353         "  <leader>00080nam a22000498a 4500</leader>\n"
354         "  <controlfield tag=\"001\">   11224466 </controlfield>\n"
355         "  <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
356         "    <subfield code=\"a\">k&#xf8;benhavn</subfield>\n"
357         "  </datafield>\n"
358         "</record>\n";
359     const char *iso2709_rec =
360         "\x30\x30\x30\x37\x37\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
361         "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
362         "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x34\x30\x30\x30\x31\x33"
363         "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
364         "\x1F\x61\x6b\xb2\x62\x65\x6e\x68\x61\x76\x6e\x1E\x1D";
365 
366     YAZ_CHECK(conv_configure_test("<backend>"
367                                   "<marc"
368                                   " inputcharset=\"utf-8\""
369                                   " outputcharset=\"marc-8\""
370                                   " inputformat=\"xml\""
371                                   " outputformat=\"marc\""
372                                   "/>"
373                                   "</backend>",
374                                   0, &p));
375     YAZ_CHECK(conv_convert_test_iter(p, marcxml_rec, iso2709_rec, 100));
376     yaz_record_conv_destroy(p);
377 }
378 
tst_convert3(void)379 static void tst_convert3(void)
380 {
381     NMEM nmem = nmem_create();
382     int ret;
383     yaz_record_conv_t p = 0;
384 
385     const char *iso2709_rec =
386         "\x30\x30\x30\x37\x37\x6E\x61\x6D\x20\x20\x32\x32\x30\x30\x30\x34"
387         "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
388         "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x34\x30\x30\x30\x31\x33"
389         "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
390         "\x1F\x61\x6b\xb2\x62\x65\x6e\x68\x61\x76\x6e\x1E\x1D";
391 
392     const char *opacxml_rec =
393         "<opacRecord>\n"
394         "  <bibliographicRecord>\n"
395         "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
396         "  <leader>00077nam a22000498a 4500</leader>\n"
397         "  <controlfield tag=\"001\">   11224466 </controlfield>\n"
398         "  <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
399         "    <subfield code=\"a\">k" "\xc3" "\xb8" /* oslash in UTF_8 */
400         "benhavn</subfield>\n"
401         "  </datafield>\n"
402         "</record>\n"
403         "  </bibliographicRecord>\n"
404         "<holdings>\n"
405         " <holding>\n"
406         "  <typeOfRecord>u</typeOfRecord>\n"
407         "  <encodingLevel>U</encodingLevel>\n"
408         "  <receiptAcqStatus>0</receiptAcqStatus>\n"
409         "  <dateOfReport>000000</dateOfReport>\n"
410         "  <nucCode>s-FM/GC</nucCode>\n"
411         "  <localLocation>Main or Science/Business Reading Rms - STORED OFFSITE</localLocation>\n"
412         "  <callNumber>MLCM 89/00602 (N)</callNumber>\n"
413         "  <shelvingData>FT MEADE</shelvingData>\n"
414         "  <copyNumber>Copy 1</copyNumber>\n"
415         "  <volumes>\n"
416         "   <volume>\n"
417         "    <enumeration>1</enumeration>\n"
418         "    <chronology>2</chronology>\n"
419         "    <enumAndChron>3</enumAndChron>\n"
420         "   </volume>\n"
421         "   <volume>\n"
422         "    <enumeration>1</enumeration>\n"
423         "    <chronology>2</chronology>\n"
424         "    <enumAndChron>3</enumAndChron>\n"
425         "   </volume>\n"
426         "  </volumes>\n"
427         "  <circulations>\n"
428         "   <circulation>\n"
429         "    <availableNow value=\"1\"/>\n"
430         "    <availabilityDate>20130129</availabilityDate>\n"
431         "    <itemId>1226176</itemId>\n"
432         "    <renewable value=\"0\"/>\n"
433         "    <onHold value=\"0\"/>\n"
434         "   </circulation>\n"
435         "  </circulations>\n"
436         " </holding>\n"
437         "</holdings>\n"
438         "</opacRecord>\n";
439 
440     Z_OPACRecord *z_opac = nmem_malloc(nmem, sizeof(*z_opac));
441     Z_HoldingsAndCircData *h;
442     Z_CircRecord *circ;
443 
444     z_opac->bibliographicRecord =
445         z_ext_record_oid_nmem(nmem, yaz_oid_recsyn_usmarc,
446                               iso2709_rec, strlen(iso2709_rec));
447     z_opac->num_holdingsData = 1;
448     z_opac->holdingsData = (Z_HoldingsRecord **)
449         nmem_malloc(nmem, sizeof(Z_HoldingsRecord *) * 1);
450     z_opac->holdingsData[0] = (Z_HoldingsRecord *)
451         nmem_malloc(nmem, sizeof(Z_HoldingsRecord));
452     z_opac->holdingsData[0]->which = Z_HoldingsRecord_holdingsAndCirc;
453     h = z_opac->holdingsData[0]->u.holdingsAndCirc = (Z_HoldingsAndCircData *)
454          nmem_malloc(nmem, sizeof(*h));
455     h->typeOfRecord = nmem_strdup(nmem, "u");
456     h->encodingLevel = nmem_strdup(nmem, "U");
457     h->format = 0;
458     h->receiptAcqStatus = nmem_strdup(nmem, "0");
459     h->generalRetention = 0;
460     h->completeness = 0;
461     h->dateOfReport = nmem_strdup(nmem, "000000");
462     h->nucCode = nmem_strdup(nmem, "s-FM/GC");
463     h->localLocation = nmem_strdup(nmem,
464                                    "Main or Science/Business Reading "
465                                    "Rms - STORED OFFSITE");
466     h->shelvingLocation = 0;
467     h->callNumber = nmem_strdup(nmem, "MLCM 89/00602 (N)");
468     h->shelvingData = nmem_strdup(nmem, "FT MEADE");
469     h->copyNumber = nmem_strdup(nmem, "Copy 1");
470     h->publicNote = 0;
471     h->reproductionNote = 0;
472     h->termsUseRepro = 0;
473     h->enumAndChron = 0;
474     h->num_volumes = 2;
475     h->volumes = 0;
476 
477     h->volumes = (Z_Volume **)
478         nmem_malloc(nmem, 2 * sizeof(Z_Volume *));
479 
480     h->volumes[0] = (Z_Volume *)
481         nmem_malloc(nmem, sizeof(Z_Volume));
482     h->volumes[1] = h->volumes[0];
483 
484     h->volumes[0]->enumeration = nmem_strdup(nmem, "1");
485     h->volumes[0]->chronology = nmem_strdup(nmem, "2");
486     h->volumes[0]->enumAndChron = nmem_strdup(nmem, "3");
487 
488     h->num_circulationData = 1;
489     h->circulationData = (Z_CircRecord **)
490         nmem_malloc(nmem, 1 * sizeof(Z_CircRecord *));
491     circ = h->circulationData[0] = (Z_CircRecord *)
492         nmem_malloc(nmem, sizeof(Z_CircRecord));
493     circ->availableNow = nmem_booldup(nmem, 1);
494     circ->availablityDate = nmem_strdup(nmem, "20130129");
495     circ->availableThru = 0;
496     circ->restrictions = 0;
497     circ->itemId = nmem_strdup(nmem, "1226176");
498     circ->renewable = nmem_booldup(nmem, 0);
499     circ->onHold = nmem_booldup(nmem, 0);
500     circ->enumAndChron = 0;
501     circ->midspine = 0;
502     circ->temporaryLocation = 0;
503 
504     YAZ_CHECK(conv_configure_test("<backend>"
505                                   "<marc"
506                                   " inputcharset=\"marc-8\""
507                                   " outputcharset=\"utf-8\""
508                                   " inputformat=\"marc\""
509                                   " outputformat=\"marcxml\""
510                                   "/>"
511                                   "</backend>",
512                                   0, &p));
513 
514     if (p)
515     {
516         WRBUF output_record = wrbuf_alloc();
517         ret = yaz_record_conv_opac_record(p, z_opac, output_record);
518         YAZ_CHECK(ret == 0);
519         if (ret == 0)
520         {
521             ret = strcmp(wrbuf_cstr(output_record), opacxml_rec);
522             YAZ_CHECK(ret == 0);
523             if (ret)
524             {
525                 printf("got-output_record len=%ld: %s\n",
526                        (long) wrbuf_len(output_record),
527                        wrbuf_cstr(output_record));
528                 printf("output_expect_record len=%ld %s\n",
529                        (long) strlen(opacxml_rec),
530                        opacxml_rec);
531             }
532         }
533         yaz_record_conv_destroy(p);
534         wrbuf_destroy(output_record);
535     }
536     {
537         Z_OPACRecord *opac = 0;
538         yaz_marc_t mt =  yaz_marc_create();
539         ret = yaz_xml_to_opac(mt, opacxml_rec, strlen(opacxml_rec),
540                               &opac, 0 /* iconv */, nmem, 0);
541         YAZ_CHECK(ret);
542         YAZ_CHECK(opac);
543 
544         if (opac)
545         {
546             WRBUF output_record = wrbuf_alloc();
547             char *p;
548 
549             yaz_marc_xml(mt, YAZ_MARC_MARCXML);
550             yaz_opac_decode_wrbuf(mt, opac, output_record);
551 
552             /* change MARC size to 00077 from 00078, due to
553                encoding of the aring (two bytes in UTF-8) */
554             p = strstr(wrbuf_buf(output_record), "00078");
555             YAZ_CHECK(p);
556             if (p)
557                 p[4] = '7';
558 
559             ret = strcmp(wrbuf_cstr(output_record), opacxml_rec);
560             YAZ_CHECK(ret == 0);
561             if (ret)
562             {
563                 printf("got-output_record len=%ld: %s\n",
564                        (long) wrbuf_len(output_record),
565                        wrbuf_cstr(output_record));
566                 printf("output_expect_record len=%ld %s\n",
567                        (long) strlen(opacxml_rec),
568                        opacxml_rec);
569             }
570             wrbuf_destroy(output_record);
571         }
572         yaz_marc_destroy(mt);
573     }
574     nmem_destroy(nmem);
575 }
576 
tst_convert4(void)577 static void tst_convert4(void)
578 {
579     NMEM nmem = nmem_create();
580     int ret;
581 
582     const char *opacxml_rec =
583         "<opacRecord>\n"
584         "  <bibliographicRecord>\n"
585         "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
586         "  <leader>00077nam a22000498a 4500</leader>\n"
587         "  <controlfield tag=\"001\">   11224466 </controlfield>\n"
588         "  <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
589         "    <subfield code=\"a\">k" "\xc3" "\xb8" /* oslash in UTF_8 */
590         "benhavn</subfield>\n"
591         "  </datafield>\n"
592         "</record>\n"
593         "  </bibliographicRecord>\n"
594         "  <holdings>\n"
595         "   <holding>\n"
596         "    <shelvingLocation>Sprague Library hidden basement</shelvingLocation>\n"
597         "    <callNumber>E98.L7L44 1976 </callNumber>\n"
598         "    <volumes/>\n"
599         "   </holding>\n"
600         "  </holdings>\n"
601         " </opacRecord>\n"
602         ;
603 
604     Z_OPACRecord *opac = 0;
605     yaz_marc_t mt =  yaz_marc_create();
606     ret = yaz_xml_to_opac(mt, opacxml_rec, strlen(opacxml_rec),
607                           &opac, 0 /* iconv */, nmem, 0);
608     YAZ_CHECK(ret);
609     YAZ_CHECK(opac);
610     yaz_marc_destroy(mt);
611     nmem_destroy(nmem);
612 }
613 
614 #endif
615 
main(int argc,char ** argv)616 int main(int argc, char **argv)
617 {
618     YAZ_CHECK_INIT(argc, argv);
619     yaz_log_xml_errors(0, 0 /* disable log */);
620 #if YAZ_HAVE_XML2
621     tst_configure();
622 #endif
623 #if YAZ_HAVE_XSLT
624     tst_convert1();
625     tst_convert2();
626     tst_convert3();
627     tst_convert4();
628 #endif
629     YAZ_CHECK_TERM;
630 }
631 
632 /*
633  * Local variables:
634  * c-basic-offset: 4
635  * c-file-style: "Stroustrup"
636  * indent-tabs-mode: nil
637  * End:
638  * vim: shiftwidth=4 tabstop=8 expandtab
639  */
640 
641