YAZ 5.35.1
marcdisp.c
Go to the documentation of this file.
1/* This file is part of the YAZ toolkit.
2 * Copyright (C) Index Data
3 * See the file LICENSE for details.
4 */
5
11#if HAVE_CONFIG_H
12#include <config.h>
13#endif
14
15#ifdef WIN32
16#include <windows.h>
17#endif
18
19#include <stdarg.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <yaz/marcdisp.h>
24#include <yaz/wrbuf.h>
25#include <yaz/yaz-util.h>
26#include <yaz/nmem_xml.h>
27#include <yaz/snprintf.h>
28
29#if YAZ_HAVE_XML2
30#include <libxml/parser.h>
31#include <libxml/tree.h>
32#endif
33
39
48
55
58 char *tag;
59 char *data;
60};
61
64 char *comment;
65};
66
78
84
101
103{
104 yaz_marc_t mt = (yaz_marc_t) xmalloc(sizeof(*mt));
106 mt->debug = 0;
107 mt->write_using_libxml2 = 0;
109 mt->m_wr = wrbuf_alloc();
110 mt->iconv_cd = 0;
111 mt->leader_spec = 0;
112 strcpy(mt->subfield_str, " $");
113 strcpy(mt->endline_str, "\n");
114
115 mt->nmem = nmem_create();
116 yaz_marc_reset(mt);
117 return mt;
118}
119
121{
122 if (!mt)
123 return ;
124 nmem_destroy(mt->nmem);
125 wrbuf_destroy(mt->m_wr);
126 xfree(mt->leader_spec);
127 xfree(mt);
128}
129
131{
132 return mt->nmem;
133}
134
136{
138}
139
140static int marc_exec_leader(const char *leader_spec, char *leader,
141 size_t size);
142#if YAZ_HAVE_XML2
143static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
144 const char *ns,
145 const char *format,
146 const char *type);
147#endif
148
150{
151 struct yaz_marc_node *n = (struct yaz_marc_node *)
152 nmem_malloc(mt->nmem, sizeof(*n));
153 n->next = 0;
154 *mt->nodes_pp = n;
155 mt->nodes_pp = &n->next;
156 return n;
157}
158
159#if YAZ_HAVE_XML2
160void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
161 const xmlNode *ptr_data)
162{
163 struct yaz_marc_node *n = yaz_marc_add_node(mt);
165 n->u.controlfield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
166 n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
167}
168
170 const xmlNode *ptr_data)
171{
172 struct yaz_marc_node *n = yaz_marc_add_node(mt);
174 n->u.controlfield.tag = tag;
175 n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
176}
177
178#endif
179
180
182{
183 struct yaz_marc_node *n = yaz_marc_add_node(mt);
185 n->u.comment = nmem_strdup(mt->nmem, comment);
186}
187
188void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...)
189{
190 va_list ap;
191 char buf[200];
192
193 va_start(ap, fmt);
194 yaz_vsnprintf(buf, sizeof(buf)-1, fmt, ap);
195 yaz_marc_add_comment(mt, buf);
196 va_end (ap);
197}
198
200{
201 return mt->debug;
202}
203
204void yaz_marc_add_leader(yaz_marc_t mt, const char *leader, size_t leader_len)
205{
206 struct yaz_marc_node *n = yaz_marc_add_node(mt);
208 n->u.leader = nmem_strdupn(mt->nmem, leader, leader_len);
209 marc_exec_leader(mt->leader_spec, n->u.leader, leader_len);
210}
211
212void yaz_marc_add_controlfield(yaz_marc_t mt, const char *tag,
213 const char *data, size_t data_len)
214{
215 struct yaz_marc_node *n = yaz_marc_add_node(mt);
217 n->u.controlfield.tag = nmem_strdup(mt->nmem, tag);
218 n->u.controlfield.data = nmem_strdupn(mt->nmem, data, data_len);
219 if (mt->debug)
220 {
221 size_t i;
222 char msg[80];
223
224 sprintf(msg, "controlfield:");
225 for (i = 0; i < 16 && i < data_len; i++)
226 sprintf(msg + strlen(msg), " %02X", data[i] & 0xff);
227 if (i < data_len)
228 sprintf(msg + strlen(msg), " ..");
229 yaz_marc_add_comment(mt, msg);
230 }
231}
232
233void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
234 const char *indicator, size_t indicator_len)
235{
236 struct yaz_marc_node *n = yaz_marc_add_node(mt);
238 n->u.datafield.tag = nmem_strdup(mt->nmem, tag);
240 nmem_strdupn(mt->nmem, indicator, indicator_len);
241 n->u.datafield.subfields = 0;
242
243 /* make subfield_pp the current (last one) */
245}
246
254 yaz_marc_t mt, WRBUF buffer,
255 const char *attribute_name, char *code_data, size_t code_len)
256{
257 /* TODO Map special codes to something possible for XML ELEMENT names */
258
259 int encode = 0;
260 size_t index = 0;
261 int success = 0;
262 for (index = 0; index < code_len; index++)
263 {
264 if (!((code_data[index] >= '0' && code_data[index] <= '9') ||
265 (code_data[index] >= 'a' && code_data[index] <= 'z') ||
266 (code_data[index] >= 'A' && code_data[index] <= 'Z')))
267 encode = 1;
268 }
269 /* Add as attribute */
270 if (encode && attribute_name)
271 wrbuf_printf(buffer, " %s=\"", attribute_name);
272
273 if (!encode || attribute_name)
274 wrbuf_iconv_write_cdata(buffer, mt->iconv_cd, code_data, code_len);
275 else
276 success = -1;
277
278 if (encode && attribute_name)
279 wrbuf_printf(buffer, "\""); /* return error if we couldn't handle it.*/
280 return success;
281}
282
283#if YAZ_HAVE_XML2
284void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
285 const char *indicator, size_t indicator_len)
286{
287 struct yaz_marc_node *n = yaz_marc_add_node(mt);
289 n->u.datafield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
290 n->u.datafield.indicator = nmem_strdup(mt->nmem, indicator);
291 n->u.datafield.subfields = 0;
292
293 /* make subfield_pp the current (last one) */
295}
296
297void yaz_marc_add_datafield_xml2(yaz_marc_t mt, char *tag_value, char *indicators)
298{
299 struct yaz_marc_node *n = yaz_marc_add_node(mt);
301 n->u.datafield.tag = tag_value;
302 n->u.datafield.indicator = indicators;
303 n->u.datafield.subfields = 0;
304
305 /* make subfield_pp the current (last one) */
307}
308
309void yaz_marc_datafield_set_indicators(struct yaz_marc_node *n, char *indicator)
310{
311 n->u.datafield.indicator = indicator;
312}
313
314#endif
315
317 const char *code_data, size_t code_data_len)
318{
319 if (mt->debug)
320 {
321 size_t i;
322 char msg[80];
323
324 sprintf(msg, "subfield:");
325 for (i = 0; i < 16 && i < code_data_len; i++)
326 sprintf(msg + strlen(msg), " %02X", code_data[i] & 0xff);
327 if (i < code_data_len)
328 sprintf(msg + strlen(msg), " ..");
329 yaz_marc_add_comment(mt, msg);
330 }
331
332 if (mt->subfield_pp)
333 {
334 struct yaz_marc_subfield *n = (struct yaz_marc_subfield *)
335 nmem_malloc(mt->nmem, sizeof(*n));
336 n->code_data = nmem_strdupn(mt->nmem, code_data, code_data_len);
337 n->next = 0;
338 /* mark subfield_pp to point to this one, so we append here next */
339 *mt->subfield_pp = n;
340 mt->subfield_pp = &n->next;
341 }
342}
343
344static void check_ascii(yaz_marc_t mt, char *leader, int offset,
345 int ch_default)
346{
347 if (leader[offset] < ' ' || leader[offset] > 127)
348 {
350 "Leader character at offset %d is non-ASCII. "
351 "Setting value to '%c'", offset, ch_default);
352 leader[offset] = ch_default;
353 }
354}
355
356void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
357 int *indicator_length,
358 int *identifier_length,
359 int *base_address,
360 int *length_data_entry,
361 int *length_starting,
362 int *length_implementation)
363{
364 char leader[24];
365
366 memcpy(leader, leader_c, 24);
367
368 check_ascii(mt, leader, 5, 'a');
369 check_ascii(mt, leader, 6, 'a');
370 check_ascii(mt, leader, 7, 'a');
371 check_ascii(mt, leader, 8, '#');
372 check_ascii(mt, leader, 9, '#');
373 if (!atoi_n_check(leader+10, 1, indicator_length) || *indicator_length == 0)
374 {
375 yaz_marc_cprintf(mt, "Indicator length at offset 10 should"
376 " hold a number 1-9. Assuming 2");
377 leader[10] = '2';
378 *indicator_length = 2;
379 }
380 if (!atoi_n_check(leader+11, 1, identifier_length) || *identifier_length == 0)
381 {
382 yaz_marc_cprintf(mt, "Identifier length at offset 11 should "
383 " hold a number 1-9. Assuming 2");
384 leader[11] = '2';
385 *identifier_length = 2;
386 }
387 if (!atoi_n_check(leader+12, 5, base_address))
388 {
389 yaz_marc_cprintf(mt, "Base address at offsets 12..16 should"
390 " hold a number. Assuming 0");
391 *base_address = 0;
392 }
393 check_ascii(mt, leader, 17, '#');
394 check_ascii(mt, leader, 18, '#');
395 check_ascii(mt, leader, 19, '#');
396 if (!atoi_n_check(leader+20, 1, length_data_entry) ||
397 *length_data_entry < 3)
398 {
399 yaz_marc_cprintf(mt, "Length data entry at offset 20 should"
400 " hold a number 3-9. Assuming 4");
401 *length_data_entry = 4;
402 leader[20] = '4';
403 }
404 if (!atoi_n_check(leader+21, 1, length_starting) || *length_starting < 4)
405 {
406 yaz_marc_cprintf(mt, "Length starting at offset 21 should"
407 " hold a number 4-9. Assuming 5");
408 *length_starting = 5;
409 leader[21] = '5';
410 }
411 if (!atoi_n_check(leader+22, 1, length_implementation))
412 {
413 yaz_marc_cprintf(mt, "Length implementation at offset 22 should"
414 " hold a number. Assuming 0");
415 *length_implementation = 0;
416 leader[22] = '0';
417 }
418 check_ascii(mt, leader, 23, '0');
419
420 if (mt->debug)
421 {
422 yaz_marc_cprintf(mt, "Indicator length %5d", *indicator_length);
423 yaz_marc_cprintf(mt, "Identifier length %5d", *identifier_length);
424 yaz_marc_cprintf(mt, "Base address %5d", *base_address);
425 yaz_marc_cprintf(mt, "Length data entry %5d", *length_data_entry);
426 yaz_marc_cprintf(mt, "Length starting %5d", *length_starting);
427 yaz_marc_cprintf(mt, "Length implementation %5d", *length_implementation);
428 }
429 yaz_marc_add_leader(mt, leader, 24);
430}
431
432void yaz_marc_subfield_str(yaz_marc_t mt, const char *s)
433{
434 strncpy(mt->subfield_str, s, sizeof(mt->subfield_str)-1);
435 mt->subfield_str[sizeof(mt->subfield_str)-1] = '\0';
436}
437
438void yaz_marc_endline_str(yaz_marc_t mt, const char *s)
439{
440 strncpy(mt->endline_str, s, sizeof(mt->endline_str)-1);
441 mt->endline_str[sizeof(mt->endline_str)-1] = '\0';
442}
443
444/* try to guess how many bytes the identifier really is! */
445static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
446{
447 if (mt->iconv_cd)
448 {
449 size_t i;
450 for (i = 1; i<5; i++)
451 {
452 char outbuf[12];
453 size_t outbytesleft = sizeof(outbuf);
454 char *outp = outbuf;
455 const char *inp = buf;
456
457 size_t inbytesleft = i;
458 size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
459 &outp, &outbytesleft);
460 yaz_iconv(mt->iconv_cd, 0, 0, &outp, &outbytesleft);
461 if (r != (size_t) (-1))
462 return i; /* got a complete sequence */
463 }
464 return 1; /* giving up */
465 }
466 else
467 {
468 int error = 0;
469 size_t no_read = 0;
470 (void) yaz_read_UTF8_char((const unsigned char *) buf, 4,
471 &no_read, &error);
472 if (error == 0 && no_read > 0)
473 return no_read;
474 }
475 return 1; /* we don't know */
476}
477
478size_t yaz_marc_sizeof_char(yaz_marc_t mt, const char *buf)
479{
480 return cdata_one_character(mt, buf);
481}
482
484{
485 nmem_reset(mt->nmem);
486 mt->nodes = 0;
487 mt->nodes_pp = &mt->nodes;
488 mt->subfield_pp = 0;
489}
490
492{
493 struct yaz_marc_node *n;
494 int identifier_length;
495 const char *leader = 0;
496
497 for (n = mt->nodes; n; n = n->next)
498 if (n->which == YAZ_MARC_LEADER)
499 {
500 leader = n->u.leader;
501 break;
502 }
503
504 if (!leader)
505 return -1;
506 if (!atoi_n_check(leader+11, 1, &identifier_length))
507 return -1;
508
509 for (n = mt->nodes; n; n = n->next)
510 {
511 switch(n->which)
512 {
513 case YAZ_MARC_COMMENT:
515 n->u.comment, strlen(n->u.comment));
516 wrbuf_puts(wr, "\n");
517 break;
518 default:
519 break;
520 }
521 }
522 return 0;
523}
524
525static size_t get_subfield_len(yaz_marc_t mt, const char *data,
526 int identifier_length)
527{
528 /* if identifier length is 2 (most MARCs) or less (probably an error),
529 the code is a single character .. However we've
530 seen multibyte codes, so see how big it really is */
531 if (identifier_length > 2)
532 return identifier_length - 1;
533 else
534 return cdata_one_character(mt, data);
535}
536
538{
539 struct yaz_marc_node *n;
540 int identifier_length;
541 const char *leader = 0;
542
543 for (n = mt->nodes; n; n = n->next)
544 if (n->which == YAZ_MARC_LEADER)
545 {
546 leader = n->u.leader;
547 break;
548 }
549
550 if (!leader)
551 return -1;
552 if (!atoi_n_check(leader+11, 1, &identifier_length))
553 return -1;
554
555 for (n = mt->nodes; n; n = n->next)
556 {
557 struct yaz_marc_subfield *s;
558 switch(n->which)
559 {
561 wrbuf_printf(wr, "%s %s", n->u.datafield.tag,
563 for (s = n->u.datafield.subfields; s; s = s->next)
564 {
565 size_t using_code_len = get_subfield_len(mt, s->code_data,
566 identifier_length);
567
568 wrbuf_puts (wr, mt->subfield_str);
570 using_code_len);
571 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
573 s->code_data + using_code_len);
574 marc_iconv_reset(mt, wr);
575 }
576 wrbuf_puts (wr, mt->endline_str);
577 break;
579 wrbuf_printf(wr, "%s", n->u.controlfield.tag);
580 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
582 marc_iconv_reset(mt, wr);
583 wrbuf_puts (wr, mt->endline_str);
584 break;
585 case YAZ_MARC_COMMENT:
586 wrbuf_puts(wr, "(");
588 n->u.comment, strlen(n->u.comment));
589 marc_iconv_reset(mt, wr);
590 wrbuf_puts(wr, ")\n");
591 break;
592 case YAZ_MARC_LEADER:
593 wrbuf_printf(wr, "%s\n", n->u.leader);
594 }
595 }
596 wrbuf_puts(wr, "\n");
597 return 0;
598}
599
601{
603 {
604 switch(mt->output_format)
605 {
606 case YAZ_MARC_MARCXML:
608 wrbuf_printf(wr, "</collection>\n");
609 break;
610 case YAZ_MARC_XCHANGE:
611 wrbuf_printf(wr, "</collection>\n");
612 break;
613 }
614 }
615 return 0;
616}
617
622
624{
625 switch(mt->output_format)
626 {
627 case YAZ_MARC_LINE:
628 return yaz_marc_write_line(mt, wr);
629 case YAZ_MARC_MARCXML:
630 return yaz_marc_write_marcxml(mt, wr);
632 return yaz_marc_write_turbomarc(mt, wr);
633 case YAZ_MARC_XCHANGE:
634 return yaz_marc_write_marcxchange(mt, wr, 0, 0); /* no format, type */
635 case YAZ_MARC_ISO2709:
636 return yaz_marc_write_iso2709(mt, wr);
637 case YAZ_MARC_CHECK:
638 return yaz_marc_write_check(mt, wr);
639 case YAZ_MARC_JSON:
640 return yaz_marc_write_json(mt, wr);
641 }
642 return -1;
643}
644
645static const char *record_name[2] = { "record", "r"};
646static const char *leader_name[2] = { "leader", "l"};
647static const char *controlfield_name[2] = { "controlfield", "c"};
648static const char *datafield_name[2] = { "datafield", "d"};
649static const char *indicator_name[2] = { "ind", "i"};
650static const char *subfield_name[2] = { "subfield", "s"};
651
663 const char *ns,
664 const char *format,
665 const char *type,
666 int turbo)
667{
668 struct yaz_marc_node *n;
669 int identifier_length;
670 const char *leader = 0;
671
672 for (n = mt->nodes; n; n = n->next)
673 if (n->which == YAZ_MARC_LEADER)
674 {
675 leader = n->u.leader;
676 break;
677 }
678
679 if (!leader)
680 return -1;
681 if (!atoi_n_check(leader+11, 1, &identifier_length))
682 return -1;
683
685 {
687 {
688 wrbuf_printf(wr, "<collection xmlns=\"%s\">\n", ns);
690 }
691 wrbuf_printf(wr, "<%s", record_name[turbo]);
692 }
693 else
694 {
695 wrbuf_printf(wr, "<%s xmlns=\"%s\"", record_name[turbo], ns);
696 }
697 if (format)
698 wrbuf_printf(wr, " format=\"%.80s\"", format);
699 if (type)
700 wrbuf_printf(wr, " type=\"%.80s\"", type);
701 wrbuf_printf(wr, ">\n");
702 for (n = mt->nodes; n; n = n->next)
703 {
704 struct yaz_marc_subfield *s;
705
706 switch(n->which)
707 {
709
710 wrbuf_printf(wr, " <%s", datafield_name[turbo]);
711 if (!turbo)
712 wrbuf_printf(wr, " tag=\"");
714 strlen(n->u.datafield.tag));
715 if (!turbo)
716 wrbuf_printf(wr, "\"");
717 if (n->u.datafield.indicator)
718 {
719 int i;
720 size_t off = 0;
721 for (i = 0; n->u.datafield.indicator[off]; i++)
722 {
723 size_t ilen =
725 wrbuf_printf(wr, " %s%d=\"", indicator_name[turbo], i+1);
727 n->u.datafield.indicator + off,
728 ilen);
729 off += ilen;
730 wrbuf_iconv_puts(wr, mt->iconv_cd, "\"");
731 }
732 }
733 wrbuf_printf(wr, ">\n");
734 for (s = n->u.datafield.subfields; s; s = s->next)
735 {
736 size_t using_code_len = get_subfield_len(mt, s->code_data,
737 identifier_length);
738 wrbuf_printf(wr, " <%s", subfield_name[turbo]);
739 if (!turbo)
740 {
741 wrbuf_printf(wr, " code=\"");
743 s->code_data, using_code_len);
744 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
745 }
746 else
747 {
748 element_name_append_attribute_value(mt, wr, "code", s->code_data, using_code_len);
749 wrbuf_puts(wr, ">");
750 }
752 s->code_data + using_code_len,
753 strlen(s->code_data + using_code_len));
754 marc_iconv_reset(mt, wr);
755 wrbuf_printf(wr, "</%s", subfield_name[turbo]);
756 if (turbo)
757 element_name_append_attribute_value(mt, wr, 0, s->code_data, using_code_len);
758 wrbuf_puts(wr, ">\n");
759 }
760 wrbuf_printf(wr, " </%s", datafield_name[turbo]);
761 /* TODO Not CDATA */
762 if (turbo)
764 strlen(n->u.datafield.tag));
765 wrbuf_printf(wr, ">\n");
766 break;
768 wrbuf_printf(wr, " <%s", controlfield_name[turbo]);
769 if (!turbo)
770 {
771 wrbuf_printf(wr, " tag=\"");
773 strlen(n->u.controlfield.tag));
774 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
775 }
776 else
777 {
778 /* TODO convert special */
780 strlen(n->u.controlfield.tag));
781 wrbuf_iconv_puts(wr, mt->iconv_cd, ">");
782 }
785 strlen(n->u.controlfield.data));
786 marc_iconv_reset(mt, wr);
787 wrbuf_printf(wr, "</%s", controlfield_name[turbo]);
788 /* TODO convert special */
789 if (turbo)
791 strlen(n->u.controlfield.tag));
792 wrbuf_puts(wr, ">\n");
793 break;
794 case YAZ_MARC_COMMENT:
795 wrbuf_printf(wr, "<!-- ");
796 wrbuf_puts(wr, n->u.comment);
797 wrbuf_printf(wr, " -->\n");
798 break;
799 case YAZ_MARC_LEADER:
800 wrbuf_printf(wr, " <%s>", leader_name[turbo]);
802 0 , /* no charset conversion for leader */
803 n->u.leader, strlen(n->u.leader));
804 wrbuf_printf(wr, "</%s>\n", leader_name[turbo]);
805 }
806 }
807 wrbuf_printf(wr, "</%s>\n", record_name[turbo]);
808 return 0;
809}
810
812 const char *ns,
813 const char *format,
814 const char *type,
815 int turbo)
816{
817 if (mt->write_using_libxml2)
818 {
819#if YAZ_HAVE_XML2
820 int ret;
821 xmlNode *root_ptr;
822
823 if (!turbo)
824 ret = yaz_marc_write_xml(mt, &root_ptr, ns, format, type);
825 else
826 ret = yaz_marc_write_xml_turbo_xml(mt, &root_ptr, ns, format, type);
827 if (ret == 0)
828 {
829 xmlChar *buf_out;
830 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
831 int len_out;
832
833 xmlDocSetRootElement(doc, root_ptr);
834 xmlDocDumpMemory(doc, &buf_out, &len_out);
835
836 wrbuf_write(wr, (const char *) buf_out, len_out);
837 wrbuf_puts(wr, "");
838 xmlFree(buf_out);
839 xmlFreeDoc(doc);
840 }
841 return ret;
842#else
843 return -1;
844#endif
845 }
846 else
847 return yaz_marc_write_marcxml_wrbuf(mt, wr, ns, format, type, turbo);
848}
849
851{
852 /* set leader 09 to 'a' for UNICODE */
853 /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
854 if (!mt->leader_spec)
855 yaz_marc_modify_leader(mt, 9, "a");
856 return yaz_marc_write_marcxml_ns(mt, wr,
857 "http://www.loc.gov/MARC21/slim",
858 0, 0, 0);
859}
860
862{
863 /* set leader 09 to 'a' for UNICODE */
864 /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
865 if (!mt->leader_spec)
866 yaz_marc_modify_leader(mt, 9, "a");
867 return yaz_marc_write_marcxml_ns(mt, wr,
868 "http://www.indexdata.com/turbomarc", 0, 0, 1);
869}
870
872 const char *format,
873 const char *type)
874{
875 return yaz_marc_write_marcxml_ns(mt, wr,
876 "info:lc/xmlns/marcxchange-v1",
877 0, 0, 0);
878}
879
880#if YAZ_HAVE_XML2
882 xmlNode *ptr, int turbo)
883{
884 if (n->u.datafield.indicator)
885 {
886 int i;
887 size_t off = 0;
888 for (i = 0; n->u.datafield.indicator[off]; i++)
889 {
890 size_t ilen =
892 char ind_val[10];
893 if (ilen < sizeof(ind_val) - 1)
894 {
895 char ind_str[12];
896 sprintf(ind_str, "%s%d", indicator_name[turbo], i+1);
897 memcpy(ind_val, n->u.datafield.indicator + off, ilen);
898 ind_val[ilen] = '\0';
899 xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
900 }
901 off += ilen;
902 }
903 }
904}
905
907 struct yaz_marc_node *n,
908 xmlNode *record_ptr,
909 xmlNsPtr ns_record, WRBUF wr_cdata,
910 int identifier_length)
911{
912 xmlNode *ptr;
913 struct yaz_marc_subfield *s;
915
916 /* TODO consider if safe */
917 char field[10];
918 field[0] = 'd';
919 strncpy(field + 1, n->u.datafield.tag, 3);
920 field[4] = '\0';
921 ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST field, 0);
922
923 write_xml_indicator(mt, n, ptr, 1);
924 for (s = n->u.datafield.subfields; s; s = s->next)
925 {
926 int not_written;
927 xmlNode *ptr_subfield;
928 size_t using_code_len = get_subfield_len(mt, s->code_data,
929 identifier_length);
930 wrbuf_rewind(wr_cdata);
931 wrbuf_iconv_puts2(wr_cdata, mt->iconv_cd, s->code_data + using_code_len, wrbuf_xml_strip);
932 marc_iconv_reset(mt, wr_cdata);
933
936 not_written = element_name_append_attribute_value(mt, subfield_name, 0, s->code_data, using_code_len) != 0;
937 ptr_subfield = xmlNewTextChild(ptr, ns_record,
938 BAD_CAST wrbuf_cstr(subfield_name),
939 BAD_CAST wrbuf_cstr(wr_cdata));
940 if (not_written)
941 {
942 /* Generate code attribute value and add */
943 wrbuf_rewind(wr_cdata);
944 wrbuf_iconv_write2(wr_cdata, mt->iconv_cd, s->code_data, using_code_len, wrbuf_xml_strip);
945 xmlNewProp(ptr_subfield, BAD_CAST "code", BAD_CAST wrbuf_cstr(wr_cdata));
946 }
947 }
949}
950
951static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
952 const char *ns,
953 const char *format,
954 const char *type)
955{
956 struct yaz_marc_node *n;
957 int identifier_length;
958 const char *leader = 0;
959 xmlNode *record_ptr;
960 xmlNsPtr ns_record;
961 WRBUF wr_cdata = 0;
962
963 for (n = mt->nodes; n; n = n->next)
964 if (n->which == YAZ_MARC_LEADER)
965 {
966 leader = n->u.leader;
967 break;
968 }
969
970 if (!leader)
971 return -1;
972 if (!atoi_n_check(leader+11, 1, &identifier_length))
973 return -1;
974
975 wr_cdata = wrbuf_alloc();
976
977 record_ptr = xmlNewNode(0, BAD_CAST "r");
978 *root_ptr = record_ptr;
979
980 ns_record = xmlNewNs(record_ptr, BAD_CAST ns, 0);
981 xmlSetNs(record_ptr, ns_record);
982
983 if (format)
984 xmlNewProp(record_ptr, BAD_CAST "format", BAD_CAST format);
985 if (type)
986 xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
987 for (n = mt->nodes; n; n = n->next)
988 {
989 xmlNode *ptr;
990
991 char field[10];
992 field[0] = 'c';
993 field[4] = '\0';
994
995 switch(n->which)
996 {
998 add_marc_datafield_turbo_xml(mt, n, record_ptr, ns_record, wr_cdata, identifier_length);
999 break;
1001 wrbuf_rewind(wr_cdata);
1003 marc_iconv_reset(mt, wr_cdata);
1004
1005 strncpy(field + 1, n->u.controlfield.tag, 3);
1006 ptr = xmlNewTextChild(record_ptr, ns_record,
1007 BAD_CAST field,
1008 BAD_CAST wrbuf_cstr(wr_cdata));
1009 break;
1010 case YAZ_MARC_COMMENT:
1011 ptr = xmlNewComment(BAD_CAST n->u.comment);
1012 xmlAddChild(record_ptr, ptr);
1013 break;
1014 case YAZ_MARC_LEADER:
1015 xmlNewTextChild(record_ptr, ns_record, BAD_CAST "l",
1016 BAD_CAST n->u.leader);
1017 break;
1018 }
1019 }
1020 wrbuf_destroy(wr_cdata);
1021 return 0;
1022}
1023
1024
1025int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
1026 const char *ns,
1027 const char *format,
1028 const char *type)
1029{
1030 struct yaz_marc_node *n;
1031 int identifier_length;
1032 const char *leader = 0;
1033 xmlNode *record_ptr;
1034 xmlNsPtr ns_record;
1035 WRBUF wr_cdata = 0;
1036
1037 for (n = mt->nodes; n; n = n->next)
1038 if (n->which == YAZ_MARC_LEADER)
1039 {
1040 leader = n->u.leader;
1041 break;
1042 }
1043
1044 if (!leader)
1045 return -1;
1046 if (!atoi_n_check(leader+11, 1, &identifier_length))
1047 return -1;
1048
1049 wr_cdata = wrbuf_alloc();
1050
1051 record_ptr = xmlNewNode(0, BAD_CAST "record");
1052 *root_ptr = record_ptr;
1053
1054 ns_record = xmlNewNs(record_ptr, BAD_CAST ns, 0);
1055 xmlSetNs(record_ptr, ns_record);
1056
1057 if (format)
1058 xmlNewProp(record_ptr, BAD_CAST "format", BAD_CAST format);
1059 if (type)
1060 xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
1061 for (n = mt->nodes; n; n = n->next)
1062 {
1063 struct yaz_marc_subfield *s;
1064 xmlNode *ptr;
1065
1066 switch(n->which)
1067 {
1068 case YAZ_MARC_DATAFIELD:
1069 ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST "datafield", 0);
1070 xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.datafield.tag);
1071 write_xml_indicator(mt, n, ptr, 0);
1072 for (s = n->u.datafield.subfields; s; s = s->next)
1073 {
1074 xmlNode *ptr_subfield;
1075 size_t using_code_len = get_subfield_len(mt, s->code_data,
1076 identifier_length);
1077 wrbuf_rewind(wr_cdata);
1078 wrbuf_iconv_puts2(wr_cdata, mt->iconv_cd,
1079 s->code_data + using_code_len, wrbuf_xml_strip);
1080 marc_iconv_reset(mt, wr_cdata);
1081 ptr_subfield = xmlNewTextChild(
1082 ptr, ns_record,
1083 BAD_CAST "subfield", BAD_CAST wrbuf_cstr(wr_cdata));
1084
1085 wrbuf_rewind(wr_cdata);
1086 wrbuf_iconv_write2(wr_cdata, mt->iconv_cd,
1087 s->code_data, using_code_len, wrbuf_xml_strip);
1088 xmlNewProp(ptr_subfield, BAD_CAST "code",
1089 BAD_CAST wrbuf_cstr(wr_cdata));
1090 }
1091 break;
1093 wrbuf_rewind(wr_cdata);
1095 marc_iconv_reset(mt, wr_cdata);
1096
1097 ptr = xmlNewTextChild(record_ptr, ns_record,
1098 BAD_CAST "controlfield",
1099 BAD_CAST wrbuf_cstr(wr_cdata));
1100
1101 xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag);
1102 break;
1103 case YAZ_MARC_COMMENT:
1104 ptr = xmlNewComment(BAD_CAST n->u.comment);
1105 xmlAddChild(record_ptr, ptr);
1106 break;
1107 case YAZ_MARC_LEADER:
1108 xmlNewTextChild(record_ptr, ns_record, BAD_CAST "leader",
1109 BAD_CAST n->u.leader);
1110 break;
1111 }
1112 }
1113 wrbuf_destroy(wr_cdata);
1114 return 0;
1115}
1116
1117#endif
1118
1120{
1121 struct yaz_marc_node *n, *cap_node = 0;
1122 int indicator_length;
1123 int identifier_length;
1124 int length_data_entry;
1125 int length_starting;
1126 int length_implementation;
1127 int data_offset = 0;
1128 const char *leader = 0;
1129 WRBUF wr_dir, wr_head, wr_data_tmp;
1130 int base_address;
1131
1132 for (n = mt->nodes; n; n = n->next)
1133 if (n->which == YAZ_MARC_LEADER)
1134 leader = n->u.leader;
1135
1136 if (!leader)
1137 return -1;
1138 if (!atoi_n_check(leader+10, 1, &indicator_length))
1139 return -1;
1140 if (!atoi_n_check(leader+11, 1, &identifier_length))
1141 return -1;
1142 if (!atoi_n_check(leader+20, 1, &length_data_entry))
1143 return -1;
1144 if (!atoi_n_check(leader+21, 1, &length_starting))
1145 return -1;
1146 if (!atoi_n_check(leader+22, 1, &length_implementation))
1147 return -1;
1148
1149 wr_data_tmp = wrbuf_alloc();
1150 wr_dir = wrbuf_alloc();
1151 for (n = mt->nodes; n; n = n->next)
1152 {
1153 int data_length = 0;
1154 const char *tag = 0;
1155 struct yaz_marc_subfield *s;
1156
1157 switch(n->which)
1158 {
1159 case YAZ_MARC_DATAFIELD:
1160 tag = n->u.datafield.tag;
1161 data_length += strlen(n->u.datafield.indicator);
1162 wrbuf_rewind(wr_data_tmp);
1163 for (s = n->u.datafield.subfields; s; s = s->next)
1164 {
1165 /* write dummy IDFS + content */
1166 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
1167 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, s->code_data);
1168 marc_iconv_reset(mt, wr_data_tmp);
1169 }
1170 /* write dummy FS (makes MARC-8 to become ASCII) */
1171 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
1172 marc_iconv_reset(mt, wr_data_tmp);
1173 data_length += wrbuf_len(wr_data_tmp);
1174 break;
1176 tag = n->u.controlfield.tag;
1177 wrbuf_rewind(wr_data_tmp);
1178 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd,
1179 n->u.controlfield.data);
1180 marc_iconv_reset(mt, wr_data_tmp);
1181 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');/* field sep */
1182 marc_iconv_reset(mt, wr_data_tmp);
1183 data_length += wrbuf_len(wr_data_tmp);
1184 break;
1185 case YAZ_MARC_COMMENT:
1186 break;
1187 case YAZ_MARC_LEADER:
1188 break;
1189 }
1190 if (data_length && tag)
1191 {
1192 if (wrbuf_len(wr_dir) + 40 + data_offset + data_length > 99999)
1193 {
1194 cap_node = n;
1195 break;
1196 }
1197 wrbuf_printf(wr_dir, "%3.3s", tag);
1198 wrbuf_printf(wr_dir, "%0*d", length_data_entry, data_length);
1199 wrbuf_printf(wr_dir, "%0*d", length_starting, data_offset);
1200 data_offset += data_length;
1201 }
1202 }
1203 /* mark end of directory */
1204 wrbuf_putc(wr_dir, ISO2709_FS);
1205
1206 /* base address of data (comes after leader+directory) */
1207 base_address = 24 + wrbuf_len(wr_dir);
1208
1209 wr_head = wrbuf_alloc();
1210
1211 /* write record length */
1212 wrbuf_printf(wr_head, "%05d", base_address + data_offset + 1);
1213 /* from "original" leader */
1214 wrbuf_write(wr_head, leader+5, 7);
1215 /* base address of data */
1216 wrbuf_printf(wr_head, "%05d", base_address);
1217 /* from "original" leader */
1218 wrbuf_write(wr_head, leader+17, 7);
1219
1220 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
1221 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
1222 wrbuf_destroy(wr_head);
1223 wrbuf_destroy(wr_dir);
1224 wrbuf_destroy(wr_data_tmp);
1225
1226 for (n = mt->nodes; n != cap_node; n = n->next)
1227 {
1228 struct yaz_marc_subfield *s;
1229
1230 switch(n->which)
1231 {
1232 case YAZ_MARC_DATAFIELD:
1234 for (s = n->u.datafield.subfields; s; s = s->next)
1235 {
1237 wrbuf_iconv_puts(wr, mt->iconv_cd, s->code_data);
1238 marc_iconv_reset(mt, wr);
1239 }
1241 break;
1244 marc_iconv_reset(mt, wr);
1246 break;
1247 case YAZ_MARC_COMMENT:
1248 break;
1249 case YAZ_MARC_LEADER:
1250 break;
1251 }
1252 }
1253 wrbuf_printf(wr, "%c", ISO2709_RS);
1254 return 0;
1255}
1256
1258{
1259 int identifier_length;
1260 struct yaz_marc_node *n;
1261 const char *leader = 0;
1262 int first = 1;
1263
1264 wrbuf_puts(w, "{\n");
1265 for (n = mt->nodes; n; n = n->next)
1266 if (n->which == YAZ_MARC_LEADER)
1267 leader = n->u.leader;
1268
1269 if (!leader)
1270 return -1;
1271
1272 if (!atoi_n_check(leader+11, 1, &identifier_length))
1273 return -1;
1274
1275 wrbuf_puts(w, " \"leader\": \"");
1277 wrbuf_puts(w, "\",\n");
1278 wrbuf_puts(w, " \"fields\": [");
1279
1280 for (n = mt->nodes; n; n = n->next)
1281 {
1282 struct yaz_marc_subfield *s;
1283 const char *sep = "";
1284 switch (n->which)
1285 {
1286 case YAZ_MARC_LEADER:
1287 case YAZ_MARC_COMMENT:
1288 break;
1290 if (first)
1291 first = 0;
1292 else
1293 wrbuf_puts(w, ",");
1294 wrbuf_puts(w, "\n {\n \"");
1296 wrbuf_puts(w, "\": \"");
1298 wrbuf_puts(w, "\"\n }");
1299 break;
1300 case YAZ_MARC_DATAFIELD:
1301 if (first)
1302 first = 0;
1303 else
1304 wrbuf_puts(w, ",");
1305
1306 wrbuf_puts(w, "\n {\n \"");
1308 wrbuf_puts(w, "\": {\n \"subfields\": [\n");
1309 for (s = n->u.datafield.subfields; s; s = s->next)
1310 {
1311 size_t using_code_len = get_subfield_len(mt, s->code_data,
1312 identifier_length);
1313 wrbuf_puts(w, sep);
1314 sep = ",\n";
1315 wrbuf_puts(w, " {\n \"");
1317 s->code_data, using_code_len);
1318 wrbuf_puts(w, "\": \"");
1320 s->code_data + using_code_len);
1321 wrbuf_puts(w, "\"\n }");
1322 }
1323 wrbuf_puts(w, "\n ]");
1324 if (n->u.datafield.indicator)
1325 {
1326 int i;
1327 size_t off = 0;
1328 for (i = 0; n->u.datafield.indicator[off]; i++)
1329 {
1330 size_t ilen =
1332 wrbuf_printf(w, ",\n \"ind%d\": \"", i + 1);
1333 wrbuf_json_write(w, &n->u.datafield.indicator[off], ilen);
1334 wrbuf_printf(w, "\"");
1335 off += ilen;
1336 }
1337 }
1338 wrbuf_puts(w, "\n }");
1339 wrbuf_puts(w, "\n }");
1340 break;
1341 }
1342 }
1343 if (first == 0) {
1344 wrbuf_puts(w, "\n ");
1345 }
1346 wrbuf_puts(w, "]\n");
1347 wrbuf_puts(w, "}\n");
1348 return 0;
1349}
1350
1351int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
1352{
1353 int s, r = yaz_marc_read_iso2709(mt, buf, bsize);
1354 if (r <= 0)
1355 return r;
1356 s = yaz_marc_write_mode(mt, wr); /* returns 0 for OK, -1 otherwise */
1357 if (s != 0)
1358 return -1; /* error */
1359 return r; /* OK, return length > 0 */
1360}
1361
1362int yaz_marc_decode_buf(yaz_marc_t mt, const char *buf, int bsize,
1363 const char **result, size_t *rsize)
1364{
1365 int r;
1366
1367 wrbuf_rewind(mt->m_wr);
1368 r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
1369 if (result)
1370 *result = wrbuf_cstr(mt->m_wr);
1371 if (rsize)
1372 *rsize = wrbuf_len(mt->m_wr);
1373 return r;
1374}
1375
1376void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
1377{
1378 mt->output_format = xmlmode;
1379}
1380
1381void yaz_marc_debug(yaz_marc_t mt, int level)
1382{
1383 if (mt)
1384 mt->debug = level;
1385}
1386
1388{
1389 mt->iconv_cd = cd;
1390}
1391
1393{
1394 return mt->iconv_cd;
1395}
1396
1397void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str)
1398{
1399 struct yaz_marc_node *n;
1400 char *leader = 0;
1401 for (n = mt->nodes; n; n = n->next)
1402 if (n->which == YAZ_MARC_LEADER)
1403 {
1404 leader = n->u.leader;
1405 memcpy(leader+off, str, strlen(str));
1406 break;
1407 }
1408}
1409
1410int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
1411{
1412 xfree(mt->leader_spec);
1413 mt->leader_spec = 0;
1414 if (leader_spec)
1415 {
1416 char dummy_leader[24];
1417 if (marc_exec_leader(leader_spec, dummy_leader, 24))
1418 return -1;
1419 mt->leader_spec = xstrdup(leader_spec);
1420 }
1421 return 0;
1422}
1423
1424static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
1425{
1426 const char *cp = leader_spec;
1427 while (cp)
1428 {
1429 char val[21];
1430 int pos;
1431 int no_read = 0, no = 0;
1432
1433 no = sscanf(cp, "%d=%20[^,]%n", &pos, val, &no_read);
1434 if (no < 2 || no_read < 3)
1435 return -1;
1436 if (pos < 0 || (size_t) pos >= size)
1437 return -1;
1438
1439 if (*val == '\'')
1440 {
1441 const char *vp = strchr(val+1, '\'');
1442 size_t len;
1443
1444 if (!vp)
1445 return -1;
1446 len = vp-val-1;
1447 if (len + pos > size)
1448 return -1;
1449 memcpy(leader + pos, val+1, len);
1450 }
1451 else if (*val >= '0' && *val <= '9')
1452 {
1453 int ch = atoi(val);
1454 leader[pos] = ch;
1455 }
1456 else
1457 return -1;
1458 cp += no_read;
1459 if (*cp != ',')
1460 break;
1461
1462 cp++;
1463 }
1464 return 0;
1465}
1466
1467int yaz_marc_decode_formatstr(const char *arg)
1468{
1469 int mode = -1;
1470 if (!strcmp(arg, "marc"))
1471 mode = YAZ_MARC_ISO2709;
1472 if (!strcmp(arg, "marcxml"))
1473 mode = YAZ_MARC_MARCXML;
1474 if (!strcmp(arg, "turbomarc"))
1475 mode = YAZ_MARC_TURBOMARC;
1476 if (!strcmp(arg, "marcxchange"))
1477 mode = YAZ_MARC_XCHANGE;
1478 if (!strcmp(arg, "line"))
1479 mode = YAZ_MARC_LINE;
1480 if (!strcmp(arg, "json"))
1481 mode = YAZ_MARC_JSON;
1482 return mode;
1483}
1484
1486{
1487 mt->write_using_libxml2 = enable;
1488}
1489
1490int yaz_marc_check_marc21_coding(const char *charset,
1491 const char *marc_buf, int sz)
1492{
1493 if (charset && (!yaz_matchstr(charset, "MARC8?") ||
1494 !yaz_matchstr(charset, "MARC8")) && marc_buf && sz > 25
1495 && marc_buf[9] == 'a')
1496 return 1;
1497 return 0;
1498}
1499
1500/*
1501 * Local variables:
1502 * c-basic-offset: 4
1503 * c-file-style: "Stroustrup"
1504 * indent-tabs-mode: nil
1505 * End:
1506 * vim: shiftwidth=4 tabstop=8 expandtab
1507 */
1508
int atoi_n_check(const char *buf, int size, int *val)
like atoi_n but checks for proper formatting
Definition atoin.c:32
enum l_file_type type
Definition log.c:47
int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize)
read ISO2709/MARC record from buffer
int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
sets leader spec (for modifying bytes in 24 byte leader)
Definition marcdisp.c:1410
int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
writes record in ISO2709 format
Definition marcdisp.c:1119
void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag, const xmlNode *ptr_data)
adds controlfield to MARC structure using xml Nodes
Definition marcdisp.c:160
static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr, const char *ns, const char *format, const char *type)
Definition marcdisp.c:951
static const char * subfield_name[2]
Definition marcdisp.c:650
void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt,...)
adds MARC annotation - printf interface
Definition marcdisp.c:188
int yaz_marc_check_marc21_coding(const char *charset, const char *marc_buf, int sz)
check if MARC21 is UTF-8 encoded
Definition marcdisp.c:1490
yaz_marc_t yaz_marc_create(void)
construct yaz_marc_t handle
Definition marcdisp.c:102
int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
writes record in line format
Definition marcdisp.c:537
static void check_ascii(yaz_marc_t mt, char *leader, int offset, int ch_default)
Definition marcdisp.c:344
size_t yaz_marc_sizeof_char(yaz_marc_t mt, const char *buf)
Definition marcdisp.c:478
void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
set iconv handle for character set conversion
Definition marcdisp.c:1387
static const char * controlfield_name[2]
Definition marcdisp.c:647
static const char * leader_name[2]
Definition marcdisp.c:646
void yaz_marc_add_leader(yaz_marc_t mt, const char *leader, size_t leader_len)
Definition marcdisp.c:204
void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
set XML mode YAZ_MARC_LINE, YAZ_MARCXML, YAZ_MARC_ISO2709 ..
Definition marcdisp.c:1376
void yaz_marc_add_subfield(yaz_marc_t mt, const char *code_data, size_t code_data_len)
adds subfield to MARC structure
Definition marcdisp.c:316
static struct yaz_marc_node * yaz_marc_add_node(yaz_marc_t mt)
Definition marcdisp.c:149
void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag, const char *indicator, size_t indicator_len)
adds datafield to MARC structure using xml Nodes
Definition marcdisp.c:284
void yaz_marc_write_using_libxml2(yaz_marc_t mt, int enable)
Enables or disables writing of MARC XML records using Libxml2.
Definition marcdisp.c:1485
NMEM yaz_marc_get_nmem(yaz_marc_t mt)
returns memory for MARC handle
Definition marcdisp.c:130
void yaz_marc_endline_str(yaz_marc_t mt, const char *s)
Definition marcdisp.c:438
int yaz_marc_get_debug(yaz_marc_t mt)
gets debug level for MARC system
Definition marcdisp.c:199
int yaz_marc_write_turbomarc(yaz_marc_t mt, WRBUF wr)
writes record in TurboMARC format
Definition marcdisp.c:861
void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag, const char *indicator, size_t indicator_len)
adds datafield to MARC structure using strings
Definition marcdisp.c:233
YAZ_MARC_NODE_TYPE
node types for yaz_marc_node
Definition marcdisp.c:42
@ YAZ_MARC_COMMENT
Definition marcdisp.c:45
@ YAZ_MARC_LEADER
Definition marcdisp.c:46
@ YAZ_MARC_DATAFIELD
Definition marcdisp.c:43
@ YAZ_MARC_CONTROLFIELD
Definition marcdisp.c:44
void yaz_marc_add_datafield_xml2(yaz_marc_t mt, char *tag_value, char *indicators)
adds datafield to MARC structure using xml Nodes
Definition marcdisp.c:297
void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str)
modifies part of the MARC leader
Definition marcdisp.c:1397
int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr, const char *ns, const char *format, const char *type)
writes MARC record as libxml2 tree
Definition marcdisp.c:1025
int yaz_marc_decode_formatstr(const char *arg)
Converts MARC format type to format type(YAZ_MARC_..)
Definition marcdisp.c:1467
int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
writes record in MARCXML format
Definition marcdisp.c:850
static void write_xml_indicator(yaz_marc_t mt, struct yaz_marc_node *n, xmlNode *ptr, int turbo)
Definition marcdisp.c:881
void yaz_marc_subfield_str(yaz_marc_t mt, const char *s)
Definition marcdisp.c:432
yaz_iconv_t yaz_marc_get_iconv(yaz_marc_t mt)
supply iconv handle for character set conversion
Definition marcdisp.c:1392
void yaz_marc_destroy(yaz_marc_t mt)
destroy yaz_marc_t handle
Definition marcdisp.c:120
int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr)
Definition marcdisp.c:491
static const char * record_name[2]
Definition marcdisp.c:645
static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr, const char *ns, const char *format, const char *type, int turbo)
common MARC XML/Xchange/turbomarc writer
Definition marcdisp.c:662
yaz_collection_state
Definition marcdisp.c:34
@ no_collection
Definition marcdisp.c:35
@ collection_first
Definition marcdisp.c:36
@ collection_second
Definition marcdisp.c:37
void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c, int *indicator_length, int *identifier_length, int *base_address, int *length_data_entry, int *length_starting, int *length_implementation)
sets leader, validates it, and returns important values
Definition marcdisp.c:356
static void marc_iconv_reset(yaz_marc_t mt, WRBUF wr)
Definition marcdisp.c:135
static void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n, xmlNode *record_ptr, xmlNsPtr ns_record, WRBUF wr_cdata, int identifier_length)
Definition marcdisp.c:906
void yaz_marc_add_controlfield_xml2(yaz_marc_t mt, char *tag, const xmlNode *ptr_data)
adds controlfield to MARC structure using xml Nodes for data
Definition marcdisp.c:169
int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
writes record in mode - given by yaz_marc_xml mode
Definition marcdisp.c:623
void yaz_marc_add_controlfield(yaz_marc_t mt, const char *tag, const char *data, size_t data_len)
adds controlfield to MARC structure
Definition marcdisp.c:212
void yaz_marc_add_comment(yaz_marc_t mt, char *comment)
adds MARC comment string
Definition marcdisp.c:181
static const char * datafield_name[2]
Definition marcdisp.c:648
void yaz_marc_reset(yaz_marc_t mt)
clears memory and MARC record
Definition marcdisp.c:483
int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr, const char *format, const char *type)
writes record in MarcXchange XML (ISO25577)
Definition marcdisp.c:871
int yaz_marc_write_json(yaz_marc_t mt, WRBUF w)
writes MARC record in JSON represenation
Definition marcdisp.c:1257
void yaz_marc_enable_collection(yaz_marc_t mt)
enables record collection output
Definition marcdisp.c:618
static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
Definition marcdisp.c:1424
int yaz_marc_write_trailer(yaz_marc_t mt, WRBUF wr)
flushes records
Definition marcdisp.c:600
int yaz_marc_decode_buf(yaz_marc_t mt, const char *buf, int bsize, const char **result, size_t *rsize)
decodes ISO2709 buffer using straight buffers
Definition marcdisp.c:1362
void yaz_marc_datafield_set_indicators(struct yaz_marc_node *n, char *indicator)
Definition marcdisp.c:309
static const char * indicator_name[2]
Definition marcdisp.c:649
void yaz_marc_debug(yaz_marc_t mt, int level)
set debug level
Definition marcdisp.c:1381
static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
Definition marcdisp.c:445
int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
decodes ISO2709/MARC buffer and stores result in WRBUF
Definition marcdisp.c:1351
static int element_name_append_attribute_value(yaz_marc_t mt, WRBUF buffer, const char *attribute_name, char *code_data, size_t code_len)
adds a attribute value to the element name if it is plain chars
Definition marcdisp.c:253
static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr, const char *ns, const char *format, const char *type, int turbo)
Definition marcdisp.c:811
static size_t get_subfield_len(yaz_marc_t mt, const char *data, int identifier_length)
Definition marcdisp.c:525
MARC conversion.
#define YAZ_MARC_MARCXML
Output format: MARCXML.
Definition marcdisp.h:70
#define ISO2709_FS
MARC control char: field separator (30 Dec, 1E Hex)
Definition marcdisp.h:148
#define YAZ_MARC_XCHANGE
Output format: MarcXchange (ISO25577)
Definition marcdisp.h:74
#define YAZ_MARC_ISO2709
Output format: ISO2709.
Definition marcdisp.h:72
#define YAZ_MARC_LINE
Output format: Line-format.
Definition marcdisp.h:64
#define YAZ_MARC_CHECK
Output format: check only (no marc output)
Definition marcdisp.h:76
#define YAZ_MARC_JSON
Output format: JSON.
Definition marcdisp.h:80
#define ISO2709_IDFS
MARC control char: identifier-field separator (31 Dec, 1F Hex)
Definition marcdisp.h:150
#define ISO2709_RS
MARC control char: record separator (29 Dec, 1D Hex)
Definition marcdisp.h:146
#define YAZ_MARC_TURBOMARC
Output format: Turbo MARC Index Data format (XML based)
Definition marcdisp.h:78
struct yaz_marc_t_ * yaz_marc_t
a yaz_marc_t handle (private content)
Definition marcdisp.h:47
int yaz_matchstr(const char *s1, const char *s2)
match strings - independent of case and '-'
Definition matchstr.c:42
void nmem_reset(NMEM n)
releases memory associaged with an NMEM handle
Definition nmem.c:129
NMEM nmem_create(void)
returns new NMEM handle
Definition nmem.c:181
void * nmem_malloc(NMEM n, size_t size)
allocates memory block on NMEM handle
Definition nmem.c:145
void nmem_destroy(NMEM n)
destroys NMEM handle and memory associated with it
Definition nmem.c:204
Header for Nibble Memory functions + Libxml2 specific stuff.
char * nmem_strdup(NMEM mem, const char *src)
allocates string on NMEM handle (similar strdup)
Definition nmemsdup.c:18
char * nmem_strdupn(NMEM mem, const char *src, size_t n)
allocates string of certain size on NMEM handle
Definition nmemsdup.c:33
char * nmem_text_node_cdata(const xmlNode *ptr_cdata, NMEM nmem)
copies TEXT Libxml2 node data to NMEM
Definition nmemsdup.c:145
size_t yaz_iconv(yaz_iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
just like iconv(3)
Definition siconv.c:146
void yaz_vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
Definition snprintf.c:17
Header for config file reading utilities.
string buffer
Definition wrbuf.h:43
a comment node
Definition marcdisp.c:63
represents a control field
Definition marcdisp.c:57
represents a data field
Definition marcdisp.c:50
struct yaz_marc_subfield * subfields
Definition marcdisp.c:53
MARC node.
Definition marcdisp.c:68
struct yaz_marc_datafield datafield
Definition marcdisp.c:71
struct yaz_marc_controlfield controlfield
Definition marcdisp.c:72
enum YAZ_MARC_NODE_TYPE which
Definition marcdisp.c:69
struct yaz_marc_node * next
Definition marcdisp.c:76
char * comment
Definition marcdisp.c:73
union yaz_marc_node::@5 u
char * leader
Definition marcdisp.c:74
represents a subfield
Definition marcdisp.c:80
struct yaz_marc_subfield * next
Definition marcdisp.c:82
the internals of a yaz_marc_t handle
Definition marcdisp.c:86
char endline_str[8]
Definition marcdisp.c:95
enum yaz_collection_state enable_collection
Definition marcdisp.c:92
struct yaz_marc_subfield ** subfield_pp
Definition marcdisp.c:99
NMEM nmem
Definition marcdisp.c:88
char * leader_spec
Definition marcdisp.c:96
struct yaz_marc_node ** nodes_pp
Definition marcdisp.c:98
int write_using_libxml2
Definition marcdisp.c:91
WRBUF m_wr
Definition marcdisp.c:87
int output_format
Definition marcdisp.c:89
char subfield_str[8]
Definition marcdisp.c:94
struct yaz_marc_node * nodes
Definition marcdisp.c:97
yaz_iconv_t iconv_cd
Definition marcdisp.c:93
unsigned long yaz_read_UTF8_char(const unsigned char *inp, size_t inbytesleft, size_t *no_read, int *error)
Definition utf8.c:41
void wrbuf_destroy(WRBUF b)
destroy WRBUF and its buffer
Definition wrbuf.c:38
void wrbuf_iconv_reset(WRBUF b, yaz_iconv_t cd)
iconv reset(flush) to WRBUF
Definition wrbuf.c:286
const char * wrbuf_cstr(WRBUF b)
returns WRBUF content as C-string
Definition wrbuf.c:299
void wrbuf_rewind(WRBUF b)
empty WRBUF content (length of buffer set to 0)
Definition wrbuf.c:47
WRBUF wrbuf_alloc(void)
construct WRBUF
Definition wrbuf.c:25
void wrbuf_iconv_putchar(WRBUF b, yaz_iconv_t cd, int ch)
iconv converts character and appends to WRBUF
Definition wrbuf.c:258
void wrbuf_json_puts(WRBUF b, const char *str)
writes JSON text to WRBUF with escaping
Definition wrbuf.c:372
void wrbuf_printf(WRBUF b, const char *fmt,...)
writes printf result to WRBUF
Definition wrbuf.c:189
void wrbuf_xml_strip(WRBUF b, const char *cp, size_t size)
writes buffer of certain size to WRBUF and strips non-allowed XML chars
Definition wrbuf.c:178
int wrbuf_iconv_write2(WRBUF b, yaz_iconv_t cd, const char *buf, size_t size, void(*wfunc)(WRBUF, const char *, size_t))
General writer of string using iconv and cdata.
Definition wrbuf.c:208
void wrbuf_iconv_write(WRBUF b, yaz_iconv_t cd, const char *buf, size_t size)
Converts buffer using iconv and appends to WRBUF.
Definition wrbuf.c:248
void wrbuf_iconv_json_write(WRBUF b, yaz_iconv_t cd, const char *buf, size_t size)
Definition wrbuf.c:275
void wrbuf_iconv_puts(WRBUF b, yaz_iconv_t cd, const char *strz)
iconv converts C-string and appends to WRBUF
Definition wrbuf.c:253
void wrbuf_puts(WRBUF b, const char *buf)
appends C-string to WRBUF
Definition wrbuf.c:89
int wrbuf_iconv_puts2(WRBUF b, yaz_iconv_t cd, const char *buf, void(*wfunc)(WRBUF, const char *, size_t))
General writer of string using iconv and cdata.
Definition wrbuf.c:202
void wrbuf_iconv_json_puts(WRBUF b, yaz_iconv_t cd, const char *strz)
Definition wrbuf.c:281
void wrbuf_write(WRBUF b, const char *buf, size_t size)
append constant size buffer to WRBUF
Definition wrbuf.c:68
void wrbuf_json_write(WRBUF b, const char *cp, size_t sz)
writes JSON text to WRBUF with escaping
Definition wrbuf.c:337
void wrbuf_iconv_write_cdata(WRBUF b, yaz_iconv_t cd, const char *buf, size_t size)
Converts buffer using iconv and appends to WRBUF as XML CDATA.
Definition wrbuf.c:265
Header for WRBUF (growing buffer)
#define wrbuf_putc(b, c)
Definition wrbuf.h:287
#define wrbuf_buf(b)
Definition wrbuf.h:270
#define wrbuf_len(b)
Definition wrbuf.h:269
#define xstrdup(s)
utility macro which calls xstrdup_f
Definition xmalloc.h:55
#define xfree(x)
utility macro which calls xfree_f
Definition xmalloc.h:53
#define xmalloc(x)
utility macro which calls malloc_f
Definition xmalloc.h:49
Header for common YAZ utilities.