1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
9 #include <yaz/record_conv.h>
11 #include <yaz/wrbuf.h>
14 #include <yaz/proto.h>
15 #include <yaz/prt-ext.h>
16 #include <yaz/oid_db.h>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
23 #include <libxslt/xslt.h>
26 yaz_record_conv_t conv_configure(const char *xmlstring, WRBUF w)
28 xmlDocPtr doc = xmlParseMemory(xmlstring, strlen(xmlstring));
31 wrbuf_printf(w, "xmlParseMemory");
36 xmlNodePtr ptr = xmlDocGetRootElement(doc);
37 yaz_record_conv_t p = yaz_record_conv_create();
41 const char *srcdir = getenv("srcdir");
43 yaz_record_conv_set_path(p, srcdir);
47 wrbuf_printf(w, "xmlDocGetRootElement");
48 yaz_record_conv_destroy(p);
53 wrbuf_printf(w, "yaz_record_conv_create");
59 int r = yaz_record_conv_configure(p, ptr);
63 wrbuf_puts(w, yaz_record_conv_get_error(p));
64 yaz_record_conv_destroy(p);
73 int conv_configure_test(const char *xmlstring, const char *expect_error,
74 yaz_record_conv_t *pt)
76 WRBUF w = wrbuf_alloc();
79 yaz_record_conv_t p = conv_configure(xmlstring, w);
83 if (expect_error && !strcmp(wrbuf_cstr(w), expect_error))
88 printf("%s\n", wrbuf_cstr(w));
103 yaz_record_conv_destroy(p);
109 static void tst_configure(void)
114 YAZ_CHECK(conv_configure_test("<bad", "xmlParseMemory", 0));
117 YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
119 "Element <backend>: expected <marc> or "
120 "<xslt> element, got <bad>", 0));
123 YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
124 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
126 " inputcharset=\"marc-8\""
127 " outputcharset=\"marc-8\""
130 "Element <marc>: attribute 'inputformat' "
132 YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
135 "Element <xslt>: attribute 'stylesheet' "
137 YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
139 " inputcharset=\"utf-8\""
140 " outputcharset=\"marc-8\""
141 " inputformat=\"xml\""
142 " outputformat=\"marc\""
144 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
148 YAZ_CHECK(conv_configure_test("<backend syntax='usmarc' name='F'>"
149 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
152 " YAZ compiled without XSLT support", 0));
156 static int conv_convert_test(yaz_record_conv_t p,
157 const char *input_record,
158 const char *output_expect_record)
167 WRBUF output_record = wrbuf_alloc();
168 int r = yaz_record_conv_record(p, input_record, strlen(input_record),
172 if (output_expect_record)
174 printf("yaz_record_conv error=%s\n",
175 yaz_record_conv_get_error(p));
183 if (!output_expect_record)
187 else if (strcmp(output_expect_record, wrbuf_cstr(output_record)))
190 printf("got-output_record len=%ld: %s\n",
191 (long) wrbuf_len(output_record),
192 wrbuf_cstr(output_record));
193 printf("output_expect_record len=%ld %s\n",
194 (long) strlen(output_expect_record),
195 output_expect_record);
202 wrbuf_destroy(output_record);
207 static int conv_convert_test_iter(yaz_record_conv_t p,
208 const char *input_record,
209 const char *output_expect_record,
214 for (i = 0; i < num_iter; i++)
216 ret = conv_convert_test(p, input_record, output_expect_record);
223 static void tst_convert1(void)
225 yaz_record_conv_t p = 0;
226 const char *marcxml_rec =
227 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
228 " <leader>00080nam a22000498a 4500</leader>\n"
229 " <controlfield tag=\"001\"> 11224466 </controlfield>\n"
230 " <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
231 " <subfield code=\"a\"> 11224466 </subfield>\n"
234 const char *tmarcxml_rec =
235 "<r xmlns=\"http://www.indexdata.com/MARC21/turboxml\">\n"
236 " <l>00080nam a22000498a 4500</l>\n"
237 " <c001> 11224466 </c001>\n"
238 " <d010 i1=\" \" i2=\" \">\n"
239 " <sa> 11224466 </sa>\n"
242 const char *iso2709_rec =
243 "\x30\x30\x30\x38\x30\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
244 "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
245 "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x37\x30\x30\x30\x31\x33"
246 "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
247 "\x1F\x61\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x1D";
249 YAZ_CHECK(conv_configure_test("<backend>"
251 " inputcharset=\"utf-8\""
252 " outputcharset=\"marc-8\""
253 " inputformat=\"xml\""
254 " outputformat=\"marc\""
258 YAZ_CHECK(conv_convert_test(p, marcxml_rec, iso2709_rec));
259 YAZ_CHECK(conv_convert_test(p, tmarcxml_rec, iso2709_rec));
260 yaz_record_conv_destroy(p);
262 YAZ_CHECK(conv_configure_test("<backend>"
264 " outputcharset=\"utf-8\""
265 " inputcharset=\"marc-8\""
266 " outputformat=\"marcxml\""
267 " inputformat=\"marc\""
271 YAZ_CHECK(conv_convert_test(p, iso2709_rec, marcxml_rec));
272 yaz_record_conv_destroy(p);
275 YAZ_CHECK(conv_configure_test("<backend>"
276 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
277 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
279 " inputcharset=\"utf-8\""
280 " outputcharset=\"marc-8\""
281 " inputformat=\"xml\""
282 " outputformat=\"marc\""
285 " outputcharset=\"utf-8\""
286 " inputcharset=\"marc-8\""
287 " outputformat=\"marcxml\""
288 " inputformat=\"marc\""
292 YAZ_CHECK(conv_convert_test(p, marcxml_rec, marcxml_rec));
293 yaz_record_conv_destroy(p);
296 YAZ_CHECK(conv_configure_test("<backend>"
297 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
298 "<xslt stylesheet=\"test_record_conv.xsl\"/>"
300 " outputcharset=\"marc-8\""
301 " inputformat=\"xml\""
302 " outputformat=\"marc\""
305 " inputcharset=\"marc-8\""
306 " outputformat=\"marcxml\""
307 " inputformat=\"marc\""
311 YAZ_CHECK(conv_convert_test(p, marcxml_rec, marcxml_rec));
312 yaz_record_conv_destroy(p);
315 static void tst_convert2(void)
317 yaz_record_conv_t p = 0;
318 const char *marcxml_rec =
319 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
320 " <leader>00080nam a22000498a 4500</leader>\n"
321 " <controlfield tag=\"001\"> 11224466 </controlfield>\n"
322 " <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
323 " <subfield code=\"a\">københavn</subfield>\n"
326 const char *iso2709_rec =
327 "\x30\x30\x30\x37\x37\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
328 "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
329 "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x34\x30\x30\x30\x31\x33"
330 "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
331 "\x1F\x61\x6b\xb2\x62\x65\x6e\x68\x61\x76\x6e\x1E\x1D";
333 YAZ_CHECK(conv_configure_test("<backend>"
335 " inputcharset=\"utf-8\""
336 " outputcharset=\"marc-8\""
337 " inputformat=\"xml\""
338 " outputformat=\"marc\""
342 YAZ_CHECK(conv_convert_test_iter(p, marcxml_rec, iso2709_rec, 100));
343 yaz_record_conv_destroy(p);
346 static void tst_convert3(void)
348 NMEM nmem = nmem_create();
350 yaz_record_conv_t p = 0;
352 const char *iso2709_rec =
353 "\x30\x30\x30\x37\x37\x6E\x61\x6D\x20\x61\x32\x32\x30\x30\x30\x34"
354 "\x39\x38\x61\x20\x34\x35\x30\x30\x30\x30\x31\x30\x30\x31\x33\x30"
355 "\x30\x30\x30\x30\x30\x31\x30\x30\x30\x31\x34\x30\x30\x30\x31\x33"
356 "\x1E\x20\x20\x20\x31\x31\x32\x32\x34\x34\x36\x36\x20\x1E\x20\x20"
357 "\x1F\x61\x6b\xb2\x62\x65\x6e\x68\x61\x76\x6e\x1E\x1D";
359 const char *opacxml_rec =
361 " <bibliographicRecord>\n"
362 "<record xmlns=\"http://www.loc.gov/MARC21/slim\">\n"
363 " <leader>00077nam a22000498a 4500</leader>\n"
364 " <controlfield tag=\"001\"> 11224466 </controlfield>\n"
365 " <datafield tag=\"010\" ind1=\" \" ind2=\" \">\n"
366 " <subfield code=\"a\">k" "\xc3" "\xb8" /* oslash in UTF_8 */
367 "benhavn</subfield>\n"
370 " </bibliographicRecord>\n"
373 " <typeOfRecord>u</typeOfRecord>\n"
374 " <encodingLevel>U</encodingLevel>\n"
375 " <receiptAcqStatus>0</receiptAcqStatus>\n"
376 " <dateOfReport>000000</dateOfReport>\n"
377 " <nucCode>s-FM/GC</nucCode>\n"
378 " <localLocation>Main or Science/Business Reading Rms - STORED OFFSITE</localLocation>\n"
379 " <callNumber>MLCM 89/00602 (N)</callNumber>\n"
380 " <shelvingData>FT MEADE</shelvingData>\n"
381 " <copyNumber>Copy 1</copyNumber>\n"
384 " <enumeration>1</enumeration>\n"
385 " <chronology>2</chronology>\n"
386 " <enumAndChron>3</enumAndChron>\n"
389 " <enumeration>1</enumeration>\n"
390 " <chronology>2</chronology>\n"
391 " <enumAndChron>3</enumAndChron>\n"
396 " <availableNow value=\"1\"/>\n"
397 " <availabilityDate>20130129</availabilityDate>\n"
398 " <itemId>1226176</itemId>\n"
399 " <renewable value=\"0\"/>\n"
400 " <onHold value=\"0\"/>\n"
407 Z_OPACRecord *z_opac = nmem_malloc(nmem, sizeof(*z_opac));
408 Z_HoldingsAndCircData *h;
411 z_opac->bibliographicRecord =
412 z_ext_record_oid_nmem(nmem, yaz_oid_recsyn_usmarc,
413 iso2709_rec, strlen(iso2709_rec));
414 z_opac->num_holdingsData = 1;
415 z_opac->holdingsData = (Z_HoldingsRecord **)
416 nmem_malloc(nmem, sizeof(Z_HoldingsRecord *) * 1);
417 z_opac->holdingsData[0] = (Z_HoldingsRecord *)
418 nmem_malloc(nmem, sizeof(Z_HoldingsRecord));
419 z_opac->holdingsData[0]->which = Z_HoldingsRecord_holdingsAndCirc;
420 h = z_opac->holdingsData[0]->u.holdingsAndCirc = (Z_HoldingsAndCircData *)
421 nmem_malloc(nmem, sizeof(*h));
422 h->typeOfRecord = nmem_strdup(nmem, "u");
423 h->encodingLevel = nmem_strdup(nmem, "U");
425 h->receiptAcqStatus = nmem_strdup(nmem, "0");
426 h->generalRetention = 0;
428 h->dateOfReport = nmem_strdup(nmem, "000000");
429 h->nucCode = nmem_strdup(nmem, "s-FM/GC");
430 h->localLocation = nmem_strdup(nmem,
431 "Main or Science/Business Reading "
432 "Rms - STORED OFFSITE");
433 h->shelvingLocation = 0;
434 h->callNumber = nmem_strdup(nmem, "MLCM 89/00602 (N)");
435 h->shelvingData = nmem_strdup(nmem, "FT MEADE");
436 h->copyNumber = nmem_strdup(nmem, "Copy 1");
438 h->reproductionNote = 0;
439 h->termsUseRepro = 0;
444 h->volumes = (Z_Volume **)
445 nmem_malloc(nmem, 2 * sizeof(Z_Volume *));
447 h->volumes[0] = (Z_Volume *)
448 nmem_malloc(nmem, sizeof(Z_Volume));
449 h->volumes[1] = h->volumes[0];
451 h->volumes[0]->enumeration = nmem_strdup(nmem, "1");
452 h->volumes[0]->chronology = nmem_strdup(nmem, "2");
453 h->volumes[0]->enumAndChron = nmem_strdup(nmem, "3");
455 h->num_circulationData = 1;
456 h->circulationData = (Z_CircRecord **)
457 nmem_malloc(nmem, 1 * sizeof(Z_CircRecord *));
458 circ = h->circulationData[0] = (Z_CircRecord *)
459 nmem_malloc(nmem, sizeof(Z_CircRecord));
460 circ->availableNow = nmem_booldup(nmem, 1);
461 circ->availablityDate = nmem_strdup(nmem, "20130129");
462 circ->availableThru = 0;
463 circ->restrictions = 0;
464 circ->itemId = nmem_strdup(nmem, "1226176");
465 circ->renewable = nmem_booldup(nmem, 0);
466 circ->onHold = nmem_booldup(nmem, 0);
467 circ->enumAndChron = 0;
469 circ->temporaryLocation = 0;
471 YAZ_CHECK(conv_configure_test("<backend>"
473 " inputcharset=\"marc-8\""
474 " outputcharset=\"utf-8\""
475 " inputformat=\"marc\""
476 " outputformat=\"marcxml\""
483 WRBUF output_record = wrbuf_alloc();
484 ret = yaz_record_conv_opac_record(p, z_opac, output_record);
488 ret = strcmp(wrbuf_cstr(output_record), opacxml_rec);
492 printf("got-output_record len=%ld: %s\n",
493 (long) wrbuf_len(output_record),
494 wrbuf_cstr(output_record));
495 printf("output_expect_record len=%ld %s\n",
496 (long) strlen(opacxml_rec),
500 yaz_record_conv_destroy(p);
501 wrbuf_destroy(output_record);
504 Z_OPACRecord *opac = 0;
505 yaz_marc_t mt = yaz_marc_create();
506 ret = yaz_xml_to_opac(mt, opacxml_rec, strlen(opacxml_rec),
507 &opac, 0 /* iconv */, nmem, 0);
513 WRBUF output_record = wrbuf_alloc();
516 yaz_marc_xml(mt, YAZ_MARC_MARCXML);
517 yaz_opac_decode_wrbuf(mt, opac, output_record);
519 /* change MARC size to 00077 from 00078, due to
520 encoding of the aring (two bytes in UTF-8) */
521 p = strstr(wrbuf_buf(output_record), "00078");
526 ret = strcmp(wrbuf_cstr(output_record), opacxml_rec);
530 printf("got-output_record len=%ld: %s\n",
531 (long) wrbuf_len(output_record),
532 wrbuf_cstr(output_record));
533 printf("output_expect_record len=%ld %s\n",
534 (long) strlen(opacxml_rec),
537 wrbuf_destroy(output_record);
539 yaz_marc_destroy(mt);
546 int main(int argc, char **argv)
548 YAZ_CHECK_INIT(argc, argv);
549 yaz_log_xml_errors(0, 0 /* disable log */);
557 xsltCleanupGlobals();
568 * c-file-style: "Stroustrup"
569 * indent-tabs-mode: nil
571 * vim: shiftwidth=4 tabstop=8 expandtab