From cd2f012a70ebadf660acb71936e32192287dc30a Mon Sep 17 00:00:00 2001 From: Adam Dickmeiss Date: Fri, 15 Dec 2006 19:28:45 +0000 Subject: [PATCH] Implemented function yaz_marc_read_line which parses MARC line format records. There is a wealth of formats out there. So far, this function reads line records produced by yaz_marc_write_line. yaz-marcdump's options -x, -X, -I, -e have been replaced with the more generic and easier to remember(!) options: -i format and -o format which specifies input format and output format respectively - where format is one of "marc", "marcxml", "line", "marcxchange". --- NEWS | 9 +++ doc/yaz-marcdump-man.xml | 49 ++++-------- include/yaz/marcdisp.h | 19 ++++- src/marc_read_line.c | 184 +++++++++++++++++++++++++++++++++++++++++++++- src/marcdisp.c | 25 ++++++- test/marccol1.u8.1.lst | 19 +++++ test/marccol1.u8.2.lst | 19 +++++ test/tstmarccol.sh | 4 +- test/tstmarciso.sh | 6 +- test/tstmarcxml.sh | 4 +- util/marcdump.c | 111 +++++++++++++++++++++------- 11 files changed, 373 insertions(+), 76 deletions(-) diff --git a/NEWS b/NEWS index d86bad8..02c112e 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +Implemented function yaz_marc_read_line which parses MARC line format +records. There is a wealth of formats out there. So far, this function +reads line records produced by yaz_marc_write_line. + +yaz-marcdump's options -x, -X, -I, -e have been replaced with the +more generic and easier to remember(!) options: -i format and -o format +which specifies input format and output format respectively - where +format is one of "marc", "marcxml", "line", "marcxchange". + Added 'check only' option for MARC utilities. Option -n for yaz-marcdump does not print anything except warnings for records. diff --git a/doc/yaz-marcdump-man.xml b/doc/yaz-marcdump-man.xml index 8b3daa1..ac6b685 100644 --- a/doc/yaz-marcdump-man.xml +++ b/doc/yaz-marcdump-man.xml @@ -8,7 +8,7 @@ %common; ]> - + YAZ @@ -27,10 +27,8 @@ yaz-marcdump - - - - + + @@ -60,8 +58,7 @@ By default, each record is written to standard output in a line format with newline for each field, $x for each subfield x. - The output format may be changed with options -X, - -e, -I. + The output format may be changed with option -o, yaz-marcdump can also be requested to perform @@ -73,38 +70,20 @@ - -x + -i format - Reads MARC records in MARCXML/MarcXchange format. Without - this option, yaz-marcdump reads records - in ISO2709 format. + Specifies input format. Must be one of + marcxml, marc (ISO2709), + line (line mode MARC). - -X + -o format - Writes MARC records in MARCXML. - This format is equivalent to YAZ_MARC_MARCXML in - yaz/marcdisp.h. - - - - - -e - - Writes MARC records in MarcXchange format. - This format is equivalent to YAZ_MARC_XCHANGE in - yaz/marcdisp.h. - - - - - -I - - Writes MARC records in ISO2709 format. - This format is equivalent to YAZ_MARC_ISO2709 in - yaz/marcdisp.h. + Specifies output format. Must be one of + marcxml, marc (ISO2709), + line (line mode MARC). @@ -155,13 +134,13 @@ MARC21/USMARC in UTF-8 encoding. Leader offset 9 is set to 'a'. Both input and output records are ISO2709 encoded. - yaz-marcdump -f MARC-8 -t UTF-8 -I -l 9=97 marc21.raw >marc21.utf8.raw + yaz-marcdump -f MARC-8 -t UTF-8 -o marc -l 9=97 marc21.raw >marc21.utf8.raw The same records may be converted to MARCXML instead in UTF-8: - yaz-marcdump -f MARC-8 -t UTF-8 -X marc21.raw >marcxml.xml + yaz-marcdump -f MARC-8 -t UTF-8 -o marcxml marc21.raw >marcxml.xml diff --git a/include/yaz/marcdisp.h b/include/yaz/marcdisp.h index 1b8e818..8805f71 100644 --- a/include/yaz/marcdisp.h +++ b/include/yaz/marcdisp.h @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* $Id: marcdisp.h,v 1.22 2006-12-15 12:37:17 adam Exp $ */ +/* $Id: marcdisp.h,v 1.23 2006-12-15 19:28:46 adam Exp $ */ /** * \file marcdisp.h @@ -130,6 +130,16 @@ YAZ_EXPORT void yaz_marc_modify_leader(yaz_marc_t mt, size_t off, /** \brief like atoi(3) except that it reads exactly len characters */ YAZ_EXPORT int atoi_n(const char *buf, int len); +/** \brief like atoi_n but checks for proper formatting + \param buf buffer to read values from + \param size size of buffer + \param val value of decimal number (if successful) + \retval 0 no value found (non-digits found) + \retval 1 value found and *val holds value +*/ +YAZ_EXPORT +int atoi_n_check(const char *buf, int size, int *val); + /** \brief MARC control char: record separator (29 Dec, 1D Hex) */ #define ISO2709_RS 035 /** \brief MARC control char: field separator (30 Dec, 1E Hex) */ @@ -334,6 +344,13 @@ void yaz_marc_reset(yaz_marc_t mt); YAZ_EXPORT int yaz_marc_get_debug(yaz_marc_t mt); +/** \brief convert MARC format type to format type(YAZ_MARC_..) + \param arg string + \returns -1 if arg is not a known format; YAZ_MARC_.. otherwise (OK) +*/ +YAZ_EXPORT +int yaz_marc_decode_formatstr(const char *arg); + YAZ_END_CDECL #endif diff --git a/src/marc_read_line.c b/src/marc_read_line.c index c05af1b..90a3521 100644 --- a/src/marc_read_line.c +++ b/src/marc_read_line.c @@ -2,12 +2,12 @@ * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: marc_read_line.c,v 1.1 2006-12-15 12:37:18 adam Exp $ + * $Id: marc_read_line.c,v 1.2 2006-12-15 19:28:47 adam Exp $ */ /** - * \file marc_read_iso2709.c - * \brief Implements reading of MARC as ISO2709 + * \file marc_read_line.c + * \brief Implements reading of MARC in line format */ #if HAVE_CONFIG_H @@ -18,6 +18,7 @@ #include #endif +#include #include #include #include @@ -26,14 +27,189 @@ #include #include +int yaz_gets(int (*getbyte)(void *client_data), + void (*ungetbyte)(int b, void *client_data), + void *client_data, + char *buf, size_t len) +{ + size_t sz = 0; + int ch = getbyte(client_data); + while (ch != '\0' && ch != '\r' && ch != '\n') + { + if (sz < len-1) + buf[sz++] = ch; + ch = getbyte(client_data); + } + if (ch == '\r') + { + ch = getbyte(client_data); + if (ch != '\n' && ch != '\0') + ungetbyte(ch, client_data); + } + else if (ch == '\n') + { + ch = getbyte(client_data); + if (ch != '\r' && ch != '\0') + ungetbyte(ch, client_data); + } + buf[sz] = '\0'; + if (sz) + return 1; + return 0; +} + int yaz_marc_read_line(yaz_marc_t mt, int (*getbyte)(void *client_data), void (*ungetbyte)(int b, void *client_data), void *client_data) { + int indicator_length; + int identifier_length; + int base_address; + int length_data_entry; + int length_starting; + int length_implementation; + int marker_ch = 0; + int marker_skip = 0; + int header_created = 0; + char line[4096]; + yaz_marc_reset(mt); - return -1; + while (yaz_gets(getbyte, ungetbyte, client_data, line, sizeof(line))) + { + int val; + size_t line_len = strlen(line); + /* see if have leader lines of the form: + 00366nam 22001698a 4500 + */ + if (line_len == 0) /* empty line indicates end of record */ + { + if (header_created) + break; + } + else if (line[0] == '$') /* indicates beginning/end of record */ + { + if (header_created) + break; + } + else if (line[0] == '(') /* annotation, skip it */ + ; + else if (line_len == 24 && atoi_n_check(line, 5, &val) && val >= 24) + { + if (header_created) + break; + yaz_marc_set_leader(mt, line, + &indicator_length, + &identifier_length, + &base_address, + &length_data_entry, + &length_starting, + &length_implementation); + header_created = 1; + } + else if (line_len > 5 && memcmp(line, " ", 4) == 0) + { /* continuation line */ + ; + } + else if (line_len > 5 && line[3] == ' ') + { + char tag[4]; + char *datafield_start = line+6; + marker_ch = 0; + marker_skip = 0; + + memcpy(tag, line, 3); + tag[3] = '\0'; + if (line_len >= 8) /* control - or datafield ? */ + { + if (*datafield_start == ' ') + datafield_start++; /* skip blank after indicator */ + + if (strchr("$_*", *datafield_start)) + { + marker_ch = *datafield_start; + if (datafield_start[2] == ' ') + marker_skip = 1; /* subfields has blank before data */ + } + } + if (!header_created) + { + const char *leader = "01000cam 2200265 i 4500"; + + yaz_marc_set_leader(mt, leader, + &indicator_length, + &identifier_length, + &base_address, + &length_data_entry, + &length_starting, + &length_implementation); + header_created = 1; + } + + if (marker_ch == 0) + { /* control field */ + yaz_marc_add_controlfield(mt, tag, line+4, strlen(line+4)); + } + else + { /* data field */ + const char *indicator = line+4; + int indicator_len = 2; + char *cp = datafield_start; + + yaz_marc_add_datafield(mt, tag, indicator, indicator_len); + for (;;) + { + char *next; + size_t len; + + assert(cp[0] == marker_ch); + cp++; + next = cp; + while ((next = strchr(next, marker_ch))) + { + if ((next[1] >= 'A' && next[1] <= 'Z') + ||(next[1] >= 'a' && next[1] <= 'z')) + { + if (!marker_skip) + break; + else if (next[2] == ' ') + break; + } + next++; + } + len = strlen(cp); + if (next) + len = next - cp - marker_skip; + + if (marker_skip) + { + /* remove ' ' after subfield marker */ + char *cp_blank = strchr(cp, ' '); + if (cp_blank) + { + len--; + while (cp_blank != cp) + { + cp_blank[0] = cp_blank[-1]; + cp_blank--; + } + cp++; + } + } + assert(len >= 0); + assert(len < 399); + yaz_marc_add_subfield(mt, cp, len); + if (!next) + break; + cp = next; + } + } + } + } + if (!header_created) + return -1; + return 0; } /* diff --git a/src/marcdisp.c b/src/marcdisp.c index 321cd72..54ad37b 100644 --- a/src/marcdisp.c +++ b/src/marcdisp.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: marcdisp.c,v 1.38 2006-12-15 12:37:18 adam Exp $ + * $Id: marcdisp.c,v 1.39 2006-12-15 19:28:47 adam Exp $ */ /** @@ -267,10 +267,12 @@ void yaz_marc_add_subfield(yaz_marc_t mt, } } -static int atoi_n_check(const char *buf, int size, int *val) +int atoi_n_check(const char *buf, int size, int *val) { - if (!isdigit(*(const unsigned char *) buf)) - return 0; + int i; + for (i = 0; i < size; i++) + if (!isdigit(i[(const unsigned char *) buf])) + return 0; *val = atoi_n(buf, size); return 1; } @@ -491,6 +493,7 @@ int yaz_marc_write_line(yaz_marc_t mt, WRBUF wr) wrbuf_printf(wr, "%s\n", n->u.leader); } } + wrbuf_puts(wr, "\n"); return 0; } @@ -927,6 +930,20 @@ static int marc_exec_leader(const char *leader_spec, char *leader, size_t size) return 0; } +int yaz_marc_decode_formatstr(const char *arg) +{ + int mode = -1; + if (!strcmp(arg, "marc")) + mode = YAZ_MARC_ISO2709; + if (!strcmp(arg, "marcxml")) + mode = YAZ_MARC_MARCXML; + if (!strcmp(arg, "marcxchange")) + mode = YAZ_MARC_XCHANGE; + if (!strcmp(arg, "line")) + mode = YAZ_MARC_LINE; + return mode; +} + /* * Local variables: * c-basic-offset: 4 diff --git a/test/marccol1.u8.1.lst b/test/marccol1.u8.1.lst index d8fe3e2..ec47cef 100644 --- a/test/marccol1.u8.1.lst +++ b/test/marccol1.u8.1.lst @@ -20,6 +20,7 @@ 880 0 $6 260-02/$1 $a [半田市] : $b 半田市, $c 昭和 43-<59> [1968-<1984> 880 4 $6 651-03/$1 $a 半田市 (Japan) 880 4 $6 651-04/$1 $a 半田市 (Japan) $x History $x Sources. + 00847nam a2200229 a 4500 001 75840215 /ACN/r86 003 DLC @@ -38,6 +39,7 @@ 880 00 $6 245-01/$1 $a 歷叢. 880 0 $6 260-02/$1 $a [高雄市] : $b 文化院 : $b 發行所 聖書 出版社, $c <民國63-66 [1974-1977 > 880 20 $6 710-03/$1 $a 高雄市 文化院. + 01020nam a2200277 a 4500 001 84226659 /ACN 003 DLC @@ -60,6 +62,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a 成都 : $b 四川 人民 出版社 : $b 四川省 新华 书店 发行, $c 1983. 880 0 $6 440-04/$1 $a 德育 丛书 + 01336cam a2200349 a 4500 001 84231405 003 DLC @@ -88,6 +91,7 @@ 880 24 $6 610-04/$1 $a 中国 共产党 $x Party work. 880 2 $6 710-05/$1 $a 辽宁 人氱 出版社. 987 $a PINYIN $b CStRLIN $c 20001212 $d c $e 1.0 + 00916nam a2200241 a 4500 001 85174785 /ACN 003 DLC @@ -107,6 +111,7 @@ 880 00 $6 245-01/$1 $a 河北 氱间 故事 选 / $c [插图 张 文学]. 880 $6 250-02/$1 $a 新1版. 880 0 $6 260-03/$1 $a 石家庄 : $b 花山 文艺 出版社 : $b 河北省 新華 書店 叱行, $c 1983. + 01171nam a2200325 a 4500 001 86116930 /ACN 003 DLC @@ -133,6 +138,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 合肥市 : $b 安徽 文艺 出版社 : $b 安徽省 新華 書店 发行, $c 1984. 880 0 $6 440-05/$1 $a 青年 文学 丛书 + 01437nam a2200301 a 4500 001 86117080 /ACN 003 DLC @@ -157,6 +163,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a 西安 : $b 陕西 秱学 技术 出版社 : $b 陕西省 新華 書店 叱行, $c 1985. 880 20 $6 710-04/$1 $a 国家 地震局 兰州 地震 研究所. + 01289cam a2200337 a 4500 001 86118651 /ACN/r88 003 DLC @@ -184,6 +191,7 @@ 880 $6 250-03/$1 $a 初版. 880 0 $6 260-04/$1 $a 台北市 : $b 名山 出版社, $c 氱國74 [1985] 880 10 $6 700-05/$1 $a 黃 釱仙. + 00995nam a2200289 a 4500 001 86118679 /ACN 003 DLC @@ -207,6 +215,7 @@ 880 $6 250-03/$1 $a 初版. 880 0 $6 260-04/$1 $a 台北市 : $b 皇冠 出版社, $c 民國74 [1985] 880 0 $6 440-05/$1 $a 皇冠 叢書 ; $v 第1143種 + 01365cam a2200361 a 4500 001 86119726 003 DLC @@ -236,6 +245,7 @@ 880 1 $6 700-04/$1 $a 周 宝珠. 880 1 $6 700-05/$1 $a 陈 振. 987 $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0 + 01069nam a2200289 a 4500 001 86122256 /ACN 003 DLC @@ -259,6 +269,7 @@ 880 10 $6 245-02/$1 $a 中国 现代 诗歌 论 / $c [骆 寒超]. 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a [南京市] : $b 江苏 人氱 出版社 : $b 江苏省 新華 書店 叱行, $c 1984. + 01194nam a2200325 a 4500 001 86124008 /ACN 003 DLC @@ -285,6 +296,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 乌鲁木齐市 : $b 新疆 人民 出版社 : $b 新疆 新華 書店 发行, $c 1985. 880 0 $6 440-05/$1 $a 祖国 大家庭 丛书 + 01192cam a2200313 a 4500 001 86124229 003 DLC @@ -310,6 +322,7 @@ 880 $6 260-04/$1 $a 北京 : $b 人民 文学 出版社 : $b 新华 书店 北京 发行所 发行, $c 1985. 880 0 $6 440-05/$1 $a 中国 小说 史料 丛书 987 $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0 + 01470cam a2200349 a 4500 001 86124531 /ACN/r93 003 DLC @@ -338,6 +351,7 @@ 880 $6 250-02/$1 $a 第1版. 880 $6 260-03/$1 $a 上海 : $b 上海 人氱 出版社 : $b 新華 書店 上海 叱行所 叱行, $c 1985. 880 20 $6 710-04/$1 $a 中共 上海 市委. $b 宣传部. + 01072nam a2200301 a 4500 001 86125160 /ACN 003 DLC @@ -362,6 +376,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 北京 : $b 北京 十月 文艺 出版社 : $b 新华 书店 北京 叱行所 叱行, $c 1985. 880 0 $6 440-05/$1 $a 红叶 诗丛 + 01248nam a2200301 a 4500 001 86125348 /ACN 003 DLC @@ -386,6 +401,7 @@ 880 0 $6 260-03/$1 $a [臺北縣 永和市] : $b 文海 出版社, $c 民國74 [1985] 880 1 $6 490-04/$1 $a 近代 中國 史料 叢刊 三編 : 第二輯 ; $v 20 880 0 $6 830-05/$1 $a 近代 中國 史料 叢刊 三編 ; $v 20. + 01116cam a2200325 a 4500 001 86125443 003 DLC @@ -412,6 +428,7 @@ 880 $6 250-03/$1 $a 初版. 880 $6 260-04/$1 $a 台北市 : $b 世界 書局, $c 氱國74 [1985] 987 $a PINYIN $b DLC $c 20020326 $d c + 01199nam a2200301 a 4500 001 86154542 /ACN/r86 003 DLC @@ -436,6 +453,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a [长春市] : $b 吉林 人民 出版社 : $b 吉林省 新华 书店 发行, $c 1985. 880 10 $6 700-04/$1 $a 虞 祖尧. + 00920nam a2200253 a 4500 001 86159478 /AK 003 DLC @@ -456,3 +474,4 @@ 880 10 $6 245-02/$1 $a 들어라, 딸들 아 : $b 김 동길 대표 에세이. 880 0 $6 260-03/$1 $a 서울 : $b 청년사, $c 1984 $g (1985 printing) 880 0 $6 440-04/$1 $a 우리 시대 의 대표 산문선 ; $v 1 + diff --git a/test/marccol1.u8.2.lst b/test/marccol1.u8.2.lst index dc0398f..557fdef 100644 --- a/test/marccol1.u8.2.lst +++ b/test/marccol1.u8.2.lst @@ -20,6 +20,7 @@ 880 0 $6 260-02/$1 $a [半田市] : $b 半田市, $c 昭和 43-<59> [1968-<1984> 880 4 $6 651-03/$1 $a 半田市 (Japan) 880 4 $6 651-04/$1 $a 半田市 (Japan) $x History $x Sources. + 00885nam a2200229 a 4500 001 75840215 /ACN/r86 003 DLC @@ -38,6 +39,7 @@ 880 00 $6 245-01/$1 $a 歷叢. 880 0 $6 260-02/$1 $a [高雄市] : $b 文化院 : $b 發行所 聖書 出版社, $c <民國63-66 [1974-1977 > 880 20 $6 710-03/$1 $a 高雄市 文化院. + 01054nam a2200277 a 4500 001 84226659 /ACN 003 DLC @@ -60,6 +62,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a 成都 : $b 四川 人民 出版社 : $b 四川省 新华 书店 发行, $c 1983. 880 0 $6 440-04/$1 $a 德育 丛书 + 01390cam a2200349 a 4500 001 84231405 003 DLC @@ -88,6 +91,7 @@ 880 24 $6 610-04/$1 $a 中国 共产党 $x Party work. 880 2 $6 710-05/$1 $a 辽宁 人氱 出版社. 987 $a PINYIN $b CStRLIN $c 20001212 $d c $e 1.0 + 00953nam a2200241 a 4500 001 85174785 /ACN 003 DLC @@ -107,6 +111,7 @@ 880 00 $6 245-01/$1 $a 河北 氱间 故事 选 / $c [插图 张 文学]. 880 $6 250-02/$1 $a 新1版. 880 0 $6 260-03/$1 $a 石家庄 : $b 花山 文艺 出版社 : $b 河北省 新華 書店 叱行, $c 1983. + 01219nam a2200325 a 4500 001 86116930 /ACN 003 DLC @@ -133,6 +138,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 合肥市 : $b 安徽 文艺 出版社 : $b 安徽省 新華 書店 发行, $c 1984. 880 0 $6 440-05/$1 $a 青年 文学 丛书 + 01502nam a2200301 a 4500 001 86117080 /ACN 003 DLC @@ -157,6 +163,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a 西安 : $b 陕西 学 技术 出版社 : $b 陕西省 新華 書店 叱行, $c 1985. 880 20 $6 710-04/$1 $a 国家 地震局 兰州 地震 研究所. + 01333cam a2200337 a 4500 001 86118651 /ACN/r88 003 DLC @@ -184,6 +191,7 @@ 880 $6 250-03/$1 $a 初版. 880 0 $6 260-04/$1 $a 台北市 : $b 名山 出版社, $c 氱國74 [1985] 880 10 $6 700-05/$1 $a 黃 釱仙. + 01051nam a2200289 a 4500 001 86118679 /ACN 003 DLC @@ -207,6 +215,7 @@ 880 $6 250-03/$1 $a 初版. 880 0 $6 260-04/$1 $a 台北市 : $b 皇冠 出版社, $c 民國74 [1985] 880 0 $6 440-05/$1 $a 皇冠 叢書 ; $v 第1143種 + 01437cam a2200361 a 4500 001 86119726 003 DLC @@ -236,6 +245,7 @@ 880 1 $6 700-04/$1 $a 周 宝珠. 880 1 $6 700-05/$1 $a 陈 振. 987 $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0 + 01114nam a2200289 a 4500 001 86122256 /ACN 003 DLC @@ -259,6 +269,7 @@ 880 10 $6 245-02/$1 $a 中国 现代 诗歌 论 / $c [骆 寒超]. 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a [南京市] : $b 江苏 人氱 出版社 : $b 江苏省 新華 書店 叱行, $c 1984. + 01244nam a2200325 a 4500 001 86124008 /ACN 003 DLC @@ -285,6 +296,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 乌鲁木齐市 : $b 新疆 人民 出版社 : $b 新疆 新華 書店 发行, $c 1985. 880 0 $6 440-05/$1 $a 祖国 大家庭 丛书 + 01252cam a2200313 a 4500 001 86124229 003 DLC @@ -310,6 +322,7 @@ 880 $6 260-04/$1 $a 北京 : $b 人民 文学 出版社 : $b 新华 书店 北京 发行所 发行, $c 1985. 880 0 $6 440-05/$1 $a 中国 小说 史料 丛书 987 $a PINYIN $b CStRLIN $c 20001214 $d c $e 1.0 + 01516cam a2200349 a 4500 001 86124531 /ACN/r93 003 DLC @@ -338,6 +351,7 @@ 880 $6 250-02/$1 $a 第1版. 880 $6 260-03/$1 $a 上海 : $b 上海 人氱 出版社 : $b 新華 書店 上海 叱行所 叱行, $c 1985. 880 20 $6 710-04/$1 $a 中共 上海 市委. $b 宣传部. + 01121nam a2200301 a 4500 001 86125160 /ACN 003 DLC @@ -362,6 +376,7 @@ 880 $6 250-03/$1 $a 第1版. 880 0 $6 260-04/$1 $a 北京 : $b 北京 十月 文艺 出版社 : $b 新华 书店 北京 叱行所 叱行, $c 1985. 880 0 $6 440-05/$1 $a 红叶 诗丛 + 01301nam a2200301 a 4500 001 86125348 /ACN 003 DLC @@ -386,6 +401,7 @@ 880 0 $6 260-03/$1 $a [臺北縣 永和市] : $b 文海 出版社, $c 民國74 [1985] 880 1 $6 490-04/$1 $a 近代 中國 史料 叢刊 三編 : 第二輯 ; $v 20 880 0 $6 830-05/$1 $a 近代 中國 史料 叢刊 三編 ; $v 20. + 01158cam a2200325 a 4500 001 86125443 003 DLC @@ -412,6 +428,7 @@ 880 $6 250-03/$1 $a 初版. 880 $6 260-04/$1 $a 台北市 : $b 世界 書局, $c 氱國74 [1985] 987 $a PINYIN $b DLC $c 20020326 $d c + 01247nam a2200301 a 4500 001 86154542 /ACN/r86 003 DLC @@ -436,6 +453,7 @@ 880 $6 250-02/$1 $a 第1版. 880 0 $6 260-03/$1 $a [长春市] : $b 吉林 人民 出版社 : $b 吉林省 新华 书店 发行, $c 1985. 880 10 $6 700-04/$1 $a 虞 祖尧. + 00951nam a2200253 a 4500 001 86159478 /AK 003 DLC @@ -456,3 +474,4 @@ 880 10 $6 245-02/$1 $a 들어라, 딸들 아 : $b 김 동길 대표 에세이. 880 0 $6 260-03/$1 $a 서울 : $b 청년사, $c 1984 $g (1985 printing) 880 0 $6 440-04/$1 $a 우리 시대 의 대표 산문선 ; $v 1 + diff --git a/test/tstmarccol.sh b/test/tstmarccol.sh index f201ae3..f7d1ce4 100755 --- a/test/tstmarccol.sh +++ b/test/tstmarccol.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: tstmarccol.sh,v 1.1 2006-08-28 12:34:42 adam Exp $ +# $Id: tstmarccol.sh,v 1.2 2006-12-15 19:28:47 adam Exp $ # Tests reading of a bunch of non-roman UTF-8 ISO2709 and see if # we can encode it in MARC-8 # @@ -32,7 +32,7 @@ for f in ${srcdir}/marccol?.u8.marc; do fi filem=`echo $fb | sed 's/u8/m8/'`.marc - ../util/yaz-marcdump -I -f utf8 -t marc8 $f >$filem + ../util/yaz-marcdump -o marc -f utf8 -t marc8 $f >$filem DIFF=${fb}.2.lst.diff NEW=${fb}.2.lst.new diff --git a/test/tstmarciso.sh b/test/tstmarciso.sh index 0ff5022..e4d56ea 100755 --- a/test/tstmarciso.sh +++ b/test/tstmarciso.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: tstmarciso.sh,v 1.3 2006-08-28 12:34:42 adam Exp $ +# $Id: tstmarciso.sh,v 1.4 2006-12-15 19:28:47 adam Exp $ # Tests reading of ISO2709 and checks that we get identical MARCXML # # Reads marc?.marc files , Generates marc?.xml files @@ -11,7 +11,7 @@ for f in ${srcdir}/marc?.marc; do NEW=${fb}.new.xml OLD=${srcdir}/${fb}.xml DIFF=`basename ${f}`.diff - ../util/yaz-marcdump -f `cat $CHR` -t utf-8 -X $f > $NEW + ../util/yaz-marcdump -f `cat $CHR` -t utf-8 -o marcxml $f > $NEW if test $? != "0"; then echo "$f: yaz-marcdump returned error" ecode=1 @@ -25,7 +25,7 @@ for f in ${srcdir}/marc?.marc; do fi else echo "$f: Making test result $OLD for the first time" - if test -x /usr/bin/xmllint; then + if test -i marcxml /usr/bin/xmllint; then if xmllint --noout $NEW >out 2>stderr; then echo "$f: $NEW is well-formed" mv $NEW $OLD diff --git a/test/tstmarcxml.sh b/test/tstmarcxml.sh index b18a3a8..6093628 100755 --- a/test/tstmarcxml.sh +++ b/test/tstmarcxml.sh @@ -1,5 +1,5 @@ #!/bin/sh -# $Id: tstmarcxml.sh,v 1.3 2006-08-28 12:34:42 adam Exp $ +# $Id: tstmarcxml.sh,v 1.4 2006-12-15 19:28:47 adam Exp $ # Tests reading of MARCXML and checks that we get identical ISO2709 output. # # Reads marc?.xml files , Generates marc?.xml.marc files @@ -14,7 +14,7 @@ for f in ${srcdir}/marc?.xml; do NEW=`basename ${f}`.new.marc OLD=${f}.marc DIFF=`basename ${f}`.diff - ../util/yaz-marcdump -f utf-8 -t utf-8 -x -I $f > $NEW + ../util/yaz-marcdump -f utf-8 -t utf-8 -i marcxml -o marc $f > $NEW if test $? != "0"; then echo "Failed decode of $f" ecode=1 diff --git a/util/marcdump.c b/util/marcdump.c index 040a51b..254c2d4 100644 --- a/util/marcdump.c +++ b/util/marcdump.c @@ -2,7 +2,7 @@ * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: marcdump.c,v 1.44 2006-12-07 11:08:05 adam Exp $ + * $Id: marcdump.c,v 1.45 2006-12-15 19:28:48 adam Exp $ */ #define _FILE_OFFSET_BITS 64 @@ -50,11 +50,52 @@ static char *prog; static void usage(const char *prog) { - fprintf (stderr, "Usage: %s [-c cfile] [-f from] [-t to] [-x] [-X] [-e] " - "[-I] [-n] [-l pos=value] [-v] [-C chunk] [-s splitfname] file...\n", + fprintf (stderr, "Usage: %s [-c cfile] [-f from] [-t to] " + "[-i format] [-o format] " + "[-n] [-l pos=value] [-v] [-C chunk] [-s splitfname] file...\n", prog); } +static int getbyte_stream(void *client_data) +{ + FILE *f = (FILE*) client_data; + + int c = fgetc(f); + if (c == EOF) + return 0; + return c; +} + +static void ungetbyte_stream(int c, void *client_data) +{ + FILE *f = (FILE*) client_data; + + if (c == 0) + c = EOF; + ungetc(c, f); +} + +static void marcdump_read_line(yaz_marc_t mt, const char *fname) +{ + FILE *inf = fopen(fname, "rb"); + if (!inf) + { + fprintf (stderr, "%s: cannot open %s:%s\n", + prog, fname, strerror (errno)); + exit(1); + } + + while (yaz_marc_read_line(mt, getbyte_stream, + ungetbyte_stream, inf) == 0) + { + WRBUF wrbuf = wrbuf_alloc(); + yaz_marc_write_mode(mt, wrbuf); + fputs(wrbuf_buf(wrbuf), stdout); + wrbuf_free(wrbuf, 1); + } + fclose(inf); +} + #if YAZ_HAVE_XML2 static void marcdump_read_xml(yaz_marc_t mt, const char *fname) { @@ -84,7 +125,7 @@ static void marcdump_read_xml(yaz_marc_t mt, const char *fname) #endif static void dump(const char *fname, const char *from, const char *to, - int read_xml, int xml, + int input_format, int output_format, int print_offset, const char *split_fname, int split_chunk, int verbose, FILE *cfile, const char *leader_spec) { @@ -109,18 +150,20 @@ static void dump(const char *fname, const char *from, const char *to, } yaz_marc_iconv(mt, cd); } - yaz_marc_xml(mt, xml); + yaz_marc_xml(mt, output_format); yaz_marc_debug(mt, verbose); - if (read_xml) + if (input_format == YAZ_MARC_MARCXML || input_format == YAZ_MARC_XCHANGE) { #if YAZ_HAVE_XML2 marcdump_read_xml(mt, fname); -#else - return; #endif } - else + else if (input_format == YAZ_MARC_LINE) + { + marcdump_read_line(mt, fname); + } + else if (input_format == YAZ_MARC_ISO2709) { FILE *inf = fopen(fname, "rb"); int num = 1; @@ -265,10 +308,10 @@ int main (int argc, char **argv) char *arg; int verbose = 0; int no = 0; - int xml = 0; + int output_format = YAZ_MARC_LINE; FILE *cfile = 0; char *from = 0, *to = 0; - int read_xml = 0; + int input_format = YAZ_MARC_ISO2709; int split_chunk = 1; const char *split_fname = 0; const char *leader_spec = 0; @@ -283,11 +326,27 @@ int main (int argc, char **argv) #endif prog = *argv; - while ((r = options("C:npvc:xOeXIf:t:s:l:", argv, argc, &arg)) != -2) + while ((r = options("i:o:C:npvc:xOeXIf:t:s:l:", argv, argc, &arg)) != -2) { no++; switch (r) { + case 'i': + input_format = yaz_marc_decode_formatstr(arg); + if (input_format == -1) + { + fprintf(stderr, "%s: bad input format: %s\n", prog, arg); + exit(1); + } + break; + case 'o': + output_format = yaz_marc_decode_formatstr(arg); + if (output_format == -1) + { + fprintf(stderr, "%s: bad output format: %s\n", prog, arg); + exit(1); + } + break; case 'l': leader_spec = arg; break; @@ -303,13 +362,9 @@ int main (int argc, char **argv) cfile = fopen(arg, "w"); break; case 'x': -#if YAZ_HAVE_XML2 - read_xml = 1; -#else - fprintf(stderr, "%s: -x not supported." - " YAZ not compiled with Libxml2 support\n", prog); - exit(3); -#endif + fprintf(stderr, "%s: -x no longer supported. " + "Use -i marcxml instead\n", prog); + exit(1); break; case 'O': fprintf(stderr, "%s: OAI MARC no longer supported." @@ -317,16 +372,22 @@ int main (int argc, char **argv) exit(1); break; case 'e': - xml = YAZ_MARC_XCHANGE; + fprintf(stderr, "%s: -e no longer supported. " + "Use -o marcxchange instead\n", prog); + exit(1); break; case 'X': - xml = YAZ_MARC_MARCXML; + fprintf(stderr, "%s: -X no longer supported. " + "Use -o marcxml instead\n", prog); + exit(1); break; case 'I': - xml = YAZ_MARC_ISO2709; + fprintf(stderr, "%s: -I no longer supported. " + "Use -o marc instead\n", prog); + exit(1); break; case 'n': - xml = YAZ_MARC_CHECK; + output_format = YAZ_MARC_CHECK; break; case 'p': print_offset = 1; @@ -338,7 +399,7 @@ int main (int argc, char **argv) split_chunk = atoi(arg); break; case 0: - dump(arg, from, to, read_xml, xml, + dump(arg, from, to, input_format, output_format, print_offset, split_fname, split_chunk, verbose, cfile, leader_spec); break; @@ -347,7 +408,7 @@ int main (int argc, char **argv) break; default: usage(prog); - exit (1); + exit(1); } } if (cfile) -- 1.7.10.4