00001
00002
00003
00004
00005
00011 #if HAVE_CONFIG_H
00012 #include <config.h>
00013 #endif
00014
00015 #ifdef WIN32
00016 #include <windows.h>
00017 #endif
00018
00019 #include <stdarg.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <ctype.h>
00024 #include <yaz/marcdisp.h>
00025 #include <yaz/wrbuf.h>
00026 #include <yaz/yaz-util.h>
00027 #include <yaz/nmem_xml.h>
00028 #include <yaz/snprintf.h>
00029
00030 #if YAZ_HAVE_XML2
00031 #include <libxml/parser.h>
00032 #include <libxml/tree.h>
00033 #endif
00034
00035 enum yaz_collection_state {
00036 no_collection,
00037 collection_first,
00038 collection_second
00039 };
00040
00042 enum YAZ_MARC_NODE_TYPE
00043 {
00044 YAZ_MARC_DATAFIELD,
00045 YAZ_MARC_CONTROLFIELD,
00046 YAZ_MARC_COMMENT,
00047 YAZ_MARC_LEADER
00048 };
00049
00051 struct yaz_marc_datafield {
00052 char *tag;
00053 char *indicator;
00054 struct yaz_marc_subfield *subfields;
00055 };
00056
00058 struct yaz_marc_controlfield {
00059 char *tag;
00060 char *data;
00061 };
00062
00064 struct yaz_marc_comment {
00065 char *comment;
00066 };
00067
00069 struct yaz_marc_node {
00070 enum YAZ_MARC_NODE_TYPE which;
00071 union {
00072 struct yaz_marc_datafield datafield;
00073 struct yaz_marc_controlfield controlfield;
00074 char *comment;
00075 char *leader;
00076 } u;
00077 struct yaz_marc_node *next;
00078 };
00079
00081 struct yaz_marc_subfield {
00082 char *code_data;
00083 struct yaz_marc_subfield *next;
00084 };
00085
00087 struct yaz_marc_t_ {
00088 WRBUF m_wr;
00089 NMEM nmem;
00090 int output_format;
00091 int debug;
00092 int write_using_libxml2;
00093 enum yaz_collection_state enable_collection;
00094 yaz_iconv_t iconv_cd;
00095 char subfield_str[8];
00096 char endline_str[8];
00097 char *leader_spec;
00098 struct yaz_marc_node *nodes;
00099 struct yaz_marc_node **nodes_pp;
00100 struct yaz_marc_subfield **subfield_pp;
00101 };
00102
00103 yaz_marc_t yaz_marc_create(void)
00104 {
00105 yaz_marc_t mt = (yaz_marc_t) xmalloc(sizeof(*mt));
00106 mt->output_format = YAZ_MARC_LINE;
00107 mt->debug = 0;
00108 mt->write_using_libxml2 = 0;
00109 mt->enable_collection = no_collection;
00110 mt->m_wr = wrbuf_alloc();
00111 mt->iconv_cd = 0;
00112 mt->leader_spec = 0;
00113 strcpy(mt->subfield_str, " $");
00114 strcpy(mt->endline_str, "\n");
00115
00116 mt->nmem = nmem_create();
00117 yaz_marc_reset(mt);
00118 return mt;
00119 }
00120
00121 void yaz_marc_destroy(yaz_marc_t mt)
00122 {
00123 if (!mt)
00124 return ;
00125 nmem_destroy(mt->nmem);
00126 wrbuf_destroy(mt->m_wr);
00127 xfree(mt->leader_spec);
00128 xfree(mt);
00129 }
00130
00131 NMEM yaz_marc_get_nmem(yaz_marc_t mt)
00132 {
00133 return mt->nmem;
00134 }
00135
00136 static void marc_iconv_reset(yaz_marc_t mt, WRBUF wr)
00137 {
00138 wrbuf_iconv_reset(wr, mt->iconv_cd);
00139 }
00140
00141 static int marc_exec_leader(const char *leader_spec, char *leader,
00142 size_t size);
00143 static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
00144 const char *ns,
00145 const char *format,
00146 const char *type);
00147
00148 static struct yaz_marc_node *yaz_marc_add_node(yaz_marc_t mt)
00149 {
00150 struct yaz_marc_node *n = (struct yaz_marc_node *)
00151 nmem_malloc(mt->nmem, sizeof(*n));
00152 n->next = 0;
00153 *mt->nodes_pp = n;
00154 mt->nodes_pp = &n->next;
00155 return n;
00156 }
00157
00158 #if YAZ_HAVE_XML2
00159 void yaz_marc_add_controlfield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
00160 const xmlNode *ptr_data)
00161 {
00162 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00163 n->which = YAZ_MARC_CONTROLFIELD;
00164 n->u.controlfield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
00165 n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
00166 }
00167
00168 void yaz_marc_add_controlfield_xml2(yaz_marc_t mt, char *tag,
00169 const xmlNode *ptr_data)
00170 {
00171 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00172 n->which = YAZ_MARC_CONTROLFIELD;
00173 n->u.controlfield.tag = tag;
00174 n->u.controlfield.data = nmem_text_node_cdata(ptr_data, mt->nmem);
00175 }
00176
00177 #endif
00178
00179
00180 void yaz_marc_add_comment(yaz_marc_t mt, char *comment)
00181 {
00182 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00183 n->which = YAZ_MARC_COMMENT;
00184 n->u.comment = nmem_strdup(mt->nmem, comment);
00185 }
00186
00187 void yaz_marc_cprintf(yaz_marc_t mt, const char *fmt, ...)
00188 {
00189 va_list ap;
00190 char buf[200];
00191
00192 va_start(ap, fmt);
00193 yaz_vsnprintf(buf, sizeof(buf)-1, fmt, ap);
00194 yaz_marc_add_comment(mt, buf);
00195 va_end (ap);
00196 }
00197
00198 int yaz_marc_get_debug(yaz_marc_t mt)
00199 {
00200 return mt->debug;
00201 }
00202
00203 void yaz_marc_add_leader(yaz_marc_t mt, const char *leader, size_t leader_len)
00204 {
00205 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00206 n->which = YAZ_MARC_LEADER;
00207 n->u.leader = nmem_strdupn(mt->nmem, leader, leader_len);
00208 marc_exec_leader(mt->leader_spec, n->u.leader, leader_len);
00209 }
00210
00211 void yaz_marc_add_controlfield(yaz_marc_t mt, const char *tag,
00212 const char *data, size_t data_len)
00213 {
00214 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00215 n->which = YAZ_MARC_CONTROLFIELD;
00216 n->u.controlfield.tag = nmem_strdup(mt->nmem, tag);
00217 n->u.controlfield.data = nmem_strdupn(mt->nmem, data, data_len);
00218 if (mt->debug)
00219 {
00220 size_t i;
00221 char msg[80];
00222
00223 sprintf(msg, "controlfield:");
00224 for (i = 0; i < 16 && i < data_len; i++)
00225 sprintf(msg + strlen(msg), " %02X", data[i] & 0xff);
00226 if (i < data_len)
00227 sprintf(msg + strlen(msg), " ..");
00228 yaz_marc_add_comment(mt, msg);
00229 }
00230 }
00231
00232 void yaz_marc_add_datafield(yaz_marc_t mt, const char *tag,
00233 const char *indicator, size_t indicator_len)
00234 {
00235 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00236 n->which = YAZ_MARC_DATAFIELD;
00237 n->u.datafield.tag = nmem_strdup(mt->nmem, tag);
00238 n->u.datafield.indicator =
00239 nmem_strdupn(mt->nmem, indicator, indicator_len);
00240 n->u.datafield.subfields = 0;
00241
00242
00243 mt->subfield_pp = &n->u.datafield.subfields;
00244 }
00245
00246
00247
00248
00249
00250 int element_name_append_attribute_value(yaz_marc_t mt, WRBUF buffer, const char *attribute_name, char *code_data, size_t code_len)
00251 {
00252
00253
00254 int encode = 0;
00255 int index = 0;
00256 int success = 0;
00257 for (index = 0; index < code_len; index++)
00258 {
00259 if (!((code_data[index] >= '0' && code_data[index] <= '9') ||
00260 (code_data[index] >= 'a' && code_data[index] <= 'z') ||
00261 (code_data[index] >= 'A' && code_data[index] <= 'Z')))
00262 encode = 1;
00263 }
00264
00265 if (encode && attribute_name)
00266 wrbuf_printf(buffer, " %s=\"", attribute_name);
00267
00268 if (!encode || attribute_name)
00269 wrbuf_iconv_write_cdata(buffer, mt->iconv_cd, code_data, code_len);
00270 else
00271 success = -1;
00272
00273 if (encode && attribute_name)
00274 wrbuf_printf(buffer, "\"");
00275 return success;
00276 }
00277
00278 #if YAZ_HAVE_XML2
00279 void yaz_marc_add_datafield_xml(yaz_marc_t mt, const xmlNode *ptr_tag,
00280 const char *indicator, size_t indicator_len)
00281 {
00282 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00283 n->which = YAZ_MARC_DATAFIELD;
00284 n->u.datafield.tag = nmem_text_node_cdata(ptr_tag, mt->nmem);
00285 n->u.datafield.indicator =
00286 nmem_strdupn(mt->nmem, indicator, indicator_len);
00287 n->u.datafield.subfields = 0;
00288
00289
00290 mt->subfield_pp = &n->u.datafield.subfields;
00291 }
00292
00293 void yaz_marc_add_datafield_xml2(yaz_marc_t mt, char *tag_value, char *indicators)
00294 {
00295 struct yaz_marc_node *n = yaz_marc_add_node(mt);
00296 n->which = YAZ_MARC_DATAFIELD;
00297 n->u.datafield.tag = tag_value;
00298 n->u.datafield.indicator = indicators;
00299 n->u.datafield.subfields = 0;
00300
00301
00302 mt->subfield_pp = &n->u.datafield.subfields;
00303 }
00304
00305 void yaz_marc_datafield_set_indicators(struct yaz_marc_node *n, char *indicator)
00306 {
00307 n->u.datafield.indicator = indicator;
00308 }
00309
00310 #endif
00311
00312 void yaz_marc_add_subfield(yaz_marc_t mt,
00313 const char *code_data, size_t code_data_len)
00314 {
00315 if (mt->debug)
00316 {
00317 size_t i;
00318 char msg[80];
00319
00320 sprintf(msg, "subfield:");
00321 for (i = 0; i < 16 && i < code_data_len; i++)
00322 sprintf(msg + strlen(msg), " %02X", code_data[i] & 0xff);
00323 if (i < code_data_len)
00324 sprintf(msg + strlen(msg), " ..");
00325 yaz_marc_add_comment(mt, msg);
00326 }
00327
00328 if (mt->subfield_pp)
00329 {
00330 struct yaz_marc_subfield *n = (struct yaz_marc_subfield *)
00331 nmem_malloc(mt->nmem, sizeof(*n));
00332 n->code_data = nmem_strdupn(mt->nmem, code_data, code_data_len);
00333 n->next = 0;
00334
00335 *mt->subfield_pp = n;
00336 mt->subfield_pp = &n->next;
00337 }
00338 }
00339
00340 void yaz_marc_set_leader(yaz_marc_t mt, const char *leader_c,
00341 int *indicator_length,
00342 int *identifier_length,
00343 int *base_address,
00344 int *length_data_entry,
00345 int *length_starting,
00346 int *length_implementation)
00347 {
00348 char leader[24];
00349
00350 memcpy(leader, leader_c, 24);
00351
00352 if (!atoi_n_check(leader+10, 1, indicator_length))
00353 {
00354 yaz_marc_cprintf(mt,
00355 "Indicator length at offset 10 should hold a digit."
00356 " Assuming 2");
00357 leader[10] = '2';
00358 *indicator_length = 2;
00359 }
00360 if (!atoi_n_check(leader+11, 1, identifier_length))
00361 {
00362 yaz_marc_cprintf(mt,
00363 "Identifier length at offset 11 should hold a digit."
00364 " Assuming 2");
00365 leader[11] = '2';
00366 *identifier_length = 2;
00367 }
00368 if (!atoi_n_check(leader+12, 5, base_address))
00369 {
00370 yaz_marc_cprintf(mt,
00371 "Base address at offsets 12..16 should hold a number."
00372 " Assuming 0");
00373 *base_address = 0;
00374 }
00375 if (!atoi_n_check(leader+20, 1, length_data_entry))
00376 {
00377 yaz_marc_cprintf(mt,
00378 "Length data entry at offset 20 should hold a digit."
00379 " Assuming 4");
00380 *length_data_entry = 4;
00381 leader[20] = '4';
00382 }
00383 if (!atoi_n_check(leader+21, 1, length_starting))
00384 {
00385 yaz_marc_cprintf(mt,
00386 "Length starting at offset 21 should hold a digit."
00387 " Assuming 5");
00388 *length_starting = 5;
00389 leader[21] = '5';
00390 }
00391 if (!atoi_n_check(leader+22, 1, length_implementation))
00392 {
00393 yaz_marc_cprintf(mt,
00394 "Length implementation at offset 22 should hold a digit."
00395 " Assuming 0");
00396 *length_implementation = 0;
00397 leader[22] = '0';
00398 }
00399
00400 if (mt->debug)
00401 {
00402 yaz_marc_cprintf(mt, "Indicator length %5d", *indicator_length);
00403 yaz_marc_cprintf(mt, "Identifier length %5d", *identifier_length);
00404 yaz_marc_cprintf(mt, "Base address %5d", *base_address);
00405 yaz_marc_cprintf(mt, "Length data entry %5d", *length_data_entry);
00406 yaz_marc_cprintf(mt, "Length starting %5d", *length_starting);
00407 yaz_marc_cprintf(mt, "Length implementation %5d", *length_implementation);
00408 }
00409 yaz_marc_add_leader(mt, leader, 24);
00410 }
00411
00412 void yaz_marc_subfield_str(yaz_marc_t mt, const char *s)
00413 {
00414 strncpy(mt->subfield_str, s, sizeof(mt->subfield_str)-1);
00415 mt->subfield_str[sizeof(mt->subfield_str)-1] = '\0';
00416 }
00417
00418 void yaz_marc_endline_str(yaz_marc_t mt, const char *s)
00419 {
00420 strncpy(mt->endline_str, s, sizeof(mt->endline_str)-1);
00421 mt->endline_str[sizeof(mt->endline_str)-1] = '\0';
00422 }
00423
00424
00425 static size_t cdata_one_character(yaz_marc_t mt, const char *buf)
00426 {
00427 if (mt->iconv_cd)
00428 {
00429 size_t i;
00430 for (i = 1; i<5; i++)
00431 {
00432 char outbuf[12];
00433 size_t outbytesleft = sizeof(outbuf);
00434 char *outp = outbuf;
00435 const char *inp = buf;
00436
00437 size_t inbytesleft = i;
00438 size_t r = yaz_iconv(mt->iconv_cd, (char**) &inp, &inbytesleft,
00439 &outp, &outbytesleft);
00440 if (r != (size_t) (-1))
00441 return i;
00442 }
00443 return 1;
00444 }
00445 return 1;
00446 }
00447
00448 void yaz_marc_reset(yaz_marc_t mt)
00449 {
00450 nmem_reset(mt->nmem);
00451 mt->nodes = 0;
00452 mt->nodes_pp = &mt->nodes;
00453 mt->subfield_pp = 0;
00454 }
00455
00456 int yaz_marc_write_check(yaz_marc_t mt, WRBUF wr)
00457 {
00458 struct yaz_marc_node *n;
00459 int identifier_length;
00460 const char *leader = 0;
00461
00462 for (n = mt->nodes; n; n = n->next)
00463 if (n->which == YAZ_MARC_LEADER)
00464 {
00465 leader = n->u.leader;
00466 break;
00467 }
00468
00469 if (!leader)
00470 return -1;
00471 if (!atoi_n_check(leader+11, 1, &identifier_length))
00472 return -1;
00473
00474 for (n = mt->nodes; n; n = n->next)
00475 {
00476 switch(n->which)
00477 {
00478 case YAZ_MARC_COMMENT:
00479 wrbuf_iconv_write(wr, mt->iconv_cd,
00480 n->u.comment, strlen(n->u.comment));
00481 wrbuf_puts(wr, "\n");
00482 break;
00483 default:
00484 break;
00485 }
00486 }
00487 return 0;
00488 }
00489
00490 static size_t get_subfield_len(yaz_marc_t mt, const char *data,
00491 int identifier_length)
00492 {
00493
00494
00495
00496 if (identifier_length > 2)
00497 return identifier_length - 1;
00498 else
00499 return cdata_one_character(mt, data);
00500 }
00501
00502 int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
00503 {
00504 struct yaz_marc_node *n;
00505 int identifier_length;
00506 const char *leader = 0;
00507
00508 for (n = mt->nodes; n; n = n->next)
00509 if (n->which == YAZ_MARC_LEADER)
00510 {
00511 leader = n->u.leader;
00512 break;
00513 }
00514
00515 if (!leader)
00516 return -1;
00517 if (!atoi_n_check(leader+11, 1, &identifier_length))
00518 return -1;
00519
00520 for (n = mt->nodes; n; n = n->next)
00521 {
00522 struct yaz_marc_subfield *s;
00523 switch(n->which)
00524 {
00525 case YAZ_MARC_DATAFIELD:
00526 wrbuf_printf(wr, "%s %s", n->u.datafield.tag,
00527 n->u.datafield.indicator);
00528 for (s = n->u.datafield.subfields; s; s = s->next)
00529 {
00530 size_t using_code_len = get_subfield_len(mt, s->code_data,
00531 identifier_length);
00532
00533 wrbuf_puts (wr, mt->subfield_str);
00534 wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data,
00535 using_code_len);
00536 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
00537 wrbuf_iconv_puts(wr, mt->iconv_cd,
00538 s->code_data + using_code_len);
00539 marc_iconv_reset(mt, wr);
00540 }
00541 wrbuf_puts (wr, mt->endline_str);
00542 break;
00543 case YAZ_MARC_CONTROLFIELD:
00544 wrbuf_printf(wr, "%s", n->u.controlfield.tag);
00545 wrbuf_iconv_puts(wr, mt->iconv_cd, " ");
00546 wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data);
00547 marc_iconv_reset(mt, wr);
00548 wrbuf_puts (wr, mt->endline_str);
00549 break;
00550 case YAZ_MARC_COMMENT:
00551 wrbuf_puts(wr, "(");
00552 wrbuf_iconv_write(wr, mt->iconv_cd,
00553 n->u.comment, strlen(n->u.comment));
00554 marc_iconv_reset(mt, wr);
00555 wrbuf_puts(wr, ")\n");
00556 break;
00557 case YAZ_MARC_LEADER:
00558 wrbuf_printf(wr, "%s\n", n->u.leader);
00559 }
00560 }
00561 wrbuf_puts(wr, "\n");
00562 return 0;
00563 }
00564
00565 int yaz_marc_write_trailer(yaz_marc_t mt, WRBUF wr)
00566 {
00567 if (mt->enable_collection == collection_second)
00568 {
00569 switch(mt->output_format)
00570 {
00571 case YAZ_MARC_MARCXML:
00572 case YAZ_MARC_TURBOMARC:
00573 wrbuf_printf(wr, "</collection>\n");
00574 break;
00575 case YAZ_MARC_XCHANGE:
00576 wrbuf_printf(wr, "</collection>\n");
00577 break;
00578 }
00579 }
00580 return 0;
00581 }
00582
00583 void yaz_marc_enable_collection(yaz_marc_t mt)
00584 {
00585 mt->enable_collection = collection_first;
00586 }
00587
00588 int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
00589 {
00590 switch(mt->output_format)
00591 {
00592 case YAZ_MARC_LINE:
00593 return yaz_marc_write_line(mt, wr);
00594 case YAZ_MARC_MARCXML:
00595 return yaz_marc_write_marcxml(mt, wr);
00596 case YAZ_MARC_TURBOMARC:
00597 return yaz_marc_write_turbomarc(mt, wr);
00598 case YAZ_MARC_XCHANGE:
00599 return yaz_marc_write_marcxchange(mt, wr, 0, 0);
00600 case YAZ_MARC_ISO2709:
00601 return yaz_marc_write_iso2709(mt, wr);
00602 case YAZ_MARC_CHECK:
00603 return yaz_marc_write_check(mt, wr);
00604 }
00605 return -1;
00606 }
00607
00608 static const char *record_name[2] = { "record", "r"};
00609 static const char *leader_name[2] = { "leader", "l"};
00610 static const char *controlfield_name[2] = { "controlfield", "c"};
00611 static const char *datafield_name[2] = { "datafield", "d"};
00612 static const char *indicator_name[2] = { "ind", "i"};
00613 static const char *subfield_name[2] = { "subfield", "s"};
00614
00625 static int yaz_marc_write_marcxml_wrbuf(yaz_marc_t mt, WRBUF wr,
00626 const char *ns,
00627 const char *format,
00628 const char *type,
00629 int turbo)
00630 {
00631 struct yaz_marc_node *n;
00632 int identifier_length;
00633 const char *leader = 0;
00634
00635 for (n = mt->nodes; n; n = n->next)
00636 if (n->which == YAZ_MARC_LEADER)
00637 {
00638 leader = n->u.leader;
00639 break;
00640 }
00641
00642 if (!leader)
00643 return -1;
00644 if (!atoi_n_check(leader+11, 1, &identifier_length))
00645 return -1;
00646
00647 if (mt->enable_collection != no_collection)
00648 {
00649 if (mt->enable_collection == collection_first)
00650 {
00651 wrbuf_printf(wr, "<collection xmlns=\"%s\">\n", ns);
00652 mt->enable_collection = collection_second;
00653 }
00654 wrbuf_printf(wr, "<%s", record_name[turbo]);
00655 }
00656 else
00657 {
00658 wrbuf_printf(wr, "<%s xmlns=\"%s\"", record_name[turbo], ns);
00659 }
00660 if (format)
00661 wrbuf_printf(wr, " format=\"%.80s\"", format);
00662 if (type)
00663 wrbuf_printf(wr, " type=\"%.80s\"", type);
00664 wrbuf_printf(wr, ">\n");
00665 for (n = mt->nodes; n; n = n->next)
00666 {
00667 struct yaz_marc_subfield *s;
00668
00669 switch(n->which)
00670 {
00671 case YAZ_MARC_DATAFIELD:
00672
00673 wrbuf_printf(wr, " <%s", datafield_name[turbo]);
00674 if (!turbo)
00675 wrbuf_printf(wr, " tag=\"");
00676 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
00677 strlen(n->u.datafield.tag));
00678 if (!turbo)
00679 wrbuf_printf(wr, "\"");
00680 if (n->u.datafield.indicator)
00681 {
00682 int i;
00683 for (i = 0; n->u.datafield.indicator[i]; i++)
00684 {
00685 wrbuf_printf(wr, " %s%d=\"", indicator_name[turbo], i+1);
00686 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
00687 n->u.datafield.indicator+i, 1);
00688 wrbuf_iconv_puts(wr, mt->iconv_cd, "\"");
00689 }
00690 }
00691 wrbuf_printf(wr, ">\n");
00692 for (s = n->u.datafield.subfields; s; s = s->next)
00693 {
00694 size_t using_code_len = get_subfield_len(mt, s->code_data,
00695 identifier_length);
00696 wrbuf_printf(wr, " <%s", subfield_name[turbo]);
00697 if (!turbo)
00698 {
00699 wrbuf_printf(wr, " code=\"");
00700 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
00701 s->code_data, using_code_len);
00702 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
00703 }
00704 else
00705 {
00706 element_name_append_attribute_value(mt, wr, "code", s->code_data, using_code_len);
00707 wrbuf_puts(wr, ">");
00708 }
00709 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
00710 s->code_data + using_code_len,
00711 strlen(s->code_data + using_code_len));
00712 marc_iconv_reset(mt, wr);
00713 wrbuf_printf(wr, "</%s", subfield_name[turbo]);
00714 if (turbo)
00715 element_name_append_attribute_value(mt, wr, 0, s->code_data, using_code_len);
00716 wrbuf_puts(wr, ">\n");
00717 }
00718 wrbuf_printf(wr, " </%s", datafield_name[turbo]);
00719
00720 if (turbo)
00721 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.datafield.tag,
00722 strlen(n->u.datafield.tag));
00723 wrbuf_printf(wr, ">\n");
00724 break;
00725 case YAZ_MARC_CONTROLFIELD:
00726 wrbuf_printf(wr, " <%s", controlfield_name[turbo]);
00727 if (!turbo)
00728 {
00729 wrbuf_printf(wr, " tag=\"");
00730 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
00731 strlen(n->u.controlfield.tag));
00732 wrbuf_iconv_puts(wr, mt->iconv_cd, "\">");
00733 }
00734 else
00735 {
00736
00737 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
00738 strlen(n->u.controlfield.tag));
00739 wrbuf_iconv_puts(wr, mt->iconv_cd, ">");
00740 }
00741 wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
00742 n->u.controlfield.data,
00743 strlen(n->u.controlfield.data));
00744 marc_iconv_reset(mt, wr);
00745 wrbuf_printf(wr, "</%s", controlfield_name[turbo]);
00746
00747 if (turbo)
00748 wrbuf_iconv_write_cdata(wr, mt->iconv_cd, n->u.controlfield.tag,
00749 strlen(n->u.controlfield.tag));
00750 wrbuf_puts(wr, ">\n");
00751 break;
00752 case YAZ_MARC_COMMENT:
00753 wrbuf_printf(wr, "<!-- ");
00754 wrbuf_puts(wr, n->u.comment);
00755 wrbuf_printf(wr, " -->\n");
00756 break;
00757 case YAZ_MARC_LEADER:
00758 wrbuf_printf(wr, " <%s>", leader_name[turbo]);
00759 wrbuf_iconv_write_cdata(wr,
00760 0 ,
00761 n->u.leader, strlen(n->u.leader));
00762 wrbuf_printf(wr, "</%s>\n", leader_name[turbo]);
00763 }
00764 }
00765 wrbuf_printf(wr, "</%s>\n", record_name[turbo]);
00766 return 0;
00767 }
00768
00769 static int yaz_marc_write_marcxml_ns(yaz_marc_t mt, WRBUF wr,
00770 const char *ns,
00771 const char *format,
00772 const char *type,
00773 int turbo)
00774 {
00775 if (mt->write_using_libxml2)
00776 {
00777 #if YAZ_HAVE_XML2
00778 int ret;
00779 xmlNode *root_ptr;
00780
00781 if (!turbo)
00782 ret = yaz_marc_write_xml(mt, &root_ptr, ns, format, type);
00783 else
00784 ret = yaz_marc_write_xml_turbo_xml(mt, &root_ptr, ns, format, type);
00785 if (ret == 0)
00786 {
00787 xmlChar *buf_out;
00788 xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
00789 int len_out;
00790
00791 xmlDocSetRootElement(doc, root_ptr);
00792 xmlDocDumpMemory(doc, &buf_out, &len_out);
00793
00794 wrbuf_write(wr, (const char *) buf_out, len_out);
00795 wrbuf_puts(wr, "");
00796 xmlFree(buf_out);
00797 xmlFreeDoc(doc);
00798 }
00799 return ret;
00800 #else
00801 return -1;
00802 #endif
00803 }
00804 else
00805 return yaz_marc_write_marcxml_wrbuf(mt, wr, ns, format, type, turbo);
00806 }
00807
00808 int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
00809 {
00810
00811
00812 if (!mt->leader_spec)
00813 yaz_marc_modify_leader(mt, 9, "a");
00814 return yaz_marc_write_marcxml_ns(mt, wr,
00815 "http://www.loc.gov/MARC21/slim",
00816 0, 0, 0);
00817 }
00818
00819 int yaz_marc_write_turbomarc(yaz_marc_t mt, WRBUF wr)
00820 {
00821
00822
00823 if (!mt->leader_spec)
00824 yaz_marc_modify_leader(mt, 9, "a");
00825 return yaz_marc_write_marcxml_ns(mt, wr,
00826 "http://www.indexdata.com/turbomarc", 0, 0, 1);
00827 }
00828
00829 int yaz_marc_write_marcxchange(yaz_marc_t mt, WRBUF wr,
00830 const char *format,
00831 const char *type)
00832 {
00833 return yaz_marc_write_marcxml_ns(mt, wr,
00834 "info:lc/xmlns/marcxchange-v1",
00835 0, 0, 0);
00836 }
00837
00838 #if YAZ_HAVE_XML2
00839
00840 void add_marc_datafield_turbo_xml(yaz_marc_t mt, struct yaz_marc_node *n,
00841 xmlNode *record_ptr,
00842 xmlNsPtr ns_record, WRBUF wr_cdata,
00843 int identifier_length)
00844 {
00845 xmlNode *ptr;
00846 struct yaz_marc_subfield *s;
00847 WRBUF subfield_name = wrbuf_alloc();
00848
00849
00850 char field[10];
00851 field[0] = 'd';
00852 strncpy(field + 1, n->u.datafield.tag, 3);
00853 field[4] = '\0';
00854 ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST field, 0);
00855
00856 if (n->u.datafield.indicator)
00857 {
00858 int i;
00859 for (i = 0; n->u.datafield.indicator[i]; i++)
00860 {
00861 char ind_str[6];
00862 char ind_val[2];
00863
00864 ind_val[0] = n->u.datafield.indicator[i];
00865 ind_val[1] = '\0';
00866 sprintf(ind_str, "%s%d", indicator_name[1], i+1);
00867 xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
00868 }
00869 }
00870 for (s = n->u.datafield.subfields; s; s = s->next)
00871 {
00872 int not_written;
00873 xmlNode *ptr_subfield;
00874 size_t using_code_len = get_subfield_len(mt, s->code_data,
00875 identifier_length);
00876 wrbuf_rewind(wr_cdata);
00877 wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, s->code_data + using_code_len);
00878 marc_iconv_reset(mt, wr_cdata);
00879
00880 wrbuf_rewind(subfield_name);
00881 wrbuf_puts(subfield_name, "s");
00882 not_written = element_name_append_attribute_value(mt, subfield_name, 0, s->code_data, using_code_len) != 0;
00883 ptr_subfield = xmlNewTextChild(ptr, ns_record,
00884 BAD_CAST wrbuf_cstr(subfield_name),
00885 BAD_CAST wrbuf_cstr(wr_cdata));
00886 if (not_written)
00887 {
00888
00889 wrbuf_rewind(wr_cdata);
00890 wrbuf_iconv_write(wr_cdata, mt->iconv_cd,s->code_data, using_code_len);
00891 xmlNewProp(ptr_subfield, BAD_CAST "code", BAD_CAST wrbuf_cstr(wr_cdata));
00892 }
00893 }
00894 wrbuf_destroy(subfield_name);
00895 }
00896
00897 static int yaz_marc_write_xml_turbo_xml(yaz_marc_t mt, xmlNode **root_ptr,
00898 const char *ns,
00899 const char *format,
00900 const char *type)
00901 {
00902 struct yaz_marc_node *n;
00903 int identifier_length;
00904 const char *leader = 0;
00905 xmlNode *record_ptr;
00906 xmlNsPtr ns_record;
00907 WRBUF wr_cdata = 0;
00908
00909 for (n = mt->nodes; n; n = n->next)
00910 if (n->which == YAZ_MARC_LEADER)
00911 {
00912 leader = n->u.leader;
00913 break;
00914 }
00915
00916 if (!leader)
00917 return -1;
00918 if (!atoi_n_check(leader+11, 1, &identifier_length))
00919 return -1;
00920
00921 wr_cdata = wrbuf_alloc();
00922
00923 record_ptr = xmlNewNode(0, BAD_CAST "r");
00924 *root_ptr = record_ptr;
00925
00926 ns_record = xmlNewNs(record_ptr, BAD_CAST ns, 0);
00927 xmlSetNs(record_ptr, ns_record);
00928
00929 if (format)
00930 xmlNewProp(record_ptr, BAD_CAST "format", BAD_CAST format);
00931 if (type)
00932 xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
00933 for (n = mt->nodes; n; n = n->next)
00934 {
00935 xmlNode *ptr;
00936
00937 char field[10];
00938 field[0] = 'c';
00939 field[4] = '\0';
00940
00941 switch(n->which)
00942 {
00943 case YAZ_MARC_DATAFIELD:
00944 add_marc_datafield_turbo_xml(mt, n, record_ptr, ns_record, wr_cdata, identifier_length);
00945 break;
00946 case YAZ_MARC_CONTROLFIELD:
00947 wrbuf_rewind(wr_cdata);
00948 wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
00949 marc_iconv_reset(mt, wr_cdata);
00950
00951 strncpy(field + 1, n->u.controlfield.tag, 3);
00952 ptr = xmlNewTextChild(record_ptr, ns_record,
00953 BAD_CAST field,
00954 BAD_CAST wrbuf_cstr(wr_cdata));
00955 break;
00956 case YAZ_MARC_COMMENT:
00957 ptr = xmlNewComment(BAD_CAST n->u.comment);
00958 xmlAddChild(record_ptr, ptr);
00959 break;
00960 case YAZ_MARC_LEADER:
00961 {
00962 char *field = "leader";
00963 field = "l";
00964 xmlNewTextChild(record_ptr, ns_record, BAD_CAST field,
00965 BAD_CAST n->u.leader);
00966 }
00967 break;
00968 }
00969 }
00970 wrbuf_destroy(wr_cdata);
00971 return 0;
00972 }
00973
00974
00975 int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
00976 const char *ns,
00977 const char *format,
00978 const char *type)
00979 {
00980 struct yaz_marc_node *n;
00981 int identifier_length;
00982 const char *leader = 0;
00983 xmlNode *record_ptr;
00984 xmlNsPtr ns_record;
00985 WRBUF wr_cdata = 0;
00986
00987 for (n = mt->nodes; n; n = n->next)
00988 if (n->which == YAZ_MARC_LEADER)
00989 {
00990 leader = n->u.leader;
00991 break;
00992 }
00993
00994 if (!leader)
00995 return -1;
00996 if (!atoi_n_check(leader+11, 1, &identifier_length))
00997 return -1;
00998
00999 wr_cdata = wrbuf_alloc();
01000
01001 record_ptr = xmlNewNode(0, BAD_CAST "record");
01002 *root_ptr = record_ptr;
01003
01004 ns_record = xmlNewNs(record_ptr, BAD_CAST ns, 0);
01005 xmlSetNs(record_ptr, ns_record);
01006
01007 if (format)
01008 xmlNewProp(record_ptr, BAD_CAST "format", BAD_CAST format);
01009 if (type)
01010 xmlNewProp(record_ptr, BAD_CAST "type", BAD_CAST type);
01011 for (n = mt->nodes; n; n = n->next)
01012 {
01013 struct yaz_marc_subfield *s;
01014 xmlNode *ptr;
01015
01016 switch(n->which)
01017 {
01018 case YAZ_MARC_DATAFIELD:
01019 ptr = xmlNewChild(record_ptr, ns_record, BAD_CAST "datafield", 0);
01020 xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.datafield.tag);
01021 if (n->u.datafield.indicator)
01022 {
01023 int i;
01024 for (i = 0; n->u.datafield.indicator[i]; i++)
01025 {
01026 char ind_str[6];
01027 char ind_val[2];
01028
01029 sprintf(ind_str, "ind%d", i+1);
01030 ind_val[0] = n->u.datafield.indicator[i];
01031 ind_val[1] = '\0';
01032 xmlNewProp(ptr, BAD_CAST ind_str, BAD_CAST ind_val);
01033 }
01034 }
01035 for (s = n->u.datafield.subfields; s; s = s->next)
01036 {
01037 xmlNode *ptr_subfield;
01038 size_t using_code_len = get_subfield_len(mt, s->code_data,
01039 identifier_length);
01040 wrbuf_rewind(wr_cdata);
01041 wrbuf_iconv_puts(wr_cdata, mt->iconv_cd,
01042 s->code_data + using_code_len);
01043 marc_iconv_reset(mt, wr_cdata);
01044 ptr_subfield = xmlNewTextChild(
01045 ptr, ns_record,
01046 BAD_CAST "subfield", BAD_CAST wrbuf_cstr(wr_cdata));
01047
01048 wrbuf_rewind(wr_cdata);
01049 wrbuf_iconv_write(wr_cdata, mt->iconv_cd,
01050 s->code_data, using_code_len);
01051 xmlNewProp(ptr_subfield, BAD_CAST "code",
01052 BAD_CAST wrbuf_cstr(wr_cdata));
01053 }
01054 break;
01055 case YAZ_MARC_CONTROLFIELD:
01056 wrbuf_rewind(wr_cdata);
01057 wrbuf_iconv_puts(wr_cdata, mt->iconv_cd, n->u.controlfield.data);
01058 marc_iconv_reset(mt, wr_cdata);
01059
01060 ptr = xmlNewTextChild(record_ptr, ns_record,
01061 BAD_CAST "controlfield",
01062 BAD_CAST wrbuf_cstr(wr_cdata));
01063
01064 xmlNewProp(ptr, BAD_CAST "tag", BAD_CAST n->u.controlfield.tag);
01065 break;
01066 case YAZ_MARC_COMMENT:
01067 ptr = xmlNewComment(BAD_CAST n->u.comment);
01068 xmlAddChild(record_ptr, ptr);
01069 break;
01070 case YAZ_MARC_LEADER:
01071 xmlNewTextChild(record_ptr, ns_record, BAD_CAST "leader",
01072 BAD_CAST n->u.leader);
01073 break;
01074 }
01075 }
01076 wrbuf_destroy(wr_cdata);
01077 return 0;
01078 }
01079
01080 #endif
01081
01082 int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
01083 {
01084 struct yaz_marc_node *n;
01085 int indicator_length;
01086 int identifier_length;
01087 int length_data_entry;
01088 int length_starting;
01089 int length_implementation;
01090 int data_offset = 0;
01091 const char *leader = 0;
01092 WRBUF wr_dir, wr_head, wr_data_tmp;
01093 int base_address;
01094
01095 for (n = mt->nodes; n; n = n->next)
01096 if (n->which == YAZ_MARC_LEADER)
01097 leader = n->u.leader;
01098
01099 if (!leader)
01100 return -1;
01101 if (!atoi_n_check(leader+10, 1, &indicator_length))
01102 return -1;
01103 if (!atoi_n_check(leader+11, 1, &identifier_length))
01104 return -1;
01105 if (!atoi_n_check(leader+20, 1, &length_data_entry))
01106 return -1;
01107 if (!atoi_n_check(leader+21, 1, &length_starting))
01108 return -1;
01109 if (!atoi_n_check(leader+22, 1, &length_implementation))
01110 return -1;
01111
01112 wr_data_tmp = wrbuf_alloc();
01113 wr_dir = wrbuf_alloc();
01114 for (n = mt->nodes; n; n = n->next)
01115 {
01116 int data_length = 0;
01117 struct yaz_marc_subfield *s;
01118
01119 switch(n->which)
01120 {
01121 case YAZ_MARC_DATAFIELD:
01122 wrbuf_printf(wr_dir, "%.3s", n->u.datafield.tag);
01123 data_length += indicator_length;
01124 wrbuf_rewind(wr_data_tmp);
01125 for (s = n->u.datafield.subfields; s; s = s->next)
01126 {
01127
01128 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
01129 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd, s->code_data);
01130 marc_iconv_reset(mt, wr_data_tmp);
01131 }
01132
01133 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
01134 marc_iconv_reset(mt, wr_data_tmp);
01135 data_length += wrbuf_len(wr_data_tmp);
01136 break;
01137 case YAZ_MARC_CONTROLFIELD:
01138 wrbuf_printf(wr_dir, "%.3s", n->u.controlfield.tag);
01139
01140 wrbuf_rewind(wr_data_tmp);
01141 wrbuf_iconv_puts(wr_data_tmp, mt->iconv_cd,
01142 n->u.controlfield.data);
01143 marc_iconv_reset(mt, wr_data_tmp);
01144 wrbuf_iconv_putchar(wr_data_tmp, mt->iconv_cd, ' ');
01145 marc_iconv_reset(mt, wr_data_tmp);
01146 data_length += wrbuf_len(wr_data_tmp);
01147 break;
01148 case YAZ_MARC_COMMENT:
01149 break;
01150 case YAZ_MARC_LEADER:
01151 break;
01152 }
01153 if (data_length)
01154 {
01155 wrbuf_printf(wr_dir, "%0*d", length_data_entry, data_length);
01156 wrbuf_printf(wr_dir, "%0*d", length_starting, data_offset);
01157 data_offset += data_length;
01158 }
01159 }
01160
01161 wrbuf_putc(wr_dir, ISO2709_FS);
01162
01163
01164 base_address = 24 + wrbuf_len(wr_dir);
01165
01166 wr_head = wrbuf_alloc();
01167
01168
01169 wrbuf_printf(wr_head, "%05d", base_address + data_offset + 1);
01170
01171 wrbuf_write(wr_head, leader+5, 7);
01172
01173 wrbuf_printf(wr_head, "%05d", base_address);
01174
01175 wrbuf_write(wr_head, leader+17, 7);
01176
01177 wrbuf_write(wr, wrbuf_buf(wr_head), 24);
01178 wrbuf_write(wr, wrbuf_buf(wr_dir), wrbuf_len(wr_dir));
01179 wrbuf_destroy(wr_head);
01180 wrbuf_destroy(wr_dir);
01181 wrbuf_destroy(wr_data_tmp);
01182
01183 for (n = mt->nodes; n; n = n->next)
01184 {
01185 struct yaz_marc_subfield *s;
01186
01187 switch(n->which)
01188 {
01189 case YAZ_MARC_DATAFIELD:
01190 wrbuf_printf(wr, "%.*s", indicator_length,
01191 n->u.datafield.indicator);
01192 for (s = n->u.datafield.subfields; s; s = s->next)
01193 {
01194 wrbuf_putc(wr, ISO2709_IDFS);
01195 wrbuf_iconv_puts(wr, mt->iconv_cd, s->code_data);
01196 marc_iconv_reset(mt, wr);
01197 }
01198 wrbuf_putc(wr, ISO2709_FS);
01199 break;
01200 case YAZ_MARC_CONTROLFIELD:
01201 wrbuf_iconv_puts(wr, mt->iconv_cd, n->u.controlfield.data);
01202 marc_iconv_reset(mt, wr);
01203 wrbuf_putc(wr, ISO2709_FS);
01204 break;
01205 case YAZ_MARC_COMMENT:
01206 break;
01207 case YAZ_MARC_LEADER:
01208 break;
01209 }
01210 }
01211 wrbuf_printf(wr, "%c", ISO2709_RS);
01212 return 0;
01213 }
01214
01215
01216 int yaz_marc_decode_wrbuf(yaz_marc_t mt, const char *buf, int bsize, WRBUF wr)
01217 {
01218 int s, r = yaz_marc_read_iso2709(mt, buf, bsize);
01219 if (r <= 0)
01220 return r;
01221 s = yaz_marc_write_mode(mt, wr);
01222 if (s != 0)
01223 return -1;
01224 return r;
01225 }
01226
01227 int yaz_marc_decode_buf (yaz_marc_t mt, const char *buf, int bsize,
01228 const char **result, size_t *rsize)
01229 {
01230 int r;
01231
01232 wrbuf_rewind(mt->m_wr);
01233 r = yaz_marc_decode_wrbuf(mt, buf, bsize, mt->m_wr);
01234 if (result)
01235 *result = wrbuf_cstr(mt->m_wr);
01236 if (rsize)
01237 *rsize = wrbuf_len(mt->m_wr);
01238 return r;
01239 }
01240
01241 void yaz_marc_xml(yaz_marc_t mt, int xmlmode)
01242 {
01243 mt->output_format = xmlmode;
01244 }
01245
01246 void yaz_marc_debug(yaz_marc_t mt, int level)
01247 {
01248 if (mt)
01249 mt->debug = level;
01250 }
01251
01252 void yaz_marc_iconv(yaz_marc_t mt, yaz_iconv_t cd)
01253 {
01254 mt->iconv_cd = cd;
01255 }
01256
01257 yaz_iconv_t yaz_marc_get_iconv(yaz_marc_t mt)
01258 {
01259 return mt->iconv_cd;
01260 }
01261
01262 void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str)
01263 {
01264 struct yaz_marc_node *n;
01265 char *leader = 0;
01266 for (n = mt->nodes; n; n = n->next)
01267 if (n->which == YAZ_MARC_LEADER)
01268 {
01269 leader = n->u.leader;
01270 memcpy(leader+off, str, strlen(str));
01271 break;
01272 }
01273 }
01274
01275 int yaz_marc_leader_spec(yaz_marc_t mt, const char *leader_spec)
01276 {
01277 xfree(mt->leader_spec);
01278 mt->leader_spec = 0;
01279 if (leader_spec)
01280 {
01281 char dummy_leader[24];
01282 if (marc_exec_leader(leader_spec, dummy_leader, 24))
01283 return -1;
01284 mt->leader_spec = xstrdup(leader_spec);
01285 }
01286 return 0;
01287 }
01288
01289 static int marc_exec_leader(const char *leader_spec, char *leader, size_t size)
01290 {
01291 const char *cp = leader_spec;
01292 while (cp)
01293 {
01294 char val[21];
01295 int pos;
01296 int no_read = 0, no = 0;
01297
01298 no = sscanf(cp, "%d=%20[^,]%n", &pos, val, &no_read);
01299 if (no < 2 || no_read < 3)
01300 return -1;
01301 if (pos < 0 || (size_t) pos >= size)
01302 return -1;
01303
01304 if (*val == '\'')
01305 {
01306 const char *vp = strchr(val+1, '\'');
01307 size_t len;
01308
01309 if (!vp)
01310 return -1;
01311 len = vp-val-1;
01312 if (len + pos > size)
01313 return -1;
01314 memcpy(leader + pos, val+1, len);
01315 }
01316 else if (*val >= '0' && *val <= '9')
01317 {
01318 int ch = atoi(val);
01319 leader[pos] = ch;
01320 }
01321 else
01322 return -1;
01323 cp += no_read;
01324 if (*cp != ',')
01325 break;
01326
01327 cp++;
01328 }
01329 return 0;
01330 }
01331
01332 int yaz_marc_decode_formatstr(const char *arg)
01333 {
01334 int mode = -1;
01335 if (!strcmp(arg, "marc"))
01336 mode = YAZ_MARC_ISO2709;
01337 if (!strcmp(arg, "marcxml"))
01338 mode = YAZ_MARC_MARCXML;
01339 if (!strcmp(arg, "turbomarc"))
01340 mode = YAZ_MARC_TURBOMARC;
01341 if (!strcmp(arg, "marcxchange"))
01342 mode = YAZ_MARC_XCHANGE;
01343 if (!strcmp(arg, "line"))
01344 mode = YAZ_MARC_LINE;
01345 return mode;
01346 }
01347
01348 void yaz_marc_write_using_libxml2(yaz_marc_t mt, int enable)
01349 {
01350 mt->write_using_libxml2 = enable;
01351 }
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361