-/*
- * Copyright (C) 1995-2007, Index Data ApS
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2009 Index Data
* See the file LICENSE for details.
- *
- * $Id: marcdisp.c,v 1.51 2007-09-20 17:22:45 adam Exp $
*/
/**
#include <stdarg.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <yaz/marcdisp.h>
#include <libxml/tree.h>
#endif
+enum yaz_collection_state {
+ no_collection,
+ collection_first,
+ collection_second
+};
+
/** \brief node types for yaz_marc_node */
enum YAZ_MARC_NODE_TYPE
{
int xml;
int debug;
int write_using_libxml2;
+ enum yaz_collection_state enable_collection;
yaz_iconv_t iconv_cd;
char subfield_str[8];
char endline_str[8];
mt->xml = YAZ_MARC_LINE;
mt->debug = 0;
mt->write_using_libxml2 = 0;
+ mt->enable_collection = no_collection;
mt->m_wr = wrbuf_alloc();
mt->iconv_cd = 0;
mt->leader_spec = 0;
return 0;
}
+static size_t get_subfield_len(yaz_marc_t mt, const char *data,
+ int identifier_length)
+{
+ /* if identifier length is 2 (most MARCs) or less (probably an error),
+ the code is a single character .. However we've
+ seen multibyte codes, so see how big it really is */
+ if (identifier_length > 2)
+ return identifier_length - 1;
+ else
+ return cdata_one_character(mt, data);
+}
int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr)
{
n->u.datafield.indicator);
for (s = n->u.datafield.subfields; s; s = s->next)
{
- /* if identifier length is 2 (most MARCs),
- the code is a single character .. However we've
- seen multibyte codes, so see how big it really is */
- size_t using_code_len =
- (identifier_length != 2) ? identifier_length - 1
- :
- cdata_one_character(mt, s->code_data);
+ size_t using_code_len = get_subfield_len(mt, s->code_data,
+ identifier_length);
wrbuf_puts (wr, mt->subfield_str);
wrbuf_iconv_write(wr, mt->iconv_cd, s->code_data,
return 0;
}
+int yaz_marc_write_trailer(yaz_marc_t mt, WRBUF wr)
+{
+ if (mt->enable_collection == collection_second)
+ {
+ switch(mt->xml)
+ {
+ case YAZ_MARC_MARCXML:
+ wrbuf_printf(wr, "</collection>\n");
+ break;
+ case YAZ_MARC_XCHANGE:
+ wrbuf_printf(wr, "</collection>\n");
+ break;
+ }
+ }
+ return 0;
+}
+
+void yaz_marc_enable_collection(yaz_marc_t mt)
+{
+ mt->enable_collection = collection_first;
+}
+
int yaz_marc_write_mode(yaz_marc_t mt, WRBUF wr)
{
switch(mt->xml)
return -1;
if (!atoi_n_check(leader+11, 1, &identifier_length))
return -1;
-
- wrbuf_printf(wr, "<record xmlns=\"%s\"", ns);
+
+ if (mt->enable_collection != no_collection)
+ {
+ if (mt->enable_collection == collection_first)
+ wrbuf_printf(wr, "<collection xmlns=\"%s\">\n", ns);
+ mt->enable_collection = collection_second;
+ wrbuf_printf(wr, "<record");
+ }
+ else
+ {
+ wrbuf_printf(wr, "<record xmlns=\"%s\"", ns);
+ }
if (format)
wrbuf_printf(wr, " format=\"%.80s\"", format);
if (type)
wrbuf_printf(wr, ">\n");
for (s = n->u.datafield.subfields; s; s = s->next)
{
- /* if identifier length is 2 (most MARCs),
- the code is a single character .. However we've
- seen multibyte codes, so see how big it really is */
- size_t using_code_len =
- (identifier_length != 2) ? identifier_length - 1
- :
- cdata_one_character(mt, s->code_data);
-
+ size_t using_code_len = get_subfield_len(mt, s->code_data,
+ identifier_length);
wrbuf_iconv_puts(wr, mt->iconv_cd, " <subfield code=\"");
wrbuf_iconv_write_cdata(wr, mt->iconv_cd,
s->code_data, using_code_len);
int yaz_marc_write_marcxml(yaz_marc_t mt, WRBUF wr)
{
+ /* set leader 09 to 'a' for UNICODE */
+ /* http://www.loc.gov/marc/bibliographic/ecbdldrd.html#mrcblea */
if (!mt->leader_spec)
yaz_marc_modify_leader(mt, 9, "a");
return yaz_marc_write_marcxml_ns(mt, wr, "http://www.loc.gov/MARC21/slim",
const char *type)
{
return yaz_marc_write_marcxml_ns(mt, wr,
- "http://www.bs.dk/standards/MarcXchange",
+ "info:lc/xmlns/marcxchange-v1",
0, 0);
}
+#if YAZ_HAVE_XML2
int yaz_marc_write_xml(yaz_marc_t mt, xmlNode **root_ptr,
const char *ns,
const char *format,
const char *type)
{
-#if YAZ_HAVE_XML2
struct yaz_marc_node *n;
int identifier_length;
const char *leader = 0;
for (s = n->u.datafield.subfields; s; s = s->next)
{
xmlNode *ptr_subfield;
- /* if identifier length is 2 (most MARCs),
- the code is a single character .. However we've
- seen multibyte codes, so see how big it really is */
- size_t using_code_len =
- (identifier_length != 2) ? identifier_length - 1
- :
- cdata_one_character(mt, s->code_data);
-
+ size_t using_code_len = get_subfield_len(mt, s->code_data,
+ identifier_length);
wrbuf_rewind(wr_cdata);
wrbuf_iconv_puts(wr_cdata, mt->iconv_cd,
s->code_data + using_code_len);
}
wrbuf_destroy(wr_cdata);
return 0;
-#else
- return -1;
-#endif
}
+#endif
int yaz_marc_write_iso2709(yaz_marc_t mt, WRBUF wr)
{
mt->iconv_cd = cd;
}
+yaz_iconv_t yaz_marc_get_iconv(yaz_marc_t mt)
+{
+ return mt->iconv_cd;
+}
+
void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, const char *str)
{
struct yaz_marc_node *n;
no = sscanf(cp, "%d=%20[^,]%n", &pos, val, &no_read);
if (no < 2 || no_read < 3)
return -1;
- if (pos < 0 || pos >= size)
+ if (pos < 0 || (size_t) pos >= size)
return -1;
if (*val == '\'')
/*
* Local variables:
* c-basic-offset: 4
+ * c-file-style: "Stroustrup"
* indent-tabs-mode: nil
* End:
* vim: shiftwidth=4 tabstop=8 expandtab