SRW, CQL, 2003
authorAdam Dickmeiss <adam@indexdata.dk>
Mon, 6 Jan 2003 08:20:26 +0000 (08:20 +0000)
committerAdam Dickmeiss <adam@indexdata.dk>
Mon, 6 Jan 2003 08:20:26 +0000 (08:20 +0000)
124 files changed:
CHANGELOG
LICENSE
Makefile.am
README
client/admin.c
client/admin.h
client/client.c
client/tabcomplete.c
comstack/tcpip.c
comstack/unix.c
configure.in
cql/.cvsignore [new file with mode: 0644]
cql/Makefile.am [new file with mode: 0644]
cql/cql.y [new file with mode: 0644]
cql/cql2pqf.c [new file with mode: 0644]
cql/cql2xcql.c [new file with mode: 0644]
cql/cqlstdio.c [new file with mode: 0644]
cql/cqlstring.c [new file with mode: 0644]
cql/cqltransform.c [new file with mode: 0644]
cql/cqlutil.c [new file with mode: 0644]
cql/lexer.c [new file with mode: 0644]
cql/xcqlutil.c [new file with mode: 0644]
debian/rules
etc/MARC21slim2DC.xsl [new file with mode: 0644]
etc/MARC21slim2MODS.xsl [new file with mode: 0644]
etc/MARC21slim2RDFDC.xsl [new file with mode: 0644]
etc/MARC21slimUtils.xsl [new file with mode: 0644]
etc/Makefile.am [new file with mode: 0644]
etc/maps.xml [new file with mode: 0644]
etc/pqf.properties [new file with mode: 0644]
include/yaz/Makefile.am
include/yaz/backend.h
include/yaz/cql.h [new file with mode: 0644]
include/yaz/log.h
include/yaz/logrpn.h
include/yaz/marcdisp.h
include/yaz/nmem.h
include/yaz/odr.h
include/yaz/oid.h
include/yaz/pquery.h
include/yaz/proto.h
include/yaz/prt-ext.h
include/yaz/srw-util.h [new file with mode: 0644]
include/yaz/tpath.h
include/yaz/unix.h
include/yaz/wrbuf.h
include/yaz/yaz-iconv.h
include/yaz/yaz-util.h
include/yaz/zoom.h
lib/Makefile.am
odr/ber_any.c
odr/ber_bit.c
odr/ber_bool.c
odr/ber_int.c
odr/ber_len.c
odr/ber_null.c
odr/ber_oct.c
odr/ber_oid.c
odr/ber_tag.c
odr/dumpber.c
odr/odr-priv.h
odr/odr.c
odr/odr_any.c
odr/odr_bit.c
odr/odr_bool.c
odr/odr_choice.c
odr/odr_cons.c
odr/odr_enum.c
odr/odr_int.c
odr/odr_mem.c
odr/odr_null.c
odr/odr_oct.c
odr/odr_oid.c
odr/odr_seq.c
odr/odr_tag.c
odr/odr_use.c
odr/odr_util.c
server/seshigh.c
server/session.h
server/statserv.c
srw/.cvsignore [new file with mode: 0644]
srw/Makefile.am [new file with mode: 0644]
srw/srw-diag.c [new file with mode: 0644]
srw/srw-namespace.c [new file with mode: 0644]
srw/srw-server.c [new file with mode: 0644]
srw/srw-xcql.c [new file with mode: 0644]
srw/srw-xslt.c [new file with mode: 0644]
srw/zing.h [new file with mode: 0644]
srwapps/.cvsignore [new file with mode: 0644]
srwapps/Makefile.am [new file with mode: 0644]
srwapps/srw-client.c [new file with mode: 0644]
srwapps/srw-gateway.c [new file with mode: 0644]
util/Makefile.am
util/atoin.c
util/log.c
util/marcdisp.c
util/marcdump.c
util/nmem.c
util/oid.c
util/siconv.c
util/siconvtst.c
util/tpath.c
util/wrbuf.c
util/xmalloc.c
win/LICENSE.txt
win/yaz.rc
yaz-config.in
z39.50/prt-ext.c
z39.50/z3950v3.asn
zoom/Makefile.am
zoom/zoomsh.c
ztest/read-grs.c
ztest/ztest.c
zutil/Makefile.am
zutil/diagbib1.c
zutil/logrpn.c
zutil/otherinfo.c
zutil/pquery.c
zutil/yaz-ccl.c
zutil/z3950oid.c
zutil/zget.c
zutil/zoom-c.c
zutil/zoom-opt.c
zutil/zoom-p.h

index 917ac97..0bbd392 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,20 @@
 Possible compatibility problems with earlier versions marked with '*'.
 
---- 1.9.3 2002/MM/DD
+--- 1.9.3 2003/MM/DD
+
+Support for SRW 1.0. This is an optional feature and requires
+gSOAP to operate. Enable it by specifying --with-gsoap for
+configure. SRW stuff is located in sub directory srw.
+Example applications are located in srwapps. 
+
+Z39.50 Query Type-104 added - to facilitate CQL within Z39.50.
+
+CQL support. Source is directory 'cql'. CQL is supported in ZOOM
+(both SRW and Z39.50) and the YAZ client (Z39.50 only).
+
+ZOOM connections are SRW based if host/port is specified
+as http. e.g.  z = ZOOM_connection_new("http://myserver");
+ZOOM_query may be of type CQL, e.g. ZOOM_query_cql(q, "dc.title=x");
 
 CCL proximity operators !n, %n converts to PQF @prox 0 n 1 2 k 2
 and @prox 0 n 0 1 k 2 respectively, meaning: exlusion=false,
diff --git a/LICENSE b/LICENSE
index 6235cb1..db81ecc 100644 (file)
--- a/LICENSE
+++ b/LICENSE
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
index 260c395..4c1ea35 100644 (file)
@@ -1,8 +1,10 @@
-## $Id: Makefile.am,v 1.17 2002-10-22 12:51:18 adam Exp $
+## Copyright (C) 1994-2003, Index Data
+## All rights reserved.
+## $Id: Makefile.am,v 1.18 2003-01-06 08:20:26 adam Exp $
 
 AUTOMAKE_OPTIONS = foreign 
 
-SUBDIRS = util odr comstack z39.50 ill zutil ccl server include lib client ztest zoom doc
+SUBDIRS = util odr comstack z39.50 ill srw zutil ccl cql server include lib client ztest zoom srwapps doc etc
 
 aclocaldir=$(datadir)/aclocal
 
diff --git a/README b/README
index bc2f56b..889f14a 100644 (file)
--- a/README
+++ b/README
@@ -1,11 +1,11 @@
-YAZ toolkit - $Id: README,v 1.41 2002-08-27 13:30:18 adam Exp $
+YAZ toolkit - $Id: README,v 1.42 2003-01-06 08:20:26 adam Exp $
 
-Copyright (C) 1995-2002, Index Data ApS.
+Copyright (C) 1995-2003, Index Data ApS.
 See the file LICENSE for details.
 
 The primary output of the source here is the YAZ library, which
 contains support functions for implementing the server or client
-role of Z39.50.
+role of Z39.50 and SRW.
 
 Windows programmers: refer to the file windows.txt which describes how
 to build the software using Microsoft Visual C++.
@@ -52,11 +52,19 @@ zoom     An implementation of Mike Taylors Z39.50 Object Oriented
          in C this may be good start. You'll find example programs in 
          this directory too.
 
-server   This is the implementation of the server frontend. It
+server   This is the implementation of the Z39.50 server frontend. It
         provides event-handling and server managament functions,
         and calls the backend primitives (best documentation of these
         is in the file include/yaz/backend.h).
 
+ccl      CCL parser.
+
+cql      CQL parser.
+
+srw      SRW support (based on gSOAP).
+
+srwapps  SRW applicaions, most notably a SRW-to-Z39.50 gateway.
+
 client   A demonstration client for testing the protocol. It's bug'n
          ugly. But, it supports many features.
 
index b94e968..4f96bce 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: admin.c,v 1.14 2002-09-24 08:05:41 adam Exp $
+ * $Id: admin.c,v 1.15 2003-01-06 08:20:26 adam Exp $
  */
 
 #include <stdio.h>
index efa8483..f2d49fb 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: admin.h,v 1.4 2002-09-17 11:07:30 adam Exp $
+ * $Id: admin.h,v 1.5 2003-01-06 08:20:26 adam Exp $
  */
 
 int cmd_adm_reindex(char* arg);
index 3db21cf..639feca 100644 (file)
@@ -1,8 +1,8 @@
 /* 
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: client.c,v 1.177 2002-12-16 13:30:41 adam Exp $
+ * $Id: client.c,v 1.178 2003-01-06 08:20:26 adam Exp $
  */
 
 #include <stdio.h>
@@ -97,7 +97,8 @@ static int auto_reconnect = 0;
 typedef enum {
     QueryType_Prefix,
     QueryType_CCL,
-    QueryType_CCL2RPN
+    QueryType_CCL2RPN,
+    QueryType_CQL
 } QueryType;
 
 static QueryType queryType = QueryType_Prefix;
@@ -144,6 +145,7 @@ const char* query_type_as_string(QueryType q)
     case QueryType_Prefix: return "prefix (RPN sent to server)";
     case QueryType_CCL: return "CCL (CCL sent to server) ";
     case QueryType_CCL2RPN: return "CCL -> RPN (RPN sent to server)";
+    case QueryType_CQL: return "CQL (CQL sent to server)";
     default: 
         return "unknown Query type internal yaz-client error";
     }
@@ -875,6 +877,7 @@ static int send_searchRequest(char *arg)
     Z_RPNQuery *RPNquery;
     Odr_oct ccl_query;
     YAZ_PQF_Parser pqf_parser;
+    Z_External *ext;
 
     if (queryType == QueryType_CCL2RPN)
     {
@@ -961,6 +964,16 @@ static int send_searchRequest(char *arg)
         query.u.type_1 = RPNquery;
         ccl_rpn_delete (rpn);
         break;
+    case QueryType_CQL:
+        query.which = Z_Query_type_104;
+        ext = odr_malloc(out, sizeof(*ext));
+        ext->direct_reference = odr_getoidbystr(out, "1.2.840.10003.16.2");
+        ext->indirect_reference = 0;
+        ext->descriptor = 0;
+        ext->which = Z_External_CQL;
+        ext->u.cql = odr_strdup(out, arg);
+        query.u.type_104 =  ext;
+        break;
     default:
         printf ("Unsupported query type\n");
         return 0;
@@ -2225,12 +2238,15 @@ int cmd_querytype (char *arg)
         queryType = QueryType_Prefix;
     else if (!strcmp (arg, "ccl2rpn") || !strcmp (arg, "cclrpn"))
         queryType = QueryType_CCL2RPN;
+    else if (!strcmp(arg, "cql"))
+        queryType = QueryType_CQL;        
     else
     {
         printf ("Querytype must be one of:\n");
         printf (" prefix         - Prefix query\n");
         printf (" ccl            - CCL query\n");
         printf (" ccl2rpn        - CCL query converted to RPN\n");
+        printf (" cql            - CQL\n");
         return 0;
     }
     return 1;
index ad48f3b..c1eeba4 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2002, Index Data
  * See the file LICENSE for details.
  *
- * $Id: tabcomplete.c,v 1.8 2002-09-24 08:05:41 adam Exp $
+ * $Id: tabcomplete.c,v 1.9 2003-01-06 08:20:26 adam Exp $
  */
 
 #include <string.h>
 
 extern char** curret_global_list;
 
-/* *****************************************************************************
+/* ***************************************************************************
  *
- * generic compleater 
+ * generic completer 
  * 
- * *****************************************************************************/
+ * ***************************************************************************/
 
 char* complete_from_list(char* completions[], const char *text, int state)
 {      
@@ -44,11 +44,11 @@ char* complete_from_list(char* completions[], const char *text, int state)
 }
 
 
-/* *****************************************************************************
+/* ***************************************************************************
  * 
  * code for getting a list of valid strings from the oid subsystem
  * 
- * *****************************************************************************/
+ * ***************************************************************************/
    
 
 typedef struct {
@@ -59,8 +59,8 @@ typedef struct {
 } oid_callback_t;
 
 /*!
-  This is the call back function given to oid_trav... it updates the list of pointers into the oid
-  owned data 
+  This is the call back function given to oid_trav... it updates the list
+  of pointers into the oid owned data 
 */
 
 void oid_loader(struct oident* oid, void* data_)
@@ -91,15 +91,15 @@ char** build_list_for_oclass(oid_class oclass) {
        return data.values;        
 }
 
-/* *****************************************************************************
+/* ***************************************************************************
  * 
- * the compleater functions 
+ * the completer functions 
  * 
- * *****************************************************************************/
+ * ***************************************************************************/
 
 char* complete_querytype(const char *text, int state)
 {
-    char* querytypes[] = {"ccl2rpn","prefix","cclrpn","ccl",0};
+    char* querytypes[] = {"ccl2rpn","prefix","cclrpn","ccl","cql", 0};
     return complete_from_list(querytypes,text,state);  
 }
 
index 9e0e0cf..8649a3f 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: tcpip.c,v 1.52 2002-12-19 14:04:22 adam Exp $
+ * $Id: tcpip.c,v 1.53 2003-01-06 08:20:27 adam Exp $
  */
 
 #include <stdio.h>
index 235c9b1..908ab7e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: unix.c,v 1.8 2002-12-15 21:22:58 adam Exp $
+ * $Id: unix.c,v 1.9 2003-01-06 08:20:27 adam Exp $
  * UNIX socket COMSTACK. By Morten Bøgeskov.
  */
 #ifndef WIN32
index 41cf8d1..50fcf89 100644 (file)
@@ -1,6 +1,6 @@
-dnl YAZ Toolkit, Index Data 1994-2002
+dnl YAZ Toolkit, Index Data 1994-2003
 dnl See the file LICENSE for details.
-dnl $Id: configure.in,v 1.99 2002-12-16 13:13:53 adam Exp $
+dnl $Id: configure.in,v 1.100 2003-01-06 08:20:26 adam Exp $
 AC_INIT(include/yaz/yaz-version.h)
 AM_INIT_AUTOMAKE(yaz, 1.9.2)
 dnl
@@ -9,6 +9,8 @@ AC_SUBST(YAZ_CONF_CFLAGS)
 dnl ------ Checking programs
 AC_PROG_CC
 AC_PROG_CPP
+AC_CHECK_PROGS(YACC, 'bison -y')
+test -z "$YACC" && AC_MSG_WARN([GNU bison not found])
 AC_PROG_INSTALL
 AM_DISABLE_SHARED
 AM_PROG_LIBTOOL
@@ -173,7 +175,7 @@ if test "$with_iconv" != "no"; then
        ])
 fi
 dnl ------ various functions
-AC_CHECK_FUNCS(vsnprintf gettimeofday poll)
+AC_CHECK_FUNCS(vsnprintf gettimeofday poll strerror_r)
 if test "$ac_cv_func_poll" = "yes"; then
         AC_CHECK_HEADERS(sys/poll.h)
 fi
@@ -306,6 +308,58 @@ if test "$enable_threads" = "yes" -a "$HAVETHREADS" = "0"; then
 fi
 AM_CONDITIONAL(ISTHR, test $HAVETHREADS = "1")
 dnl
+dnl ----- gSOAP
+AC_SUBST(GSOAP_LIB)
+AC_SUBST(GSOAP_INCLUDE)
+AC_SUBST(GSOAP_PREFIX)
+gsoapdir=NONE
+AC_ARG_WITH(gsoap, [  --with-gsoap[=PREFIX]   Use gSOAP in PREFIX/{lib,include}],[gsoapdir=$withval])
+if test "x$gsoapdir" = "xNONE"; then
+       for d in /usr /usr/local; do
+               if test -f $d/include/stdsoap2.h; then
+                       gsoapdir=$d
+               fi
+       done
+fi
+AC_MSG_CHECKING(for gSOAP prefix)
+GSOAP_PREFIX=$gsoapdir
+if test -x $gsoapdir/bin/soapcpp2; then
+       AC_MSG_RESULT($gsoapdir)
+       if test "$gsoapdir" != "/usr"; then
+               GSOAP_LIB="-L$gsoapdir/lib -lgsoap"
+               GSOAP_INCLUDE=-I$gsoapdir/include
+       fi
+        AC_DEFINE(HAVE_GSOAP)
+        usesrw=1
+else
+       AC_MSG_RESULT(Not found)
+        usesrw=0
+fi
+AM_CONDITIONAL(SRW, test $usesrw = "1")
+dnl
+dnl ----- XML/XSLT
+AC_SUBST(XSLT_LIB)
+AC_SUBST(XSLT_CFLAGS)
+xsltdir=NONE
+AC_ARG_WITH(xslt, [  --with-xslt[=PREFIX]    Use libxslt in PREFIX/{lib,include}],[xsltdir=$withval])
+if test "x$xsltdir" = "xNONE"; then
+       for d in /usr /usr/local; do
+               if test -x $d/bin/xslt-config; then
+                       xsltdir=$d
+               fi
+       done
+fi
+AC_MSG_CHECKING(for XSLT)
+if test -x $xsltdir/bin/xslt-config; then
+       XSLT_LIB=`$xsltdir/bin/xslt-config --libs`
+       XSLT_CFLAGS=`$xsltdir/bin/xslt-config --cflags`
+       XSLT_VER=`$xsltdir/bin/xslt-config --version`
+       AC_MSG_RESULT($XSLT_VER)
+       AC_DEFINE(HAVE_XSLT)
+else
+       AC_MSG_RESULT(Not found)
+fi
+dnl
 dnl ------ Memory debugging
 AC_ARG_ENABLE(memdebug, [  --enable-memdebug       enable memory debugging],[enable_memdebug=$enableval],[enable_memdebug=none])
 if test "$enable_memdebug" = "yes"; then
@@ -328,13 +382,16 @@ yaz.spec
 util/Makefile
 odr/Makefile
 z39.50/Makefile
+srw/Makefile
 ill/Makefile
 zutil/Makefile
 comstack/Makefile
 ccl/Makefile
+cql/Makefile
 server/Makefile
 include/Makefile
 include/yaz/Makefile
+srwapps/Makefile
 lib/Makefile
 client/Makefile
 ztest/Makefile
@@ -345,5 +402,6 @@ doc/yazhtml.dsl
 doc/yazphp.dsl
 doc/yazprint.dsl
 doc/tkl.xsl
+etc/Makefile
 yaz-config
 ],[sed s%yaz_echo_source=yes%yaz_echo_source=no%g < yaz-config > lib/yaz-config && chmod +x yaz-config lib/yaz-config])
diff --git a/cql/.cvsignore b/cql/.cvsignore
new file mode 100644 (file)
index 0000000..f995e38
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
+cql.c
diff --git a/cql/Makefile.am b/cql/Makefile.am
new file mode 100644 (file)
index 0000000..c0c875e
--- /dev/null
@@ -0,0 +1,17 @@
+# $Id: Makefile.am,v 1.1 2003-01-06 08:20:27 adam Exp $
+AM_YFLAGS=-p cql_
+
+AM_CPPFLAGS=-I$(top_srcdir)/include
+
+noinst_LTLIBRARIES = libcql.la
+noinst_PROGRAMS = cql2pqf cql2xcql
+
+EXTRA_DIST=lexer.c
+
+libcql_la_SOURCES=cql.y cqlstdio.c cqltransform.c \
+ cqlutil.c xcqlutil.c cqlstring.c cql.h
+
+cql2pqf_SOURCES = cql2pqf.c
+cql2xcql_SOURCES = cql2xcql.c
+
+LDADD=libcql.la 
diff --git a/cql/cql.y b/cql/cql.y
new file mode 100644 (file)
index 0000000..4a816aa
--- /dev/null
+++ b/cql/cql.y
@@ -0,0 +1,267 @@
+/* $Id: cql.y,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+
+ bison parser for CQL grammar.
+*/
+%{
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <yaz/cql.h>
+    
+    typedef struct {
+        struct cql_node *rel;
+        struct cql_node *cql;
+        char buf[80];
+        size_t len;
+        size_t max;
+    } token;        
+
+    struct cql_parser {
+        int (*getbyte)(void *client_data);
+        void (*ungetbyte)(int b, void *client_data);
+        void *client_data;
+        int last_error;
+        int last_pos;
+        struct cql_node *top;
+    };
+
+#define YYSTYPE token
+    
+#define YYPARSE_PARAM parm
+#define YYLEX_PARAM parm
+    
+    int yylex(YYSTYPE *lval, void *vp);
+    int yyerror(char *s);
+%}
+
+%pure_parser
+%token TERM AND OR NOT PROX EXACT ALL ANY GE LE NE SCR
+%expect 8
+
+%%
+
+top: { 
+    $$.rel = cql_node_mk_sc("srw.serverChoice", "scr", 0);
+    ((CQL_parser) parm)->top = 0;
+} cqlQuery1 {
+    cql_node_destroy($$.rel);
+    ((CQL_parser) parm)->top = $2.cql; 
+}
+;
+
+cqlQuery1: cqlQuery
+| cqlQuery error {
+    cql_node_destroy($1.cql);
+    $$.cql = 0;
+}
+;
+
+cqlQuery: 
+  searchClause
+|
+  cqlQuery boolean { 
+      $$.rel = $0.rel; 
+  } searchClause {
+      struct cql_node *cn = cql_node_mk_boolean($2.buf);
+      
+      cn->u.bool.modifiers = $2.rel;
+      cn->u.bool.left = $1.cql;
+      cn->u.bool.right = $4.cql;
+
+      $$.cql = cn;
+  }
+;
+
+searchClause: 
+  '(' { 
+      $$.rel = $0.rel;
+      
+  } cqlQuery ')' {
+      $$.cql = $3.cql;
+  }
+|
+  searchTerm {
+      struct cql_node *st = cql_node_dup ($0.rel);
+      st->u.st.term = strdup($1.buf);
+      $$.cql = st;
+  }
+| 
+  index relation {
+      $$.rel = $2.rel;
+      $$.rel->u.st.index = strdup($1.buf);
+  } searchClause {
+      $$.cql = $4.cql;
+      cql_node_destroy($$.rel);
+  }
+| '>' searchTerm '=' searchTerm {
+      $$.rel = $0.rel;
+  } cqlQuery {
+    $$.cql = cql_node_prefix($6.cql, $2.buf, $4.buf);
+  }
+| '>' searchTerm {
+      $$.rel = $0.rel;
+  } cqlQuery {
+    $$.cql = cql_node_prefix($4.cql, 0, $2.buf);
+   }
+;
+
+boolean: 
+  AND | OR | NOT | PROX proxqualifiers {
+      $$ = $1;
+      $$.rel = $2.rel;
+  }
+  ;
+
+proxqualifiers: 
+  Prelation { 
+      $$.rel = cql_node_mk_proxargs ($1.buf, 0, 0, 0);
+  }
+|
+  PrelationO Pdistance {
+      $$.rel = cql_node_mk_proxargs ($1.buf, $2.buf, 0, 0);
+  }
+|
+  PrelationO PdistanceO Punit {
+      $$.rel = cql_node_mk_proxargs ($1.buf, $2.buf, $3.buf, 0);
+  }
+|
+  PrelationO PdistanceO PunitO Pordering {
+      $$.rel = cql_node_mk_proxargs ($1.buf, $2.buf, $3.buf, $4.buf);
+  }
+|
+{ $$.rel = 0; }
+;
+
+Punit: '/' searchTerm { 
+      $$ = $2;
+   }
+;
+
+PunitO: '/' searchTerm {
+      $$ = $2;
+   } 
+| 
+'/' { $$.buf[0] = 0; }
+;
+Prelation: '/' baseRelation {
+    $$ = $2;
+}
+;
+PrelationO: '/' baseRelation {
+    $$ = $2;
+}
+| '/' { $$.buf[0] = 0; }
+;
+Pdistance: '/' searchTerm { 
+    $$ = $2;
+}
+;
+
+PdistanceO: '/' searchTerm {
+    $$ = $2;
+}
+| '/' { $$.buf[0] = 0; }
+;
+Pordering: '/' searchTerm { 
+    $$ = $2;
+}
+;
+
+relation: baseRelation modifiers {
+    struct cql_node *st = cql_node_mk_sc(/* index */ 0, 
+                                         /* relation */ $1.buf, 
+                                         /* term */ 0);
+
+    st->u.st.modifiers = $2.cql;
+    $$.rel = st;
+}
+;
+
+modifiers: '/' searchTerm modifiers
+{ 
+    struct cql_node *mod = cql_node_mk_mod(0, $2.buf);
+
+    mod->u.mod.next = $3.cql;
+    $$.cql = mod;
+}
+|  
+{ 
+    $$.cql = 0;
+}
+;
+
+baseRelation: 
+  '=' 
+| '>' 
+| '<'
+| GE
+| LE
+| NE
+| EXACT 
+| ALL
+| ANY
+| SCR
+;
+
+index: 
+  searchTerm;
+
+searchTerm:
+  TERM
+| AND
+| OR
+| NOT
+| EXACT
+| ALL
+| ANY
+| PROX
+;
+
+%%
+
+int yyerror(char *s)
+{
+    return 0;
+}
+
+#include "lexer.c"
+
+
+int cql_parser_stream(CQL_parser cp,
+                      int (*getbyte)(void *client_data),
+                      void (*ungetbyte)(int b, void *client_data),
+                      void *client_data)
+{
+    cp->getbyte = getbyte;
+    cp->ungetbyte = ungetbyte;
+    cp->client_data = client_data;
+    cql_parse(cp);
+    if (cp->top)
+        return 0;
+    return -1;
+}
+
+CQL_parser cql_parser_create(void)
+{
+    CQL_parser cp = malloc (sizeof(*cp));
+
+    return cp;
+}
+
+void cql_parser_destroy(CQL_parser cp)
+{
+    cql_node_destroy(cp->top);
+    free (cp);
+}
+
+struct cql_node *cql_parser_result(CQL_parser cp)
+{
+    return cp->top;
+}
diff --git a/cql/cql2pqf.c b/cql/cql2pqf.c
new file mode 100644 (file)
index 0000000..e5a3731
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: cql2pqf.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <yaz/cql.h>
+
+int main(int argc, char **argv)
+{
+    cql_transform_t ct;
+    int r;
+    CQL_parser cp = cql_parser_create();
+
+    if (argc < 2)
+    {
+        fprintf (stderr, "usage\n cqltransform <properties> [<query>]\n");
+        exit (1);
+    }
+    ct = cql_transform_open_fname(argv[1]);
+    if (!ct)
+    {
+        fprintf (stderr, "failed to read properties %s\n", argv[1]);
+        exit (1);
+    }
+    if (argc == 3)
+        r = cql_parser_string(cp, argv[2]);
+    else
+        r = cql_parser_stdio(cp, stdin);
+    if (r)
+        fprintf (stderr, "Syntax error\n");
+    else
+    {
+        r = cql_transform_FILE(ct, cql_parser_result(cp), stdout);
+       printf("\n");
+        if (r)
+        {
+            const char *addinfo;
+            cql_transform_error(ct, &addinfo);
+            printf ("Transform error %d %s\n", r, addinfo ? addinfo : "");
+        }
+    }
+    cql_transform_close(ct);
+    cql_parser_destroy(cp);
+    return 0;
+}
diff --git a/cql/cql2xcql.c b/cql/cql2xcql.c
new file mode 100644 (file)
index 0000000..b2db2e5
--- /dev/null
@@ -0,0 +1,28 @@
+/* $Id: cql2xcql.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <stdio.h>
+
+#include <yaz/cql.h>
+
+int main(int argc, char **argv)
+{
+    int r;
+    CQL_parser cp = cql_parser_create();
+    if (argc == 2)
+        r = cql_parser_string(cp, argv[1]);
+    else
+        r = cql_parser_stdio(cp, stdin);
+    if (r)
+        fprintf (stderr, "Syntax error\n");
+    else
+        cql_to_xml_stdio(cql_parser_result(cp), stdout);
+    cql_parser_destroy(cp);
+    return 0;
+}
diff --git a/cql/cqlstdio.c b/cql/cqlstdio.c
new file mode 100644 (file)
index 0000000..7846f0d
--- /dev/null
@@ -0,0 +1,36 @@
+/* $Id: cqlstdio.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <yaz/cql.h>
+
+int getbyte_stream(void *client_data)
+{
+    FILE *f = (FILE*) client_data;
+
+    int c = fgetc(f);
+    if (c == EOF)
+        return 0;
+    return c;
+}
+
+void ungetbyte_stream (int c, void *client_data)
+{
+    FILE *f = (FILE*) client_data;
+
+    if (c == 0)
+        c = EOF;
+    ungetc(c, f);
+}
+
+int cql_parser_stdio(CQL_parser cp, FILE *f)
+{
+    return cql_parser_stream(cp, getbyte_stream, ungetbyte_stream, f);
+}
+
+
diff --git a/cql/cqlstring.c b/cql/cqlstring.c
new file mode 100644 (file)
index 0000000..b04dd5b
--- /dev/null
@@ -0,0 +1,40 @@
+/* $Id: cqlstring.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE for details.
+*/
+#include <yaz/cql.h>
+
+struct cql_buf_info {
+    const char *str;
+    int off;
+};
+
+int getbuf(void *vp)
+{
+    struct cql_buf_info *bi = vp;
+    if (bi->str[bi->off] == 0)
+        return 0;
+    return bi->str[bi->off++];
+}
+
+void ungetbuf(int b, void *vp)
+{
+    struct cql_buf_info *bi = vp;
+    if (b)
+        (bi->off--);
+}
+
+int cql_parser_string(CQL_parser cp, const char *str)
+{
+    struct cql_buf_info b;
+
+    b.str = str;
+    b.off = 0;
+    
+    return cql_parser_stream(cp, getbuf, ungetbuf, &b);
+}
+
diff --git a/cql/cqltransform.c b/cql/cqltransform.c
new file mode 100644 (file)
index 0000000..d5e3ddb
--- /dev/null
@@ -0,0 +1,462 @@
+/* $Id: cqltransform.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <yaz/cql.h>
+
+struct cql_prop_entry {
+    char *pattern;
+    char *value;
+    struct cql_prop_entry *next;
+};
+
+struct cql_transform_t_ {
+    struct cql_prop_entry *entry;
+    int error;
+    char *addinfo;
+};
+
+cql_transform_t cql_transform_open_FILE(FILE *f)
+{
+    char line[1024];
+    cql_transform_t ct = malloc (sizeof(*ct));
+    struct cql_prop_entry **pp = &ct->entry;
+
+    ct->error = 0;
+    ct->addinfo = 0;
+    while (fgets(line, sizeof(line)-1, f))
+    {
+        const char *cp_value_start;
+        const char *cp_value_end;
+        const char *cp_pattern_end;
+        const char *cp = line;
+        while (*cp && !strchr(" \t=\r\n#", *cp))
+            cp++;
+        cp_pattern_end = cp;
+        if (cp == line)
+            continue;
+        while (*cp && strchr(" \t\r\n", *cp))
+            cp++;
+        if (*cp != '=')
+            continue;
+        cp++;
+        while (*cp && strchr(" \t\r\n", *cp))
+            cp++;
+        cp_value_start = cp;
+        if (!(cp_value_end = strchr(cp, '#')))
+            cp_value_end = strlen(line) + line;
+
+        if (cp_value_end != cp_value_start &&
+            strchr(" \t\r\n", cp_value_end[-1]))
+            cp_value_end--;
+        *pp = malloc (sizeof(**pp));
+        (*pp)->pattern = malloc (cp_pattern_end - line + 1);
+        memcpy ((*pp)->pattern, line, cp_pattern_end - line);
+        (*pp)->pattern[cp_pattern_end-line] = 0;
+
+        (*pp)->value = malloc (cp_value_end - cp_value_start + 1);
+        if (cp_value_start != cp_value_end)
+            memcpy ((*pp)->value, cp_value_start, cp_value_end-cp_value_start);
+        (*pp)->value[cp_value_end - cp_value_start] = 0;
+        pp = &(*pp)->next;
+    }
+    *pp = 0;
+    return ct;
+}
+
+void cql_transform_close(cql_transform_t ct)
+{
+    struct cql_prop_entry *pe;
+    if (!ct)
+        return;
+    pe = ct->entry;
+    while (pe)
+    {
+        struct cql_prop_entry *pe_next = pe->next;
+        free (pe->pattern);
+        free (pe->value);
+        free (pe);
+        pe = pe_next;
+    }
+    if (ct->addinfo)
+        free (ct->addinfo);
+    free (ct);
+}
+
+cql_transform_t cql_transform_open_fname(const char *fname)
+{
+    cql_transform_t ct;
+    FILE *f = fopen(fname, "r");
+    if (!f)
+        return 0;
+    ct = cql_transform_open_FILE(f);
+    fclose(f);
+    return ct;
+}
+
+static const char *cql_lookup_property(cql_transform_t ct,
+                                       const char *pat1, const char *pat2)
+{
+    char pattern[80];
+    struct cql_prop_entry *e;
+
+    if (pat2)
+        sprintf (pattern, "%.39s%.39s", pat1, pat2);
+    else
+        sprintf (pattern, "%.39s", pat1);
+    for (e = ct->entry; e; e = e->next)
+    {
+        if (!strcmp(e->pattern, pattern))
+            return e->value;
+    }
+    return 0;
+}
+
+static const char *cql_lookup_value(cql_transform_t ct,
+                                    const char *prefix,
+                                    const char *value)
+{
+    struct cql_prop_entry *e;
+    int len = strlen(prefix);
+
+    for (e = ct->entry; e; e = e->next)
+    {
+        if (!memcmp(e->pattern, prefix, len) && !strcmp(e->value, value))
+            return e->pattern + len;
+    }
+    return 0;
+}
+
+
+int cql_pr_attr(cql_transform_t ct, const char *category,
+                const char *val,
+                const char *default_val,
+                void (*pr)(const char *buf, void *client_data),
+                void *client_data,
+                int errcode)
+{
+    const char *res;
+    res = cql_lookup_property(ct, category, val ? val : default_val);
+    if (!res)
+        res = cql_lookup_property(ct, category, "*");
+    if (res)
+    {
+        char buf[64];
+
+        const char *cp0 = res, *cp1;
+        while ((cp1 = strchr(cp0, '=')))
+        {
+            while (*cp1 && *cp1 != ' ')
+                cp1++;
+            if (cp1 - cp0 >= sizeof(buf))
+                break;
+            memcpy (buf, cp0, cp1 - cp0);
+            buf[cp1-cp0] = 0;
+            (*pr)("@attr ", client_data);
+            (*pr)(buf, client_data);
+            (*pr)(" ", client_data);
+            cp0 = cp1;
+            while (*cp0 == ' ')
+                cp0++;
+        }
+        return 1;
+    }
+    /* error ... */
+    if (errcode && !ct->error)
+    {
+        ct->error = errcode;
+        ct->addinfo = strdup(val);
+    }
+    return 0;
+}
+
+void emit_term(cql_transform_t ct,
+               const char *term, int length,
+               void (*pr)(const char *buf, void *client_data),
+               void *client_data)
+{
+    int i;
+    if (length > 0)
+    {
+        if (length > 1 && term[0] == '^' && term[length-1] == '^')
+        {
+            cql_pr_attr(ct, "position.", "firstAndLast", 0,
+                        pr, client_data, 32);
+            term++;
+            length -= 2;
+        }
+        else if (term[0] == '^')
+        {
+            cql_pr_attr(ct, "position.", "first", 0,
+                        pr, client_data, 32);
+            term++;
+        }
+        else if (term[length-1] == '^')
+        {
+            cql_pr_attr(ct, "position.", "last", 0,
+                        pr, client_data, 32);
+            length--;
+        }
+        else
+        {
+            cql_pr_attr(ct, "position.", "any", 0,
+                        pr, client_data, 32);
+        }
+    }
+    (*pr)("\"", client_data);
+    for (i = 0; i<length; i++)
+    {
+        char buf[2];
+        buf[0] = term[i];
+        buf[1] = 0;
+        (*pr)(buf, client_data);
+    }
+    (*pr)("\" ", client_data);
+}
+
+void emit_wordlist(cql_transform_t ct,
+                   struct cql_node *cn,
+                   void (*pr)(const char *buf, void *client_data),
+                   void *client_data,
+                   const char *op)
+{
+    const char *cp0 = cn->u.st.term;
+    const char *cp1;
+    const char *last_term = 0;
+    int last_length = 0;
+    while(cp0)
+    {
+        while (*cp0 == ' ')
+            cp0++;
+        cp1 = strchr(cp0, ' ');
+        if (last_term)
+        {
+            (*pr)("@", client_data);
+            (*pr)(op, client_data);
+            (*pr)(" ", client_data);
+            emit_term(ct, last_term, last_length, pr, client_data);
+        }
+        last_term = cp0;
+        if (cp1)
+            last_length = cp1 - cp0;
+        else
+            last_length = strlen(cp0);
+        cp0 = cp1;
+    }
+    if (last_term)
+        emit_term(ct, last_term, last_length, pr, client_data);
+}
+
+
+static const char *cql_get_ns(cql_transform_t ct,
+                              struct cql_node *cn,
+                              struct cql_node **prefix_ar, int prefix_level,
+                              const char **n_prefix,
+                              const char **n_suffix)
+{
+    int i;
+    const char *ns = 0;
+    char prefix[32];
+    const char *cp = cn->u.st.index;
+    const char *cp_dot = strchr(cp, '.');
+
+    /* strz current prefix (empty if not given) */
+    if (cp_dot && cp_dot-cp < sizeof(prefix))
+    {
+        memcpy (prefix, cp, cp_dot - cp);
+        prefix[cp_dot - cp] = 0;
+    }
+    else
+        *prefix = 0;
+
+    /* 2. lookup in prefix_ar. and return NS */
+    for (i = prefix_level; !ns && --i >= 0; )
+    {
+        struct cql_node *cn_prefix = prefix_ar[i];
+        for (; cn_prefix; cn_prefix = cn_prefix->u.mod.next)
+        {
+            if (*prefix && cn_prefix->u.mod.name &&
+                !strcmp(prefix, cn_prefix->u.mod.name))
+            {
+                ns = cn_prefix->u.mod.value;
+                break;
+            }
+            else if (!*prefix && !cn_prefix->u.mod.name)
+            {
+                ns = cn_prefix->u.mod.value;
+                break;
+            }
+        }
+    }
+    if (!ns)
+    {
+        if (!ct->error)
+        {
+            ct->error = 15;
+            ct->addinfo = strdup(prefix);
+        }
+        return 0;
+    }
+    /* 3. lookup in set.NS for new prefix */
+    *n_prefix = cql_lookup_value(ct, "set.", ns);
+    if (!*n_prefix)
+    {
+        if (!ct->error)
+        {
+            ct->error = 15;
+            ct->addinfo = strdup(ns);
+        }
+        return 0;
+    }
+    /* 4. lookup qualifier.prefix. */
+    
+    cp = cn->u.st.index;
+    cp_dot = strchr(cp, '.');
+    
+    *n_suffix = cp_dot ? cp_dot+1 : cp;
+    return ns;
+}
+
+void cql_transform_r(cql_transform_t ct,
+                     struct cql_node *cn,
+                     void (*pr)(const char *buf, void *client_data),
+                     void *client_data,
+                     struct cql_node **prefix_ar, int prefix_level)
+{
+    const char *ns, *n_prefix, *n_suffix;
+
+    if (!cn)
+        return;
+    switch (cn->which)
+    {
+    case CQL_NODE_ST:
+        if (cn->u.st.prefixes && prefix_level < 20)
+            prefix_ar[prefix_level++] = cn->u.st.prefixes;
+        ns = cql_get_ns(ct, cn, prefix_ar, prefix_level, &n_prefix, &n_suffix);
+        if (ns)
+        {
+            char n_full[64];
+            sprintf (n_full, "%.20s.%.40s", n_prefix, n_suffix);
+        
+            if (!strcmp(ns, "http://www.loc.gov/zing/cql/srw-indexes/v1.0/")
+                && !strcmp(n_suffix, "resultSet"))
+            {
+                (*pr)("@set \"", client_data);
+                (*pr)(cn->u.st.term, client_data);
+                (*pr)("\" ", client_data);
+                return ;
+            }
+            cql_pr_attr(ct, "qualifier.", n_full, "srw.serverChoice",
+                        pr, client_data, 16);
+        }
+
+        if (cn->u.st.relation && !strcmp(cn->u.st.relation, "="))
+            cql_pr_attr(ct, "relation.", "eq", "scr",
+                        pr, client_data, 19);
+        else
+            cql_pr_attr(ct, "relation.", cn->u.st.relation, "eq",
+                        pr, client_data, 19);
+        if (cn->u.st.modifiers)
+        {
+            struct cql_node *mod = cn->u.st.modifiers;
+            for (; mod; mod = mod->u.mod.next)
+            {
+                cql_pr_attr(ct, "relationModifier.", mod->u.mod.value, 0,
+                            pr, client_data, 20);
+            }
+        }
+        cql_pr_attr(ct, "structure.", cn->u.st.relation, 0,
+                    pr, client_data, 24);
+        if (cn->u.st.relation && !strcmp(cn->u.st.relation, "all"))
+        {
+            emit_wordlist(ct, cn, pr, client_data, "and");
+        }
+        else if (cn->u.st.relation && !strcmp(cn->u.st.relation, "any"))
+        {
+            emit_wordlist(ct, cn, pr, client_data, "or");
+        }
+        else
+        {
+            emit_term(ct, cn->u.st.term, strlen(cn->u.st.term),
+                      pr, client_data);
+        }
+        break;
+    case CQL_NODE_BOOL:
+        if (cn->u.bool.prefixes && prefix_level < 20)
+            prefix_ar[prefix_level++] = cn->u.bool.prefixes;
+        (*pr)("@", client_data);
+        (*pr)(cn->u.bool.value, client_data);
+        (*pr)(" ", client_data);
+
+        cql_transform_r(ct, cn->u.bool.left, pr, client_data,
+                        prefix_ar, prefix_level);
+        cql_transform_r(ct, cn->u.bool.right, pr, client_data,
+                        prefix_ar, prefix_level);
+    }
+}
+
+int cql_transform(cql_transform_t ct,
+                  struct cql_node *cn,
+                  void (*pr)(const char *buf, void *client_data),
+                  void *client_data)
+{
+    struct cql_node *prefix_ar[20], **pp;
+    struct cql_prop_entry *e;
+
+    ct->error = 0;
+    if (ct->addinfo)
+        free (ct->addinfo);
+    ct->addinfo = 0;
+
+    prefix_ar[0] = 0;
+    pp = &prefix_ar[0];
+    for (e = ct->entry; e ; e = e->next)
+    {
+        if (!memcmp(e->pattern, "set.", 4))
+        {
+            *pp = cql_node_mk_mod(e->pattern+4, e->value);
+            pp = &(*pp)->u.mod.next;
+        }
+        else if (!strcmp(e->pattern, "set"))
+        {
+            *pp = cql_node_mk_mod(0, e->value);
+            pp = &(*pp)->u.mod.next;
+        }
+    }
+    cql_transform_r (ct, cn, pr, client_data, prefix_ar, 1);
+    return ct->error;
+}
+
+
+int cql_transform_FILE(cql_transform_t ct, struct cql_node *cn, FILE *f)
+{
+    return cql_transform(ct, cn, cql_fputs, f);
+}
+
+int cql_transform_buf(cql_transform_t ct, struct cql_node *cn,
+                      char *out, int max)
+{
+    struct cql_buf_write_info info;
+    int r;
+
+    info.off = 0;
+    info.max = max;
+    info.buf = out;
+    r = cql_transform(ct, cn, cql_buf_write_handler, &info);
+    if (info.off >= 0)
+        info.buf[info.off] = '\0';
+    return r;
+}
+
+int cql_transform_error(cql_transform_t ct, const char **addinfo)
+{
+    *addinfo = ct->addinfo;
+    return ct->error;
+}
diff --git a/cql/cqlutil.c b/cql/cqlutil.c
new file mode 100644 (file)
index 0000000..6207d19
--- /dev/null
@@ -0,0 +1,177 @@
+/* $Id: cqlutil.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <yaz/cql.h>
+
+void cql_fputs(const char *buf, void *client_data)
+{
+    FILE *f = client_data;
+    fputs(buf, f);
+}
+
+struct cql_node *cql_node_dup (struct cql_node *cp)
+{
+    struct cql_node *cn;
+
+    if (!cp)
+        return 0;
+    switch (cp->which)
+    {
+    case CQL_NODE_ST:
+        cn = cql_node_mk_sc(cp->u.st.index,
+                            cp->u.st.relation,
+                            cp->u.st.term);
+        cn->u.st.modifiers = cql_node_dup(cp->u.st.modifiers);
+        cn->u.st.prefixes = cql_node_dup(cp->u.st.prefixes);
+        break;
+    case CQL_NODE_MOD:
+        cn = cql_node_mk_mod(cp->u.mod.name,
+                             cp->u.mod.value);
+        cn->u.mod.next = cql_node_dup(cp->u.mod.next);
+        break;
+    case CQL_NODE_BOOL:
+        cn = cql_node_mk_boolean(cp->u.bool.value);
+        cn->u.bool.left = cql_node_dup(cp->u.bool.left);
+        cn->u.bool.right = cql_node_dup(cp->u.bool.right);
+        cn->u.bool.prefixes = cql_node_dup(cp->u.bool.prefixes);
+    }
+    return cn;
+}
+
+struct cql_node *cql_node_mk_sc(const char *index,
+                                const char *relation,
+                                const char *term)
+{
+    struct cql_node *p = malloc(sizeof(*p));
+    p->which = CQL_NODE_ST;
+    p->u.st.index = 0;
+    if (index)
+        p->u.st.index = strdup(index);
+    p->u.st.term = 0;
+    if (term)
+        p->u.st.term = strdup(term);
+    p->u.st.relation = 0;
+    if (relation)
+        p->u.st.relation = strdup(relation);
+    p->u.st.modifiers = 0;
+    p->u.st.prefixes = 0;
+    return p;
+}
+
+struct cql_node *cql_node_mk_mod(const char *name,
+                                 const char *value)
+{
+    struct cql_node *p = malloc(sizeof(*p));
+    p->which = CQL_NODE_MOD;
+
+    p->u.mod.name = 0;
+    if (name)
+        p->u.mod.name = strdup(name);
+    p->u.mod.value = 0;
+    if (value)
+        p->u.mod.value = strdup(value);
+    p->u.mod.next = 0;
+    return p;
+}
+
+struct cql_node *cql_node_mk_boolean(const char *op)
+{
+    struct cql_node *p = malloc(sizeof(*p));
+    p->which = CQL_NODE_BOOL;
+    p->u.bool.value = 0;
+    if (op)
+        p->u.bool.value = strdup(op);
+    p->u.bool.left = 0;
+    p->u.bool.right = 0;
+    p->u.bool.modifiers = 0;
+    p->u.bool.prefixes = 0;
+    return p;
+}
+
+struct cql_node *cql_node_prefix(struct cql_node *n, const char *prefix,
+                                 const char *uri)
+{
+    struct cql_node **cpp = 0;
+    if (n->which == CQL_NODE_ST)
+    {
+        cpp = &n->u.st.prefixes;
+    }
+    else if (n->which == CQL_NODE_BOOL)
+    {
+        cpp = &n->u.bool.prefixes;
+    }
+    if (cpp)
+    {
+        struct cql_node *cp = cql_node_mk_mod(prefix, uri);
+        cp->u.mod.next = *cpp;
+        *cpp = cp;
+    }
+    return n;
+}
+
+struct cql_node *cql_node_mk_proxargs(const char *relation,
+                                      const char *distance,
+                                      const char *unit,
+                                      const char *ordering)
+{
+    struct cql_node *m = 0, *m1;
+
+    if (ordering && *ordering)
+        m = cql_node_mk_mod("ordering", ordering);
+    if (unit && *unit)
+    {
+        m1 = cql_node_mk_mod("unit", unit);
+        m1->u.mod.next = m;
+        m = m1;
+    }
+    if (distance && *distance)
+    {
+        m1 = cql_node_mk_mod("distance", distance);
+        m1->u.mod.next = m;
+        m = m1;
+    }
+    if (relation && *relation)
+    {
+        m1 = cql_node_mk_mod("relation", relation);
+        m1->u.mod.next = m;
+        m = m1;
+    }
+    return m;
+}
+
+void cql_node_destroy(struct cql_node *cn)
+{
+    if (!cn)
+        return;
+    switch (cn->which)
+    {
+    case CQL_NODE_ST:
+        free (cn->u.st.index);
+        free (cn->u.st.relation);
+        free (cn->u.st.term);
+        cql_node_destroy(cn->u.st.modifiers);
+        cql_node_destroy(cn->u.st.prefixes);
+        break;
+    case CQL_NODE_MOD:
+        free (cn->u.mod.name);
+        free (cn->u.mod.value);
+        cql_node_destroy(cn->u.mod.next);
+        break;
+    case CQL_NODE_BOOL:
+        free (cn->u.bool.value);
+        cql_node_destroy(cn->u.bool.left);
+        cql_node_destroy(cn->u.bool.right);
+        cql_node_destroy(cn->u.bool.prefixes);
+    }
+    free (cn);
+}
+
diff --git a/cql/lexer.c b/cql/lexer.c
new file mode 100644 (file)
index 0000000..8a26522
--- /dev/null
@@ -0,0 +1,108 @@
+/* $Id: lexer.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+/*
+ * bison lexer for CQL.
+ */
+
+int yylex(YYSTYPE *lval, void *vp)
+{
+    CQL_parser cp = (CQL_parser) vp;
+    int c;
+    do
+    {
+        c = cp->getbyte(cp->client_data);
+        if (c == 0)
+            return 0;
+        if (c == '\n')
+            return 0;
+    } while (isspace(c));
+    lval->rel = 0;
+    lval->len = 0;
+    if (strchr("()=></", c))
+    {
+        int c1;
+        lval->buf[lval->len++] = c;
+        if (c == '>')
+        {
+            c1 = cp->getbyte(cp->client_data);
+            if (c1 == '=')
+            {
+                lval->buf[lval->len++] = c1;
+                lval->buf[lval->len] = 0;
+                return GE;
+            }
+            else
+                cp->ungetbyte(c1, cp->client_data);
+        }
+        else if (c == '<')
+        {
+            c1 = cp->getbyte(cp->client_data);
+            if (c1 == '=')
+            {
+                lval->buf[lval->len++] = c1;
+                lval->buf[lval->len] = 0;
+                return LE;
+            }
+            else if (c1 == '>')
+            {
+                lval->buf[lval->len++] = c1;
+                lval->buf[lval->len] = 0;
+                return NE;
+            }
+            else
+                cp->ungetbyte(c1, cp->client_data);
+        }
+        lval->buf[lval->len] = 0;
+        return c;
+    }
+    if (c == '"')
+    {
+        while ((c = cp->getbyte(cp->client_data)) != EOF && c != '"')
+        {
+            if (c == '\\')
+                c = cp->getbyte(cp->client_data);
+            lval->buf[lval->len++] = c;
+        }
+        lval->buf[lval->len] = 0;
+    }
+    else
+    {
+        lval->buf[lval->len++] = c;
+        while ((c = cp->getbyte(cp->client_data)) != 0 &&
+               !strchr(" \n()=<>/", c))
+        {
+            if (c == '\\')
+                c = cp->getbyte(cp->client_data);
+            lval->buf[lval->len++] = c;
+        }
+        lval->buf[lval->len] = 0;
+#if YYDEBUG
+        printf ("got %s\n", lval->buf);
+#endif
+        if (c != 0)
+            cp->ungetbyte(c, cp->client_data);
+        if (!strcmp(lval->buf, "and"))
+            return AND;
+        if (!strcmp(lval->buf, "or"))
+            return OR;
+        if (!strcmp(lval->buf, "not"))
+            return NOT;
+        if (!strcmp(lval->buf, "exact"))
+            return EXACT;
+        if (!strcmp(lval->buf, "all"))
+            return ALL;
+        if (!strncmp(lval->buf, "prox", 4))
+            return PROX;
+        if (!strcmp(lval->buf, "any"))
+            return ANY;
+        if (!strcmp(lval->buf, "scr"))
+            return SCR;
+    }
+    return TERM;
+}
diff --git a/cql/xcqlutil.c b/cql/xcqlutil.c
new file mode 100644 (file)
index 0000000..9294a02
--- /dev/null
@@ -0,0 +1,210 @@
+/* $Id: xcqlutil.c,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <yaz/cql.h>
+
+static void pr_n(const char *buf, 
+                void (*pr)(const char *buf, void *client_data),
+                void *client_data, int n)
+{
+    int i;
+    for (i = 0; i<n; i++)
+        (*pr)(" ", client_data);
+    (*pr)(buf, client_data);
+}
+
+static void pr_cdata(const char *buf,
+                     void (*pr)(const char *buf, void *client_data),
+                     void *client_data)
+{
+    const char *src = buf;
+    char bf[2];
+    while (*src)
+    {
+        switch(*src)
+        {
+        case '&':
+            (*pr)("&amp;", client_data);
+            break;
+        case '<':
+            (*pr)("&lt;", client_data);
+            break;
+        case '>':
+            (*pr)("&gt;", client_data);
+            break;
+        default:
+            bf[0] = *src;
+            bf[1] = 0;
+            (*pr)(bf, client_data);
+        }
+        src++;
+    }
+}
+                    
+static void prefixes(struct cql_node *cn,
+                     void (*pr)(const char *buf, void *client_data),
+                     void *client_data, int level)
+{
+    if (cn)
+    {
+        pr_n("<prefixes>\n", pr, client_data, level);
+        for (; cn; cn = cn->u.mod.next)
+        {
+            pr_n("<prefix>\n", pr, client_data, level+2);
+            if (cn->u.mod.name)
+            {
+                pr_n("<name>", pr, client_data, level+4);
+                pr_cdata(cn->u.mod.name, pr, client_data);
+                pr_n("</name>\n", pr, client_data, 0);
+            }
+            if (cn->u.mod.value)
+            {
+                pr_n("<identifier>", pr, client_data, level+4);
+                pr_cdata(cn->u.mod.value, pr, client_data);
+                pr_n("</identifier>\n", pr, client_data, 0);
+            }
+            pr_n("</prefix>\n", pr, client_data, level+2);
+        }
+        pr_n("</prefixes>\n", pr, client_data, level);
+    }
+}
+                     
+static void cql_to_xml_r(struct cql_node *cn,
+                         void (*pr)(const char *buf, void *client_data),
+                         void *client_data, int level)
+{
+    if (!cn)
+        return;
+    switch (cn->which)
+    {
+    case CQL_NODE_ST:
+        pr_n("<searchClause>\n", pr, client_data, level);
+        prefixes(cn->u.st.prefixes, pr, client_data, level+2);
+        if (cn->u.st.index)
+        {
+            pr_n("<index>", pr, client_data, level+2);
+            pr_cdata(cn->u.st.index, pr, client_data);
+            pr_n("</index>\n", pr, client_data, 0);
+        }
+        if (cn->u.st.relation)
+        {
+            struct cql_node *m = cn->u.st.modifiers;
+            pr_n("<relation>\n", pr, client_data, level+2);
+            pr_n("<value>", pr, client_data, level+4);
+            pr_cdata(cn->u.st.relation, pr, client_data);
+            pr_n("</value>\n", pr, client_data, 0);
+            if (m)
+            {
+                pr_n("<modifiers>\n", pr, client_data, level+4);
+                for (; m; m = m->u.mod.next)
+                {
+                    pr_n("<modifier><value>", pr, client_data, level+6);
+                    pr_cdata(m->u.mod.value, pr, client_data);
+                    pr_n("</value></modifier>\n", pr, client_data, 0);
+                }
+                pr_n("</modifiers>\n", pr, client_data, level+4);
+            }
+            pr_n("</relation>\n", pr, client_data, level+2);
+        }
+        if (cn->u.st.term)
+        {
+            pr_n("<term>", pr, client_data, level+2);
+            pr_cdata(cn->u.st.term, pr, client_data);
+            pr_n("</term>\n", pr, client_data, 0);
+        }
+        pr_n("</searchClause>\n", pr, client_data, level);
+        break;
+    case CQL_NODE_BOOL:
+        pr_n("<triple>\n", pr, client_data, level);
+        prefixes(cn->u.st.prefixes, pr, client_data, level+2);
+        if (cn->u.bool.value)
+        {
+            struct cql_node *m = cn->u.bool.modifiers;
+            pr_n("<boolean>\n", pr, client_data, level+2);
+
+            pr_n("<value>", pr, client_data, level+4);
+            pr_cdata(cn->u.bool.value, pr, client_data);
+            pr_n("</value>\n", pr, client_data, 0);
+
+            if (m)
+            {
+                pr_n("<modifiers>\n", pr, client_data, level+4);
+                for (; m; m = m->u.mod.next)
+                {
+                    pr_n("<modifier><type>", pr, client_data, level+6);
+                    pr_cdata(m->u.mod.name, pr, client_data);
+                    pr_n("</type>", pr, client_data, 0);
+                    if (m->u.mod.value)
+                    {
+                        pr_n("<value>", pr, client_data, 0);
+                        pr_cdata(m->u.mod.value, pr, client_data);
+                        pr_n("</value>", pr, client_data, 0);
+                    }
+                    pr_n("</modifier>\n", pr, client_data, 0);
+                }
+                pr_n("</modifiers>\n", pr, client_data, level+4);
+            }
+            pr_n("</boolean>\n", pr, client_data, level+2);
+        }
+        if (cn->u.bool.left)
+        {
+            printf ("%*s<leftOperand>\n", level+2, "");
+            cql_to_xml_r(cn->u.bool.left, pr, client_data, level+4);
+            printf ("%*s</leftOperand>\n", level+2, "");
+        }
+        if (cn->u.bool.right)
+        {
+            printf ("%*s<rightOperand>\n", level+2, "");
+            cql_to_xml_r(cn->u.bool.right, pr, client_data, level+4);
+            printf ("%*s</rightOperand>\n", level+2, "");
+        }
+        pr_n("</triple>\n", pr, client_data, level);
+    }
+}
+
+void cql_to_xml(struct cql_node *cn, 
+                void (*pr)(const char *buf, void *client_data),
+                void *client_data)
+{
+    cql_to_xml_r(cn, pr, client_data, 0);
+}
+
+void cql_to_xml_stdio(struct cql_node *cn, FILE *f)
+{
+    cql_to_xml(cn, cql_fputs, f);
+}
+
+void cql_buf_write_handler (const char *b, void *client_data)
+{
+    struct cql_buf_write_info *info = client_data;
+    int l = strlen(b);
+    if (info->off < 0 || (info->off + l >= info->max))
+    {
+        info->off = -1;
+        return;
+    }
+    memcpy (info->buf + info->off, b, l);
+    info->off += l;
+}
+
+int cql_to_xml_buf(struct cql_node *cn, char *out, int max)
+{
+    struct cql_buf_write_info info;
+    info.off = 0;
+    info.max = max;
+    info.buf = out;
+    cql_to_xml(cn, cql_buf_write_handler, &info);
+    if (info.off >= 0)
+        info.buf[info.off] = '\0';
+    return info.off;
+}
+
index 4370644..f33c5cc 100755 (executable)
@@ -12,7 +12,7 @@
 export DH_COMPAT=2
 
 YAZ_WITH_SSL?=1
-CONFIG_FLAGS=--enable-static --enable-shared --enable-tcpd --prefix=/usr
+CONFIG_FLAGS=--without-gsoap --enable-static --enable-shared --enable-tcpd --prefix=/usr
 
 # Enable parallel builds if CONCURRENCY_LEVEL is set
 ifdef CONCURRENCY_LEVEL
diff --git a/etc/MARC21slim2DC.xsl b/etc/MARC21slim2DC.xsl
new file mode 100644 (file)
index 0000000..75f92ab
--- /dev/null
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- $Id: MARC21slim2DC.xsl,v 1.1 2003-01-06 08:20:27 adam Exp $ -->
+<xsl:stylesheet version="1.0"
+  xmlns:marc="http://www.loc.gov/MARC21/slim"
+  xmlns:dc="http://purl.org/dc/elements/1.1/"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  exclude-result-prefixes="marc">
+       <xsl:import href="MARC21slimUtils.xsl"/>
+       <xsl:output method="xml" indent="yes"/>
+       
+       <xsl:template match="/">
+                       <xsl:apply-templates/>
+       </xsl:template>
+
+       <xsl:template match="marc:record">
+               <xsl:variable name="leader" select="marc:leader"/>
+               <xsl:variable name="leader6" select="substring($leader,7,1)"/>
+               <xsl:variable name="leader7" select="substring($leader,8,1)"/>
+               <xsl:variable name="controlField008" select="marc:controlfield[@tag=008]"/>
+
+         <dc:dc>
+                       <xsl:for-each select="marc:datafield[@tag=245]">
+                               <dc:title>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abfghk</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:title>
+                       </xsl:for-each>
+
+       
+                       <xsl:for-each select="marc:datafield[@tag=100]|marc:datafield[@tag=110]|marc:datafield[@tag=111]|marc:datafield[@tag=700]|marc:datafield[@tag=710]|marc:datafield[@tag=711]|marc:datafield[@tag=720]">
+                               <dc:creator>
+                                       <xsl:value-of select="."/>
+                               </dc:creator>
+                       </xsl:for-each>
+
+                       <dc:type>               
+                               <xsl:if test="$leader7='c'">
+                                       <xsl:attribute name="collection">yes</xsl:attribute>
+                               </xsl:if>
+
+                               <xsl:if test="$leader6='d' or $leader6='f' or $leader6='p' or $leader6='t'">
+                                       <xsl:attribute name="manuscript">yes</xsl:attribute>
+                               </xsl:if>
+
+                               <xsl:choose>
+                                       <xsl:when test="$leader6='a' or $leader6='t'">text</xsl:when>
+                                       <xsl:when test="$leader6='e' or $leader6='f'">cartographic</xsl:when>
+                                       <xsl:when test="$leader6='c' or $leader6='d'">notated music</xsl:when>
+                                       <xsl:when test="$leader6='i' or $leader6='j'">sound recording</xsl:when>
+                                       <xsl:when test="$leader6='k'">still image</xsl:when>
+                                       <xsl:when test="$leader6='g'">moving image</xsl:when>
+                                       <xsl:when test="$leader6='r'">three dimensional object</xsl:when>
+                                       <xsl:when test="$leader6='m'">software, multimedia</xsl:when>
+                                       <xsl:when test="$leader6='p'">mixed material</xsl:when>
+                               </xsl:choose>
+                       </dc:type>
+
+                       <xsl:for-each select="marc:datafield[@tag=655]">
+                               <dc:type>
+                                       <xsl:value-of select="."/>
+                               </dc:type>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=260]">
+                               <dc:publisher>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">ab</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:publisher>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=260]/marc:subfield[@code='c']">
+                               <dc:date>
+                                       <xsl:value-of select="."/>
+                               </dc:date>                              
+                       </xsl:for-each>
+
+                       <dc:language>
+                               <xsl:value-of select="substring($controlField008,36,3)"/>
+                       </dc:language>
+
+                       <xsl:for-each select="marc:datafield[@tag=856]/marc:subfield[@code='q']">
+                               <dc:format>
+                                       <xsl:value-of select="."/>
+                               </dc:format>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=520]">
+                               <dc:description>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </dc:description>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=521]">
+                               <dc:description>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </dc:description>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[500&lt;@tag][@tag&lt;=599][not(@tag=506 or @tag=530 or @tag=540 or @tag=546)]">
+                               <dc:description>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </dc:description>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=600]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=610]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=611]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+               
+                       <xsl:for-each select="marc:datafield[@tag=630]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=650]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=653]">
+                               <dc:subject>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:subject>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=752]">
+                               <dc:coverage>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcd</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:coverage>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=530]">
+                               <dc:relation type="original">
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">abcdu</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:relation>  
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=760]|marc:datafield[@tag=762]|marc:datafield[@tag=765]|marc:datafield[@tag=767]|marc:datafield[@tag=770]|marc:datafield[@tag=772]|marc:datafield[@tag=773]|marc:datafield[@tag=774]|marc:datafield[@tag=775]|marc:datafield[@tag=776]|marc:datafield[@tag=777]|marc:datafield[@tag=780]|marc:datafield[@tag=785]|marc:datafield[@tag=786]|marc:datafield[@tag=787]">
+                               <dc:relation>
+                                       <xsl:call-template name="subfieldSelect">
+                                               <xsl:with-param name="codes">ot</xsl:with-param>
+                                       </xsl:call-template>
+                               </dc:relation>  
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=856]">
+                               <dc:identifier>
+                                       <xsl:value-of select="marc:subfield[@code='u']"/>
+                               </dc:identifier>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=506]">
+                               <dc:rights>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </dc:rights>
+                       </xsl:for-each>
+
+                       <xsl:for-each select="marc:datafield[@tag=540]">
+                               <dc:rights>
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>
+                               </dc:rights>
+                       </xsl:for-each>
+               </dc:dc>
+       </xsl:template>
+</xsl:stylesheet>
diff --git a/etc/MARC21slim2MODS.xsl b/etc/MARC21slim2MODS.xsl
new file mode 100644 (file)
index 0000000..ff35524
--- /dev/null
@@ -0,0 +1,1873 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<xsl:stylesheet version="1.0" xmlns:xlink="http://www.w3.org/TR/xlink" xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns="http://www.loc.gov/mods/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="marc">\r
+       <xsl:include href="MARC21slimUtils.xsl"/>\r
+       <xsl:output method="xml" indent="yes"/>\r
+       \r
+       <xsl:template match="/">\r
+               <collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/mods/  http://www.loc.gov/standards/marcxml/schema/mods.xsd">\r
+                       <xsl:apply-templates/>\r
+               </collection>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:record">\r
+               <mods>\r
+                       <xsl:variable name="leader" select="marc:leader"/>\r
+                       <xsl:variable name="leader6" select="substring($leader,7,1)"/>\r
+                       <xsl:variable name="leader7" select="substring($leader,8,1)"/>\r
+                       <xsl:variable name="controlField008" select="marc:controlfield[@tag=008]"/>\r
+\r
+                       <xsl:variable name="typeOf008">\r
+                               <xsl:choose>\r
+                                       <xsl:when test="$leader6='a'">\r
+                                               <xsl:choose>\r
+                                                       <xsl:when test="$leader7='a' or $leader7='c' or $leader7='d' or $leader7='m'">BK</xsl:when>\r
+                                                       <xsl:when test="$leader7='b' or $leader7='i' or $leader7='s'">SE</xsl:when>                             \r
+                                               </xsl:choose>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$leader6='t'">BK</xsl:when>\r
+                                       <xsl:when test="$leader6='p'">MM</xsl:when>\r
+                                       <xsl:when test="$leader6='m'">CF</xsl:when>     \r
+                                       <xsl:when test="$leader6='e' or $leader6='f'">MP</xsl:when>     \r
+                                       <xsl:when test="$leader6='g' or $leader6='k' or $leader6='o' or $leader6='r'">VM</xsl:when>                             \r
+                                       <xsl:when test="$leader6='c' or $leader6='d' or $leader6='i' or $leader6='j'">MU</xsl:when>                             \r
+                               </xsl:choose>\r
+                       </xsl:variable>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=245]">\r
+                               <titleInfo>\r
+                                       <xsl:variable name="title">\r
+                                               <xsl:call-template name="chopPunctuation">\r
+                                                       <xsl:with-param name="chopString">\r
+                                                               <xsl:call-template name="subfieldSelect">\r
+                                                                       <xsl:with-param name="codes">abfghk</xsl:with-param>\r
+                                                               </xsl:call-template>\r
+                                                       </xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </xsl:variable>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="@ind2>0">\r
+                                                       <nonSort>\r
+                                                               <xsl:value-of select="substring($title,1,@ind2)"/>\r
+                                                       </nonSort>\r
+                                                       <title>\r
+                                                               <xsl:value-of select="substring($title,@ind2+1)"/>\r
+                                                       </title>\r
+                                               </xsl:when>\r
+                                               <xsl:otherwise>\r
+                                                       <title>\r
+                                                               <xsl:value-of select="$title"/>\r
+                                                       </title>\r
+                                               </xsl:otherwise>\r
+                                       </xsl:choose>\r
+                                       <xsl:call-template name="part"/>\r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+                       \r
+                       <xsl:for-each select="marc:datafield[@tag=210]">\r
+                               <titleInfo type="abbreviated">\r
+                                       <title>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </title>\r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+                       \r
+                       <xsl:for-each select="marc:datafield[@tag=242]">\r
+                               <titleInfo type="translated">\r
+                                       <title>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">abh</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </title>\r
+                                       <xsl:call-template name="part"/>\r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+                       \r
+                       <xsl:for-each select="marc:datafield[@tag=246]">\r
+                               <titleInfo type="alternative">\r
+                                       <xsl:for-each select="marc:subfield[@code='i']">\r
+                                               <xsl:attribute name="displayLabel">\r
+                                                       <xsl:value-of select="text()"/>\r
+                                               </xsl:attribute>\r
+                                       </xsl:for-each>\r
+                                       <title>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">abfh</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </title>\r
+                                       <xsl:call-template name="part"/>                        \r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=130]|marc:datafield[@tag=240]|marc:datafield[@tag=730][@ind2!=2]">\r
+                               <titleInfo type="uniform">\r
+                                       <title>\r
+                                               <xsl:variable name="str">\r
+                                                       <xsl:for-each select="marc:subfield">\r
+                                                               <xsl:if test="(contains('adfhklmor',@code) and (not(../marc:subfield[@code='n' or @code='p']) or (following-sibling::marc:subfield[@code='n' or @code='p'])))">\r
+                                                                       <xsl:value-of select="text()"/><xsl:text> </xsl:text>\r
+                                                               </xsl:if>\r
+                                                       </xsl:for-each>\r
+                                               </xsl:variable>\r
+                                               <xsl:value-of select="substring($str,1,string-length($str)-1)"/>\r
+                                       </title>\r
+                                       <xsl:call-template name="part"/>                        \r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=740][@ind2!=2]">\r
+                               <titleInfo type="alternative">\r
+                                       <title>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">ah</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </title>\r
+                                       <xsl:call-template name="part"/>                        \r
+                               </titleInfo>\r
+                       </xsl:for-each>\r
+                       \r
+                       <xsl:for-each select="marc:datafield[@tag=100]">\r
+                               <name type="personal">\r
+                                       <xsl:call-template name="nameABCDQ"/>\r
+                                       <xsl:call-template name="affiliation"/>\r
+                                       <role>creator</role>\r
+                                       <xsl:call-template name="role"/>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=110]">\r
+                               <name type="corporate">\r
+                                       <xsl:call-template name="nameABCDN"/>\r
+                                       <role>creator</role>\r
+                                       <xsl:call-template name="role"/>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=111]">\r
+                               <name type="conference">\r
+                                       <xsl:call-template name="nameACDEQ"/>\r
+                                       <role>creator</role>\r
+                                       <xsl:for-each select="marc:subfield[@code='4']">\r
+                                               <role><xsl:value-of select="."/></role>\r
+                                       </xsl:for-each>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=700][not(marc:subfield[@code='t'])]">\r
+                               <name type="personal">\r
+                                       <xsl:call-template name="nameABCDQ"/>\r
+                                       <xsl:call-template name="affiliation"/>\r
+                                       <xsl:call-template name="role"/>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=710][not(marc:subfield[@code='t'])]">\r
+                               <name type="corporate">\r
+                                       <xsl:call-template name="nameABCDN"/>\r
+                                       <xsl:call-template name="role"/>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=711][not(marc:subfield[@code='t'])]">\r
+                               <name type="conference">\r
+                                       <xsl:call-template name="nameACDEQ"/>\r
+                                       <xsl:for-each select="marc:subfield[@code='4']">\r
+                                               <role><xsl:value-of select="."/></role>\r
+                                       </xsl:for-each>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=720][not(marc:subfield[@code='t'])]">\r
+                               <name>\r
+                                       <xsl:if test="@ind1=1">\r
+                                               <xsl:attribute name="type">personal</xsl:attribute>\r
+                                       </xsl:if>\r
+                                       <namePart>\r
+                                               <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                                       </namePart>\r
+                                       <xsl:call-template name="role"/>\r
+                               </name>\r
+                       </xsl:for-each>\r
+\r
+                       <typeOfResource>                \r
+                               <xsl:if test="$leader7='c'">\r
+                                       <xsl:attribute name="collection">yes</xsl:attribute>\r
+                               </xsl:if>\r
+                               <xsl:if test="$leader6='d' or $leader6='f' or $leader6='p' or $leader6='t'">\r
+                                       <xsl:attribute name="manuscript">yes</xsl:attribute>\r
+                               </xsl:if>\r
+\r
+                               <xsl:choose>\r
+                                       <xsl:when test="$leader6='a' or $leader6='t'">text</xsl:when>\r
+                                       <xsl:when test="$leader6='e' or $leader6='f'">cartographic</xsl:when>\r
+                                       <xsl:when test="$leader6='c' or $leader6='d'">notated music</xsl:when>\r
+                                       <xsl:when test="$leader6='i' or $leader6='j'">sound recording</xsl:when>\r
+                                       <xsl:when test="$leader6='k'">still image</xsl:when>\r
+                                       <xsl:when test="$leader6='g'">moving image</xsl:when>\r
+                                       <xsl:when test="$leader6='r'">three dimensional object</xsl:when>\r
+                                       <xsl:when test="$leader6='m'">software, multimedia</xsl:when>\r
+                                       <xsl:when test="$leader6='p'">mixed material</xsl:when>\r
+                               </xsl:choose>\r
+                       </typeOfResource>\r
+\r
+                               <xsl:if test="substring($controlField008,26,1)='d'">\r
+                                       <genre authority="marc">globe</genre>\r
+                               </xsl:if>\r
+                       \r
+                               <xsl:if test="marc:controlfield[@tag=007][substring(text(),1,1)='a'][substring(text(),2,1)='r']">\r
+                                       <genre authority="marc">remote sensing image</genre>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='MP'">\r
+                                       <xsl:variable name="controlField008-25" select="substring($controlField008,26,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-25='a' or $controlField008-25='b' or $controlField008-25='c' or marc:controlfield[@tag=007][substring(text(),1,1)='a'][substring(text(),2,1)='j']">\r
+                                                       <genre authority="marc">map</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-25='e' or marc:controlfield[@tag=007][substring(text(),1,1)='a'][substring(text(),2,1)='d']">\r
+                                                       <genre authority="marc">atlas</genre>\r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='SE'">\r
+                                       <xsl:variable name="controlField008-21" select="substring($controlField008,22,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-21='d'">\r
+                                                       <genre authority="marc">database</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-21='l'">       \r
+                                                       <genre authority="marc">loose-leaf</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-21='m'">\r
+                                                       <genre authority="marc">series</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-21='n'">\r
+                                                       <genre authority="marc">newspaper</genre>       \r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-21='p'">\r
+                                                       <genre authority="marc">periodical</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-21='w'">\r
+                                                       <genre authority="marc">web site</genre>\r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='BK' or $typeOf008='SE'">\r
+                                       <xsl:variable name="controlField008-24" select="substring($controlField008,25,4)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="contains($controlField008-24,'a')">\r
+                                                       <genre authority="marc">abstract or summary</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'b')">\r
+                                                       <genre authority="marc">bibliography</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'c')">\r
+                                                       <genre authority="marc">catalog</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'d')">\r
+                                                       <genre authority="marc">dictionary</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'e')">\r
+                                                       <genre authority="marc">encyclopedia</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'f')">\r
+                                                       <genre authority="marc">handbook</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'g')">\r
+                                                       <genre authority="marc">legal article</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'i')">\r
+                                                       <genre authority="marc">index</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'k')">\r
+                                                       <genre authority="marc">discography</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'l')">\r
+                                                       <genre authority="marc">legislation</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'m')">\r
+                                                       <genre authority="marc">theses</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'n')">\r
+                                                       <genre authority="marc">survey of literature</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'o')">\r
+                                                       <genre authority="marc">review</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'p')">\r
+                                                       <genre authority="marc">programmed text</genre>\r
+                                               </xsl:when>                                     \r
+                                               <xsl:when test="contains($controlField008-24,'q')">\r
+                                                       <genre authority="marc">filmography</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'r')">\r
+                                                       <genre authority="marc">directory</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'s')">\r
+                                                       <genre authority="marc">statistics</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'t')">\r
+                                                       <genre authority="marc">technical report</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'v')">\r
+                                                       <genre authority="marc">legal case and case notes</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'w')">\r
+                                                       <genre authority="marc">law report or digest</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="contains($controlField008-24,'z')">\r
+                                                       <genre authority="marc">treaty</genre>\r
+                                               </xsl:when>      \r
+                                       </xsl:choose>\r
+                                       <xsl:variable name="controlField008-29" select="substring($controlField008,30,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-29='1'">\r
+                                                       <genre authority="marc">conference publication</genre>\r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='CF'">\r
+                                       <xsl:variable name="controlField008-26" select="substring($controlField008,27,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-26='a'">\r
+                                                       <genre authority="marc">numeric data</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-26='e'">\r
+                                                       <genre authority="marc">database</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-26='f'">\r
+                                                       <genre authority="marc">font</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-26='g'">\r
+                                                       <genre authority="marc">game</genre>\r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='BK'">\r
+                                       <xsl:if test="substring($controlField008,25,1)='j'">\r
+                                               <genre authority="marc">patent</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="substring($controlField008,31,1)='1'">\r
+                                               <genre authority="marc">festschrift</genre>\r
+                                       </xsl:if>\r
+\r
+                                       <xsl:variable name="controlField008-34" select="substring($controlField008,35,1)"/>\r
+                                       <xsl:if test="$controlField008-34='a' or $controlField008-34='b' or $controlField008-34='c' or $controlField008-34='d'">\r
+                                               <genre authority="marc">biography</genre>\r
+                                       </xsl:if>\r
+\r
+                                       <xsl:variable name="controlField008-33" select="substring($controlField008,34,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-33='e'">\r
+                                                       <genre authority="marc">essay</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='d'">\r
+                                                       <genre authority="marc">drama</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='c'">\r
+                                                       <genre authority="marc">comic strip</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='l'">\r
+                                                       <genre authority="marc">fiction</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='h'">\r
+                                                       <genre authority="marc">humor, satire</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='i'">\r
+                                                       <genre authority="marc">letter</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='f'">\r
+                                                       <genre authority="marc">novel</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='j'">\r
+                                                       <genre authority="marc">short story</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='s'">\r
+                                                       <genre authority="marc">speech</genre>\r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='MU'">\r
+                                       <xsl:variable name="controlField008-30-31" select="substring($controlField008,31,2)"/>\r
+                                       <xsl:if test="contains($controlField008-30-31,'b')">\r
+                                               <genre authority="marc">biography</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'c')">\r
+                                               <genre authority="marc">conference publication</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'d')">\r
+                                               <genre authority="marc">drama</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'e')">\r
+                                               <genre authority="marc">essay</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'f')">\r
+                                               <genre authority="marc">fiction</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'o')">\r
+                                               <genre authority="marc">folktale</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'h')">\r
+                                               <genre authority="marc">history</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'k')">\r
+                                               <genre authority="marc">humor, satire</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'m')">\r
+                                               <genre authority="marc">memoir</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'p')">\r
+                                               <genre authority="marc">poetry</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'r')">\r
+                                               <genre authority="marc">rehersal</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'g')">\r
+                                               <genre authority="marc">reporting</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'s')">\r
+                                               <genre authority="marc">sound</genre>\r
+                                       </xsl:if>\r
+                                       <xsl:if test="contains($controlField008-30-31,'l')">\r
+                                               <genre authority="marc">speech</genre>\r
+                                       </xsl:if>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$typeOf008='VM'">\r
+                                       <xsl:variable name="controlField008-33" select="substring($controlField008,34,1)"/>\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="$controlField008-33='a'">\r
+                                                       <genre authority="marc">art original</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='b'">\r
+                                                       <genre authority="marc">kit</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='c'">\r
+                                                       <genre authority="marc">art reproduction</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='d'">\r
+                                                       <genre authority="marc">diorama</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='f'">\r
+                                                       <genre authority="marc">filmstrip</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='g'">\r
+                                                       <genre authority="marc">legal article</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='i'">\r
+                                                       <genre authority="marc">picture</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='k'">\r
+                                                       <genre authority="marc">graphic</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='l'">\r
+                                                       <genre authority="marc">technical drawing</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='m'">\r
+                                                       <genre authority="marc">motion picture</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='n'">\r
+                                                       <genre authority="marc">chart</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='o'">\r
+                                                       <genre authority="marc">flash card</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='p'">\r
+                                                       <genre authority="marc">microscope slide</genre>\r
+                                               </xsl:when>                                     \r
+                                               <xsl:when test="$controlField008-33='q' or marc:controlfield[@tag=007][substring(text(),1,1)='a'][substring(text(),2,1)='q']">\r
+                                                       <genre authority="marc">model</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='r'">\r
+                                                       <genre authority="marc">realia</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='s'">\r
+                                                       <genre authority="marc">slide</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='t'">\r
+                                                       <genre authority="marc">transparency</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='v'">\r
+                                                       <genre authority="marc">videorecording</genre>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="$controlField008-33='w'">\r
+                                                       <genre authority="marc">toy</genre>\r
+                                               </xsl:when> \r
+                                       </xsl:choose>\r
+                               </xsl:if>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=655]">\r
+                                       <genre authority="marc">\r
+                                               <xsl:attribute name="authority">\r
+                                                       <xsl:value-of select="marc:subfield[@code='2']"/>\r
+                                               </xsl:attribute>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">abvxyz</xsl:with-param>\r
+                                                       <xsl:with-param name="delimeter">-</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </genre>\r
+                               </xsl:for-each>\r
+\r
+                       <publicationInfo>\r
+                               <xsl:variable name="MARCpublicationCode" select="normalize-space(substring($controlField008,16,3))"/>\r
+                               \r
+                               <xsl:if test="translate($MARCpublicationCode,'|','')">\r
+                                       <placeCode authority="marc">\r
+                                               <xsl:value-of select="$MARCpublicationCode"/>\r
+                                       </placeCode>\r
+                               </xsl:if>\r
+                       \r
+                               <xsl:for-each select="marc:datafield[@tag=044]/marc:subfield[@code='c']">\r
+                                       <placeCode authority="iso3166">\r
+                                               <xsl:value-of select="."/>\r
+                                       </placeCode>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=260]/marc:subfield[@code='a' or @code='b' or @code='c' or @code='g']">\r
+                                       <xsl:choose>\r
+                                               <xsl:when test="@code='a'">\r
+                                                       <place>\r
+                                                               <xsl:call-template name="chopPunctuation">\r
+                                                                       <xsl:with-param name="chopString" select="."/>\r
+                                                               </xsl:call-template>\r
+                                                       </place>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="@code='b'">\r
+                                                       <publisher>\r
+                                                               <xsl:call-template name="chopPunctuation">\r
+                                                                       <xsl:with-param name="chopString" select="."/>\r
+                                                               </xsl:call-template>\r
+                                                       </publisher>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="@code='c'">\r
+                                                       <dateIssued>\r
+                                                               <xsl:call-template name="chopPunctuation">\r
+                                                                       <xsl:with-param name="chopString" select="."/>\r
+                                                               </xsl:call-template>\r
+                                                       </dateIssued>\r
+                                               </xsl:when>\r
+                                               <xsl:when test="@code='g'">\r
+                                                       <dateCreated>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </dateCreated>                  \r
+                                               </xsl:when>\r
+                                       </xsl:choose>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:variable name="dataField260c">\r
+                                       <xsl:call-template name="chopPunctuation">\r
+                                               <xsl:with-param name="chopString" select="marc:datafield[@tag=260]/marc:subfield[@code='c']"/>\r
+                                       </xsl:call-template>\r
+                               </xsl:variable>\r
+\r
+                               <xsl:variable name="controlField008-7-10" select="normalize-space(substring($controlField008, 8, 4))"/>\r
+                               <xsl:variable name="controlField008-11-14" select="normalize-space(substring($controlField008, 12, 4))"/>\r
+                               <xsl:variable name="controlField008-6" select="normalize-space(substring($controlField008, 7, 1))"/>\r
+               \r
+                               <xsl:if test="$controlField008-6='e' or $controlField008-6='p' or $controlField008-6='r' or $controlField008-6='t' or $controlField008-6='s'">\r
+                                       <xsl:if test="$controlField008-7-10 and ($controlField008-7-10 != $dataField260c)">\r
+                                               <dateIssued encoding="marc">\r
+                                                       <xsl:value-of select="$controlField008-7-10"/>\r
+                                               </dateIssued>\r
+                                       </xsl:if>\r
+                               </xsl:if>\r
+               \r
+                               <xsl:if test="$controlField008-6='c' or $controlField008-6='d' or $controlField008-6='i' or $controlField008-6='k' or $controlField008-6='m' or $controlField008-6='q' or $controlField008-6='u'">\r
+                                       <xsl:if test="$controlField008-7-10">\r
+                                               <dateIssued encoding="marc" point="start">\r
+                                                       <xsl:value-of select="$controlField008-7-10"/>\r
+                                               </dateIssued>\r
+                                       </xsl:if>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$controlField008-6='c' or $controlField008-6='d' or $controlField008-6='i' or $controlField008-6='k' or $controlField008-6='m' or $controlField008-6='q' or $controlField008-6='u'">\r
+                                       <xsl:if test="$controlField008-11-14">\r
+                                               <dateIssued encoding="marc" point="end">\r
+                                                       <xsl:value-of select="$controlField008-11-14"/>\r
+                                               </dateIssued>\r
+                                       </xsl:if>\r
+                               </xsl:if>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=033][@ind1=0 or @ind1=1]/marc:subfield[@code='a']">\r
+                                       <dateCaptured encoding="iso8601">\r
+                                               <xsl:value-of select="."/>\r
+                                       </dateCaptured>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=033][@ind1=2]/marc:subfield[@code='a'][1]">\r
+                                       <dateCaptured encoding="iso8601" point="start">\r
+                                               <xsl:value-of select="."/>\r
+                                       </dateCaptured>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=033][@ind1=2]/marc:subfield[@code='a'][2]">\r
+                                       <dateCaptured encoding="iso8601" point="end">\r
+                                               <xsl:value-of select="."/>\r
+                                       </dateCaptured>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=250]/marc:subfield[@code='a']">\r
+                                       <edition>\r
+                                               <xsl:value-of select="."/>\r
+                                       </edition>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:leader">\r
+                                       <issuance>\r
+                                               <xsl:choose>\r
+                                                       <xsl:when test="$leader7='a' or $leader7='c' or $leader7='d' or $leader7='m'">monographic</xsl:when>\r
+                                                       <xsl:when test="$leader7='b' or $leader7='i' or $leader7='s'">continuing</xsl:when>                                                     \r
+                                               </xsl:choose>\r
+                                       </issuance>\r
+                               </xsl:for-each>         \r
+                               \r
+                               <xsl:for-each select="marc:datafield[@tag=310]|marc:datafield[@tag=321]">\r
+                                       <frequency>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </frequency>\r
+                               </xsl:for-each>                                                         \r
+                       </publicationInfo>\r
+\r
+\r
+                       <xsl:for-each select="marc:controlfield[@tag=041]">\r
+                               <xsl:for-each select="marc:subfield[@code='a' or @code='d' or @code='e']">\r
+                                       <language>\r
+                                               <xsl:choose>\r
+                                                       <xsl:when test="../marc:subfield[@code='2']">\r
+                                                               <xsl:attribute name="authority">rfc3066</xsl:attribute>\r
+                                                       </xsl:when>\r
+                                                       <xsl:otherwise>\r
+                                                               <xsl:attribute name="authority">iso639-2b</xsl:attribute>                                               \r
+                                                       </xsl:otherwise>\r
+                                               </xsl:choose>\r
+                                               <xsl:value-of select="text()"/>\r
+                                       </language>\r
+                               </xsl:for-each>\r
+                       </xsl:for-each>                 \r
+\r
+                       <xsl:variable name="controlField008-35-37" select="normalize-space(translate(substring($controlField008,36,3),'|#',''))"/>\r
+                       <xsl:if test="$controlField008-35-37">\r
+                               <language authority="iso639-2b">\r
+                                       <xsl:value-of select="substring($controlField008,36,3)"/>\r
+                               </language>\r
+                       </xsl:if>\r
+\r
+                       <xsl:variable name="physicalDescription">\r
+                               <xsl:if test="$typeOf008='CF' and marc:controlfield[@tag=007][substring(.,12,1)='a' or substring(.,12,1)='b']">\r
+                                       <digitalOrigin>reformatted digital</digitalOrigin>\r
+                               </xsl:if>\r
+\r
+                               <xsl:variable name="controlField008-23" select="substring($controlField008,24,1)"/>\r
+                               <xsl:variable name="controlField008-29" select="substring($controlField008,30,1)"/>\r
+\r
+                               <xsl:variable name="check008-23">\r
+                                       <xsl:if test="$typeOf008='BK' or $typeOf008='MU' or $typeOf008='SE' or $typeOf008='MM'">\r
+                                               <xsl:value-of select="true()"/>\r
+                                       </xsl:if>\r
+                               </xsl:variable>\r
+\r
+                               <xsl:variable name="check008-29">\r
+                                       <xsl:if test="$typeOf008='MP' or $typeOf008='VM'">\r
+                                               <xsl:value-of select="true()"/>\r
+                                       </xsl:if>\r
+                               </xsl:variable>\r
+\r
+                               <xsl:choose>\r
+                                       <xsl:when test="($check008-23 and $controlField008-23='f') or ($check008-29 and $controlField008-29='f')">\r
+                                               <form><controlled>braille</controlled></form>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$leader6 = 'm' or ($check008-23 and $controlField008-23='s') or ($check008-29 and $controlField008-29='s')">\r
+                                               <form><controlled>electronic</controlled></form>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="($check008-23 and $controlField008-23='b') or ($check008-29 and $controlField008-29='b')">\r
+                                               <form><controlled>microfiche</controlled></form>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="($check008-23 and $controlField008-23='a') or ($check008-29 and $controlField008-29='a')">\r
+                                               <form><controlled>microfilm</controlled></form>\r
+                                       </xsl:when>\r
+                               </xsl:choose>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=856]/marc:subfield[@code='q'][string-length(.)>1]">\r
+                                       <internetMediaType>\r
+                                               <xsl:value-of select="."/>\r
+                                       </internetMediaType>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=256]/marc:subfield[@code='a']">\r
+                                       <form>\r
+                                               <unControlled>\r
+                                                       <xsl:value-of select="."/>\r
+                                               </unControlled>\r
+                                       </form>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:datafield[@tag=300]">\r
+                                       <extent>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">abce</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </extent>\r
+                               </xsl:for-each>\r
+                       </xsl:variable>\r
+\r
+                       <xsl:if test="string-length(normalize-space($physicalDescription))">\r
+                               <physicalDescription>\r
+                                       <xsl:copy-of select="$physicalDescription"/>\r
+                               </physicalDescription>\r
+                       </xsl:if>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=520]">\r
+                               <abstract>\r
+                                       <xsl:call-template name="uri"/>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </abstract>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=505]">\r
+                               <tableOfContents>\r
+                                       <xsl:call-template name="uri"/>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">agrt</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </tableOfContents>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=521]">\r
+                               <targetAudience>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </targetAudience>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:if test="$typeOf008='BK' or $typeOf008='CF' or $typeOf008='MU' or $typeOf008='VM'">\r
+                               <xsl:variable name="controlField008-22" select="substring($controlField008,23,1)"/>\r
+                               <xsl:choose>\r
+                                       <xsl:when test="$controlField008-22='d'">\r
+                                               <targetAudience>adolescent</targetAudience>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$controlField008-22='e'">\r
+                                               <targetAudience>adult</targetAudience>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$controlField008-22='g'">\r
+                                               <targetAudience>general</targetAudience>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$controlField008-22='b' or $controlField008-22='c' or $controlField008-22='j'">\r
+                                               <targetAudience>juvenile</targetAudience>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$controlField008-22='a'">\r
+                                               <targetAudience>preschool</targetAudience>\r
+                                       </xsl:when>\r
+                                       <xsl:when test="$controlField008-22='f'">\r
+                                               <targetAudience>specialized</targetAudience>\r
+                                       </xsl:when>\r
+                               </xsl:choose>\r
+                       </xsl:if>\r
+\r
+                       <!-- Not in mapping but in conversion -->\r
+                       <xsl:for-each select="marc:datafield[@tag=245]/marc:subfield[@code='c']">\r
+                               <note type="statement of responsibility">\r
+                                       <xsl:value-of select="."/>\r
+                               </note>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=500]">\r
+                               <note>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                                       <xsl:call-template name="uri"/>\r
+                               </note>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=511]">\r
+                               <note type="performers">\r
+                                       <xsl:call-template name="uri"/>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </note>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=518]">\r
+                               <note type="venue">\r
+                                       <xsl:call-template name="uri"/>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </note>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=501 or @tag=502 or @tag=504 or @tag=506 or @tag=507 or @tag=508 or @tag=510 or @tag=513 or @tag=514 or @tag=515 or @tag=516 or @tag=522 or @tag=524 or @tag=525 or @tag=526 or @tag=530 or @tag=533 or @tag=534 or @tag=535 or @tag=536 or @tag=538 or @tag=540 or @tag=541 or @tag=544 or @tag=545 or @tag=546 or @tag=547 or @tag=550 or @tag=552 or @tag=555 or @tag=556 or @tag=561 or @tag=562 or @tag=565 or @tag=567 or @tag=580 or @tag=581 or @tag=583 or @tag=584 or @tag=585 or @tag=586]">\r
+                               <note>\r
+                                       <xsl:call-template name="uri"/>\r
+                                       <xsl:variable name="str">\r
+                                               <xsl:for-each select="marc:subfield[@code!='6' or @code!='8']">\r
+                                                       <xsl:value-of select="."/><xsl:text> </xsl:text>\r
+                                               </xsl:for-each>\r
+                                       </xsl:variable>\r
+                                       <xsl:value-of select="substring($str,1,string-length($str)-1)"/>\r
+                               </note>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=034][marc:subfield[@code='d' or @code='e' or @code='f' or @code='g']]">\r
+                               <cartographics>\r
+                                       <coordinates>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">defg</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </coordinates>\r
+                               </cartographics>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=255]">\r
+                               <cartographics>\r
+                                       <xsl:for-each select="marc:subfield[@code='c']">\r
+                                               <coordinates>\r
+                                                       <xsl:value-of select="."/>\r
+                                               </coordinates>\r
+                                       </xsl:for-each>\r
+                                       <xsl:for-each select="marc:subfield[@code='a']">\r
+                                               <scale>\r
+                                                       <xsl:value-of select="."/>\r
+                                               </scale>\r
+                                       </xsl:for-each>\r
+                                       <xsl:for-each select="marc:subfield[@code='b']">\r
+                                               <projection>\r
+                                                       <xsl:value-of select="."/>\r
+                                               </projection>   \r
+                                       </xsl:for-each>\r
+                               </cartographics>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:apply-templates select="marc:datafield[653 >= @tag and @tag >= 600]"/>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=752]">\r
+                               <subject>\r
+                                       <hierarchicalGeographic>\r
+                                               <xsl:for-each select="marc:subfield[@code='a']">\r
+                                                       <country>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </country>\r
+                                               </xsl:for-each>         \r
+                                               <xsl:for-each select="marc:subfield[@code='b']">\r
+                                                       <state>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </state>\r
+                                               </xsl:for-each>         \r
+                                               <xsl:for-each select="marc:subfield[@code='c']">\r
+                                                       <county>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </county>\r
+                                               </xsl:for-each>         \r
+                                               <xsl:for-each select="marc:subfield[@code='d']">\r
+                                                       <city>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </city>\r
+                                               </xsl:for-each>         \r
+                                       </hierarchicalGeographic>\r
+                               </subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=050]">\r
+                               <xsl:for-each select="marc:subfield[@code='b']">\r
+                                       <classification authority="lcc">\r
+                                               <xsl:value-of select="preceding-sibling::marc:subfield[@code='a'][1]"/>\r
+                                               <xsl:text> </xsl:text>\r
+                                               <xsl:value-of select="text()"/>\r
+                                       </classification>\r
+                               </xsl:for-each>\r
+                               <xsl:for-each select="marc:subfield[@code='a'][not(following-sibling::marc:subfield[@code='b'])]">\r
+                                       <classification authority="lcc">\r
+                                               <xsl:value-of select="text()"/>\r
+                                       </classification>\r
+                               </xsl:for-each>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=082]">\r
+                               <classification authority="ddc">\r
+                                       <xsl:if test="marc:subfield[@code='2']">\r
+                                               <xsl:attribute name="edition">\r
+                                                       <xsl:value-of select="marc:subfield[@code='2']"/>\r
+                                               </xsl:attribute>\r
+                                       </xsl:if>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=080]">\r
+                               <classification authority="udc">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abx</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=060]">\r
+                               <classification authority="nlm">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=086][@ind1=0]">\r
+                               <classification authority="sudocs">\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=086][@ind1=1]">\r
+                               <classification authority="candoc">\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=086]">\r
+                               <classification>\r
+                                       <xsl:attribute name="authority">\r
+                                               <xsl:value-of select="marc:subfield[@code='2']"/>\r
+                                       </xsl:attribute>                                                \r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=084]">\r
+                               <classification>\r
+                                       <xsl:attribute name="authority">\r
+                                               <xsl:value-of select="marc:subfield[@code='2']"/>\r
+                                       </xsl:attribute>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </classification>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=440]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="subfieldSelect">\r
+                                                               <xsl:with-param name="codes">av</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                                       <xsl:call-template name="part"/>\r
+                                               </title>\r
+                                       </titleInfo>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=490][@ind1=0]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="subfieldSelect">\r
+                                                               <xsl:with-param name="codes">av</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                                       <xsl:call-template name="part"/>\r
+                                               </title>\r
+                                       </titleInfo>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=534]">\r
+                               <relatedItem type="original">\r
+                                       <xsl:call-template name="relatedTitle"/>\r
+                                       <xsl:call-template name="relatedName"/>\r
+                                       <xsl:call-template name="relatedIdentifierISSN"/>\r
+                                       <xsl:for-each select="marc:subfield[@code='z']">\r
+                                               <identifier type="isbn">\r
+                                                       <xsl:value-of select="."/>\r
+                                               </identifier>\r
+                                       </xsl:for-each>\r
+                                       <xsl:call-template name="relatedNote"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=700][marc:subfield[@code='t']]">\r
+                               <relatedItem>\r
+                                       <xsl:call-template name="constituentOrRelatedType"/>\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklmorsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">g</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="part"/>\r
+                                       </titleInfo>\r
+                                       <name type="personal">\r
+                                               <namePart>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">abcq</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="beforeCodes">g</xsl:with-param>\r
+                                                       </xsl:call-template>                                                    \r
+                                               </namePart>\r
+                                               <xsl:call-template name="nameDate"/>\r
+                                               <xsl:for-each select="marc:subfield[@code='e']">\r
+                                                       <role>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </role>\r
+                                               </xsl:for-each>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                                       <xsl:call-template name="relatedIdentifierISSN"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=710][marc:subfield[@code='t']]">\r
+                               <relatedItem>\r
+                                       <xsl:call-template name="constituentOrRelatedType"/>\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklmorsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">dg</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="relatedPart"/>\r
+                                       </titleInfo>\r
+                                       <name type="corporate">\r
+                                               <xsl:for-each select="marc:subfield[@code='a']">\r
+                                                       <namePart>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </namePart>\r
+                                               </xsl:for-each>\r
+                                               <xsl:for-each select="marc:subfield[@code='b']">\r
+                                                       <namePart>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </namePart>\r
+                                               </xsl:for-each>\r
+                                               <xsl:variable name="tempNamePart">\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">c</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="beforeCodes">dgn</xsl:with-param>\r
+                                                       </xsl:call-template>                                                    \r
+                                               </xsl:variable>\r
+                                               <xsl:if test="normalize-space($tempNamePart)">\r
+                                                       <namePart>\r
+                                                               <xsl:value-of select="$tempNamePart"/>\r
+                                                       </namePart>\r
+                                               </xsl:if>\r
+                                               <xsl:for-each select="marc:subfield[@code='e']">\r
+                                                       <role>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </role>\r
+                                               </xsl:for-each>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                                       <xsl:call-template name="relatedIdentifierISSN"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=711][marc:subfield[@code='t']]">\r
+                               <relatedItem>\r
+                                       <xsl:call-template name="constituentOrRelatedType"/>\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">g</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="relatedPart"/>\r
+                                       </titleInfo>\r
+                                       <name type="conference">\r
+                                               <namePart>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">aqdc</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="beforeCodes">gn</xsl:with-param>\r
+                                                       </xsl:call-template>                                                    \r
+                                               </namePart>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                                       <xsl:call-template name="relatedIdentifierISSN"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=730][@ind2=2]">\r
+                               <relatedItem>\r
+                                       <xsl:call-template name="constituentOrRelatedType"/>\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="subfieldSelect">\r
+                                                               <xsl:with-param name="codes">adfgklmorsv</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="part"/>\r
+                                       </titleInfo>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                                       <xsl:call-template name="relatedIdentifierISSN"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=740][@ind2=2]">\r
+                               <relatedItem>\r
+                                       <xsl:call-template name="constituentOrRelatedType"/>\r
+                                       <titleInfo>\r
+                                               <title>                                 \r
+                                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                                               </title>\r
+                                               <xsl:call-template name="part"/>\r
+                                       </titleInfo>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=760]|marc:datafield[@tag=762]">\r
+                               <relatedItem type="series">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=765]|marc:datafield[@tag=767]|marc:datafield[@tag=775]|marc:datafield[@tag=777]|marc:datafield[@tag=787]">\r
+                               <relatedItem type="related">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=770]|marc:datafield[@tag=774]">\r
+                               <relatedItem type="constituent">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=772]|marc:datafield[@tag=773]">\r
+                               <relatedItem type="host">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=776]">\r
+                               <relatedItem type="reproduction">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=780]">\r
+                               <relatedItem type="preceding">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=785]">\r
+                               <relatedItem type="succeeding">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=786]">\r
+                               <relatedItem type="original">\r
+                                       <xsl:call-template name="relatedItem76X-78X"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=800]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklmorsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">g</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="part"/>\r
+                                       </titleInfo>\r
+                                       <name type="personal">\r
+                                               <namePart>\r
+                                                       <xsl:call-template name="chopPunctuation">\r
+                                                               <xsl:with-param name="chopString">\r
+                                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                                               <xsl:with-param name="anyCodes">abcq</xsl:with-param>\r
+                                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                                               <xsl:with-param name="beforeCodes">g</xsl:with-param>\r
+                                                                       </xsl:call-template>\r
+                                                               </xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </namePart>\r
+                                               <xsl:call-template name="nameDate"/>\r
+                                               <xsl:for-each select="marc:subfield[@code='e']">\r
+                                                       <role>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </role>\r
+                                               </xsl:for-each>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                               </relatedItem>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=810]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklmorsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">dg</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="relatedPart"/>\r
+                                       </titleInfo>\r
+                                       <name type="corporate">\r
+                                               <xsl:for-each select="marc:subfield[@code='a']">\r
+                                                       <namePart>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </namePart>\r
+                                               </xsl:for-each>\r
+                                               <xsl:for-each select="marc:subfield[@code='b']">\r
+                                                       <namePart>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </namePart>\r
+                                               </xsl:for-each>\r
+                                               <namePart>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">c</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="beforeCodes">dgn</xsl:with-param>\r
+                                                       </xsl:call-template>                                                    \r
+                                               </namePart>\r
+                                               <xsl:for-each select="marc:subfield[@code='e']">\r
+                                                       <role>\r
+                                                               <xsl:value-of select="."/>\r
+                                                       </role>\r
+                                               </xsl:for-each>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=811]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">tfklsv</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="afterCodes">g</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="relatedPart"/>\r
+                                       </titleInfo>\r
+                                       <name type="conference">\r
+                                               <namePart>\r
+                                                       <xsl:call-template name="specialSubfieldSelect">\r
+                                                               <xsl:with-param name="anyCodes">aqdc</xsl:with-param>\r
+                                                               <xsl:with-param name="axis">t</xsl:with-param>\r
+                                                               <xsl:with-param name="beforeCodes">gn</xsl:with-param>\r
+                                                       </xsl:call-template>                                                    \r
+                                               </namePart>\r
+                                       </name>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=830]">\r
+                               <relatedItem type="series">\r
+                                       <titleInfo>\r
+                                               <title>\r
+                                                       <xsl:call-template name="subfieldSelect">\r
+                                                               <xsl:with-param name="codes">adfgklmorsv</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </title>\r
+                                               <xsl:call-template name="part"/>\r
+                                       </titleInfo>\r
+                                       <xsl:call-template name="relatedForm"/>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=856][@ind2=2]/marc:subfield[@code='q']">\r
+                               <relatedItem>\r
+                                       <internetMediaType>\r
+                                               <xsl:value-of select="."/>\r
+                                       </internetMediaType>\r
+                               </relatedItem>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=020]/marc:subfield[@code='a']">\r
+                               <identifier type="isbn">\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=024][@ind1=0]/marc:subfield[@code='a']">\r
+                               <identifier type="isrc">\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=024][@ind1=2]/marc:subfield[@code='a']">\r
+                               <identifier type="ismn">\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=022]/marc:subfield[@code='a']">\r
+                               <identifier type="issn">\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=010]/marc:subfield[@code='a']">\r
+                               <identifier type="lccn">\r
+                                       <xsl:value-of select="normalize-space(text())"/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=028]">\r
+                               <identifier>\r
+                                       <xsl:attribute name="type">\r
+                                               <xsl:choose>\r
+                                                       <xsl:when test="@ind1=0">issue number</xsl:when>\r
+                                                       <xsl:when test="@ind1=1">matrix number</xsl:when>\r
+                                                       <xsl:when test="@ind1=2">music plate</xsl:when>\r
+                                                       <xsl:when test="@ind1=3">music publisher</xsl:when>\r
+                                                       <xsl:when test="@ind1=4">videorecording identifier</xsl:when>\r
+                                               </xsl:choose>\r
+                                       </xsl:attribute>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+               \r
+                       <xsl:for-each select="marc:datafield[@tag=024][@ind1=4]">\r
+                               <identifier type="sici">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=856]/marc:subfield[@code='u']">\r
+                               <identifier>\r
+                                       <xsl:attribute name="type">\r
+                                               <xsl:choose>\r
+                                                       <xsl:when test="starts-with(.,'urn:doi') or starts-with(.,'doi:')">doi</xsl:when>\r
+                                                       <xsl:otherwise>uri</xsl:otherwise>\r
+                                               </xsl:choose>\r
+                                       </xsl:attribute>\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=024][@ind1=1]/marc:subfield[@code='a']">\r
+                               <identifier type="upc">\r
+                                       <xsl:value-of select="."/>\r
+                               </identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=852]">\r
+                               <location>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abj</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </location>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=506]">\r
+                               <accessCondition type="restrictionOnAccess">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcd35</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </accessCondition>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=540]">\r
+                               <accessCondition type="useAndReproduction">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcde35</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </accessCondition>\r
+                       </xsl:for-each>\r
+\r
+                       <recordInfo>\r
+                               <xsl:for-each select="marc:datafield[@tag=040]">\r
+                                       <recordContentSource>\r
+                                               <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                                       </recordContentSource>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:controlfield[@tag=008]">\r
+                                       <recordCreationDate encoding="marc">\r
+                                               <xsl:value-of select="substring(.,1,6)"/>\r
+                                       </recordCreationDate>\r
+                               </xsl:for-each>         \r
+                       \r
+                               <xsl:for-each select="marc:controlfield[@tag=005]">\r
+                                       <recordChangeDate encoding="iso8601">\r
+                                               <xsl:value-of select="."/>\r
+                                       </recordChangeDate>\r
+                               </xsl:for-each>\r
+\r
+                               <xsl:for-each select="marc:controlfield[@tag=001]">\r
+                                       <recordIdentifier>\r
+                                               <xsl:if test="../marc:controlfield[@tag=003]">\r
+                                                       <xsl:attribute name="source">\r
+                                                               <xsl:value-of select="../marc:controlfield[@tag=003]"/>\r
+                                                       </xsl:attribute>\r
+                                               </xsl:if>\r
+                                               <xsl:value-of select="."/>\r
+                                       </recordIdentifier>\r
+                               </xsl:for-each>\r
+                       </recordInfo>\r
+               </mods>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="displayForm">\r
+               <xsl:for-each select="marc:subfield[@code='c']">\r
+                       <displayForm>\r
+                               <xsl:value-of select="."/>\r
+                       </displayForm>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="affiliation">\r
+               <xsl:for-each select="marc:subfield[@code='u']">\r
+                       <affiliation>\r
+                               <xsl:value-of select="."/>\r
+                       </affiliation>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="uri">\r
+               <xsl:for-each select="marc:subfield[@code='u']">\r
+                       <xsl:attribute name="xlink:href">\r
+                               <xsl:value-of select="."/>\r
+                       </xsl:attribute>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="role">\r
+               <xsl:choose>\r
+                       <xsl:when test="marc:subfield[@code='e']">\r
+                               <role><xsl:value-of select="marc:subfield[@code='e']"/></role>\r
+                       </xsl:when>\r
+                       <xsl:when test="marc:subfield[@code='4']">\r
+                               <xsl:for-each select="marc:subfield[@code='4']">\r
+                                       <role><xsl:value-of select="text()"/></role>\r
+                               </xsl:for-each>\r
+                       </xsl:when>\r
+               </xsl:choose>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="part">\r
+               <xsl:variable name="partNumber">\r
+                       <xsl:call-template name="specialSubfieldSelect">\r
+                               <xsl:with-param name="axis">n</xsl:with-param>\r
+                               <xsl:with-param name="anyCodes">n</xsl:with-param>\r
+                               <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>\r
+                       </xsl:call-template>\r
+               </xsl:variable>\r
+               <xsl:variable name="partName">\r
+                       <xsl:call-template name="specialSubfieldSelect">\r
+                               <xsl:with-param name="axis">p</xsl:with-param>\r
+                               <xsl:with-param name="anyCodes">p</xsl:with-param>\r
+                               <xsl:with-param name="afterCodes">fghkdlmor</xsl:with-param>\r
+                       </xsl:call-template>\r
+               </xsl:variable>\r
+               <xsl:if test="string-length(normalize-space($partNumber))">\r
+                       <partNumber>\r
+                               <xsl:value-of select="$partNumber"/>\r
+                       </partNumber>\r
+               </xsl:if>\r
+               <xsl:if test="string-length(normalize-space($partName))">\r
+                       <partName>\r
+                               <xsl:value-of select="$partName"/>\r
+                       </partName>\r
+               </xsl:if>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedPart">\r
+               <xsl:for-each select="marc:subfield[@code='n'][preceding-sibling::marc:subfield[@code='t']]">\r
+                       <partNumber>\r
+                               <xsl:value-of select="."/>\r
+                       </partNumber>\r
+               </xsl:for-each>\r
+               <xsl:for-each select="marc:subfield[@code='p']">\r
+                       <partName>\r
+                               <xsl:value-of select="."/>\r
+                       </partName>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedName">\r
+               <xsl:for-each select="marc:subfield[@code='a']">\r
+                       <name>\r
+                               <namePart>\r
+                                       <xsl:value-of select="."/>\r
+                               </namePart>\r
+                       </name>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedForm">\r
+               <xsl:for-each select="marc:subfield[@code='h']">\r
+                       <physicalDescription>\r
+                               <form>\r
+                                       <unControlled>\r
+                                               <xsl:value-of select="."/>\r
+                                       </unControlled>\r
+                               </form>\r
+                       </physicalDescription>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedExtent">\r
+               <xsl:for-each select="marc:subfield[@code='h']">\r
+                       <physicalDescription>\r
+                               <extent>\r
+                                       <xsl:value-of select="."/>\r
+                               </extent>\r
+                       </physicalDescription>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedNote">\r
+               <xsl:for-each select="marc:subfield[@code='n']">\r
+                       <note>\r
+                               <xsl:value-of select="."/>\r
+                       </note>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedIdentifierISSN">\r
+               <xsl:for-each select="marc:subfield[@code='x']">\r
+                       <identifier type="issn">\r
+                               <xsl:value-of select="."/>\r
+                       </identifier>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedIdentifierLocal">\r
+               <xsl:for-each select="marc:subfield[@code='w']">\r
+                       <identifier type="local">\r
+                               <xsl:value-of select="."/>\r
+                       </identifier>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedIdentifier">\r
+               <xsl:for-each select="marc:subfield[@code='o']">\r
+                       <identifier>\r
+                               <xsl:value-of select="."/>\r
+                       </identifier>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedItem76X-78X">\r
+               <xsl:call-template name="relatedTitle76X-78X"/>\r
+               <xsl:call-template name="relatedName"/>\r
+               <xsl:call-template name="relatedExtent"/>\r
+               <xsl:call-template name="relatedIdentifier"/>\r
+               <xsl:call-template name="relatedIdentifierISSN"/>\r
+               <xsl:call-template name="relatedIdentifierLocal"/>\r
+               <xsl:call-template name="relatedNote"/>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="subjectGeographicZ">\r
+               <geographic>\r
+                       <xsl:value-of select="."/>\r
+               </geographic>                   \r
+       </xsl:template>\r
+\r
+       <xsl:template name="subjectTemporalY">\r
+               <temporal>\r
+                       <xsl:value-of select="."/>\r
+               </temporal>                     \r
+       </xsl:template>\r
+\r
+       <xsl:template name="subjectTopic">\r
+               <topic>\r
+                       <xsl:call-template name="chopPunctuation">\r
+                               <xsl:with-param name="chopString" select="."/>\r
+                       </xsl:call-template>\r
+               </topic>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="nameABCDN">\r
+               <xsl:for-each select="marc:subfield[@code='a']">\r
+                       <namePart>\r
+                               <xsl:call-template name="chopPunctuation">\r
+                                       <xsl:with-param name="chopString" select="."/>\r
+                               </xsl:call-template>\r
+                       </namePart>                                     \r
+               </xsl:for-each>\r
+               <xsl:for-each select="marc:subfield[@code='b']">\r
+                       <namePart>\r
+                               <xsl:value-of select="."/>\r
+                       </namePart>                                     \r
+               </xsl:for-each>\r
+               <xsl:if test="marc:subfield[@code='c'] or marc:subfield[@code='d'] or marc:subfield[@code='n']">\r
+                       <namePart>\r
+                               <xsl:call-template name="subfieldSelect">\r
+                                       <xsl:with-param name="codes">cdn</xsl:with-param>\r
+                               </xsl:call-template>\r
+                       </namePart>\r
+               </xsl:if>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="nameABCDQ">\r
+               <namePart>\r
+                       <xsl:call-template name="chopPunctuation">\r
+                               <xsl:with-param name="chopString">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </xsl:with-param>\r
+                       </xsl:call-template>\r
+               </namePart>\r
+               <xsl:call-template name="nameDate"/>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="nameACDEQ">\r
+               <namePart>\r
+                       <xsl:call-template name="subfieldSelect">\r
+                               <xsl:with-param name="codes">acdeq</xsl:with-param>\r
+                       </xsl:call-template>\r
+               </namePart>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="constituentOrRelatedType">\r
+               <xsl:attribute name="type">\r
+                       <xsl:choose>\r
+                               <xsl:when test="@ind2=2">constituent</xsl:when>\r
+                               <xsl:otherwise>related</xsl:otherwise>\r
+                       </xsl:choose>\r
+               </xsl:attribute>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedTitle">\r
+               <xsl:for-each select="marc:subfield[@code='t']">\r
+                       <titleInfo>\r
+                               <title>\r
+                                       <xsl:value-of select="."/>\r
+                               </title>\r
+                       </titleInfo>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="relatedTitle76X-78X">\r
+               <titleInfo>\r
+                       <xsl:for-each select="marc:subfield[@code='t']">\r
+                               <title>\r
+                                       <xsl:value-of select="."/>\r
+                               </title>\r
+                       </xsl:for-each>\r
+                       <xsl:for-each select="marc:subfield[@code='g']">\r
+                               <partNumber>\r
+                                       <xsl:value-of select="."/>\r
+                               </partNumber>\r
+                       </xsl:for-each>\r
+               </titleInfo>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="nameDate">\r
+               <xsl:for-each select="marc:subfield[@code='d']">\r
+                       <namePart type="date">\r
+                               <xsl:call-template name="chopPunctuation">\r
+                                       <xsl:with-param name="chopString" select="."/>\r
+                               </xsl:call-template>\r
+                       </namePart>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="subjectAuthority">\r
+               <xsl:attribute name="authority">\r
+                       <xsl:choose>\r
+                       <xsl:when test="@ind2=0">lcsh</xsl:when>\r
+                       <xsl:when test="@ind2=1">lcshac</xsl:when>\r
+                       <xsl:when test="@ind2=2">mesh</xsl:when>\r
+                       <xsl:when test="@ind2=3">csh</xsl:when>\r
+                       <xsl:when test="@ind2=5">nal</xsl:when>\r
+                       <xsl:when test="@ind2=6">rvm</xsl:when>\r
+                       <xsl:when test="@ind2=7"><xsl:value-of select="marc:subfield[@code='2']"/></xsl:when>\r
+                       </xsl:choose>\r
+               </xsl:attribute>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="subjectAnyOrder">\r
+               <xsl:for-each select="marc:subfield[@code='v' or @code='x' or @code='y' or @code='z']">\r
+                       <xsl:choose>\r
+                               <xsl:when test="@code='v'">\r
+                                       <xsl:call-template name="subjectTopic"/>\r
+                               </xsl:when>\r
+                               <xsl:when test="@code='x'">\r
+                                       <xsl:call-template name="subjectTopic"/>\r
+                               </xsl:when>\r
+                               <xsl:when test="@code='y'">\r
+                                       <xsl:call-template name="subjectTemporalY"/>\r
+                               </xsl:when>\r
+                               <xsl:when test="@code='z'">\r
+                                       <xsl:call-template name="subjectGeographicZ"/>\r
+                               </xsl:when>\r
+                       </xsl:choose>\r
+               </xsl:for-each>\r
+       </xsl:template>\r
+\r
+<!--   <xsl:template name="subfieldSelect">\r
+               <xsl:param name="codes"/>\r
+               <xsl:param name="delimeter"><xsl:text> </xsl:text></xsl:param>\r
+               <xsl:variable name="str">\r
+                       <xsl:for-each select="marc:subfield">\r
+                               <xsl:if test="contains($codes, @code)">\r
+                                       <xsl:value-of select="text()"/><xsl:value-of select="$delimeter"/>\r
+                               </xsl:if>\r
+                       </xsl:for-each>\r
+               </xsl:variable>\r
+               <xsl:value-of select="substring($str,1,string-length($str)-string-length($delimeter))"/>\r
+       </xsl:template>\r
+-->\r
+\r
+       <xsl:template name="specialSubfieldSelect">\r
+               <xsl:param name="anyCodes"/>\r
+               <xsl:param name="axis"/>\r
+               <xsl:param name="beforeCodes"/>\r
+               <xsl:param name="afterCodes"/>\r
+               <xsl:variable name="str">\r
+                       <xsl:for-each select="marc:subfield">\r
+                               <xsl:if test="contains($anyCodes, @code) or (contains($beforeCodes,@code) and following-sibling::marc:subfield[@code=$axis]) or (contains($afterCodes,@code) and preceding-sibling::marc:subfield[@code=$axis])">\r
+                                       <xsl:value-of select="text()"/><xsl:text> </xsl:text>\r
+                               </xsl:if>\r
+                       </xsl:for-each>\r
+               </xsl:variable>\r
+               <xsl:value-of select="substring($str,1,string-length($str)-1)"/>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=600]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <name type="personal">\r
+                               <namePart>\r
+                                       <xsl:call-template name="chopPunctuation">\r
+                                               <xsl:with-param name="chopString">\r
+                                                       <xsl:call-template name="subfieldSelect">\r
+                                                               <xsl:with-param name="codes">abcq</xsl:with-param>\r
+                                                       </xsl:call-template>\r
+                                               </xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </namePart>\r
+                               <xsl:call-template name="nameDate"/>\r
+                               <xsl:call-template name="affiliation"/>\r
+                               <xsl:call-template name="role"/>\r
+                       </name>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=610]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <name type="corporate">\r
+                               <xsl:for-each select="marc:subfield[@code='a']">\r
+                                       <namePart>\r
+                                               <xsl:value-of select="."/>\r
+                                       </namePart>\r
+                               </xsl:for-each>\r
+                               <xsl:for-each select="marc:subfield[@code='b']">\r
+                                       <namePart>\r
+                                               <xsl:value-of select="."/>\r
+                                       </namePart>\r
+                               </xsl:for-each>\r
+                               <xsl:if test="marc:subfield[@code='c' or @code='d' or @code='n' or @code='p']">\r
+                                       <namePart>\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">cdnp</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </namePart>\r
+                               </xsl:if>\r
+                               <xsl:call-template name="role"/>\r
+                       </name>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=611]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <name type="conference">\r
+                               <namePart>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdeqnp</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </namePart>\r
+                               <xsl:for-each select="marc:subfield[@code='4']">\r
+                                       <role>\r
+                                               <xsl:value-of select="."/>\r
+                                       </role>\r
+                               </xsl:for-each>\r
+                       </name>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=630]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <titleInfo>\r
+                               <title>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">adfhklor</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                                       <xsl:call-template name="part"/>                        \r
+                               </title>\r
+                       </titleInfo>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=650]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <topic>\r
+                               <xsl:call-template name="chopPunctuation">\r
+                                       <xsl:with-param name="chopString">\r
+                                               <xsl:call-template name="subfieldSelect">\r
+                                                       <xsl:with-param name="codes">abcd</xsl:with-param>\r
+                                               </xsl:call-template>\r
+                                       </xsl:with-param>\r
+                               </xsl:call-template>\r
+                       </topic>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+\r
+       <xsl:template match="marc:datafield[@tag=651]">\r
+               <subject>\r
+                       <xsl:call-template name="subjectAuthority"/>\r
+                       <xsl:for-each select="marc:subfield[@code='a']">\r
+                               <geographic>\r
+                                       <xsl:value-of select="."/>\r
+                               </geographic>                   \r
+                       </xsl:for-each>\r
+                       <xsl:call-template name="subjectAnyOrder"/>\r
+               </subject>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:datafield[@tag=653]">\r
+               <subject>\r
+                       <xsl:for-each select="marc:subfield[@code='a']">\r
+                               <topic>\r
+                                       <xsl:value-of select="."/>\r
+                               </topic>                        \r
+                       </xsl:for-each>\r
+               </subject>\r
+       </xsl:template>\r
+</xsl:stylesheet><!-- Stylus Studio meta-information - (c)1998-2002 eXcelon Corp.\r
+<metaInformation>\r
+<scenarios ><scenario default="yes" name="modstst2" userelativepaths="yes" externalpreview="no" url="..\..\..\..\..\..\marcxml\modstst2.xml" htmlbaseurl="" outputurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="no" name="modstest" userelativepaths="yes" externalpreview="no" url="..\..\..\..\..\..\marcxml\modstest.xml" htmlbaseurl="" outputurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="no" name="Scenario1" userelativepaths="yes" externalpreview="no" url="..\..\..\..\..\..\marcxml\t.xml" htmlbaseurl="" outputurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/></scenarios><MapperInfo srcSchemaPath="" srcSchemaRoot="" srcSchemaPathIsRelative="yes" srcSchemaInterpretAsXML="no" destSchemaPath="" destSchemaRoot="" destSchemaPathIsRelative="yes" destSchemaInterpretAsXML="no"/>\r
+</metaInformation>\r
+-->
\ No newline at end of file
diff --git a/etc/MARC21slim2RDFDC.xsl b/etc/MARC21slim2RDFDC.xsl
new file mode 100644 (file)
index 0000000..2e81677
--- /dev/null
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<xsl:stylesheet version="1.0" xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="marc">\r
+       <xsl:import href="MARC21slimUtils.xsl"/>\r
+       <xsl:output method="xml" indent="yes"/>\r
+       \r
+       <xsl:template match="/">\r
+                       <xsl:apply-templates/>\r
+       </xsl:template>\r
+\r
+       <xsl:template match="marc:record">\r
+               <xsl:variable name="leader" select="marc:leader"/>\r
+               <xsl:variable name="leader6" select="substring($leader,7,1)"/>\r
+               <xsl:variable name="leader7" select="substring($leader,8,1)"/>\r
+               <xsl:variable name="controlField008" select="marc:controlfield[@tag=008]"/>\r
+\r
+         <rdf:Description>\r
+                       <xsl:for-each select="marc:datafield[@tag=245]">\r
+                               <dc:title>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abfghk</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:title>\r
+                       </xsl:for-each>\r
+\r
+       \r
+                       <xsl:for-each select="marc:datafield[@tag=100]|marc:datafield[@tag=110]|marc:datafield[@tag=111]|marc:datafield[@tag=700]|marc:datafield[@tag=710]|marc:datafield[@tag=711]|marc:datafield[@tag=720]">\r
+                               <dc:creator>\r
+                                       <xsl:value-of select="."/>\r
+                               </dc:creator>\r
+                       </xsl:for-each>\r
+\r
+                       <dc:type>               \r
+                               <xsl:if test="$leader7='c'">\r
+                                       <xsl:attribute name="collection">yes</xsl:attribute>\r
+                               </xsl:if>\r
+\r
+                               <xsl:if test="$leader6='d' or $leader6='f' or $leader6='p' or $leader6='t'">\r
+                                       <xsl:attribute name="manuscript">yes</xsl:attribute>\r
+                               </xsl:if>\r
+\r
+                               <xsl:choose>\r
+                                       <xsl:when test="$leader6='a' or $leader6='t'">text</xsl:when>\r
+                                       <xsl:when test="$leader6='e' or $leader6='f'">cartographic</xsl:when>\r
+                                       <xsl:when test="$leader6='c' or $leader6='d'">notated music</xsl:when>\r
+                                       <xsl:when test="$leader6='i' or $leader6='j'">sound recording</xsl:when>\r
+                                       <xsl:when test="$leader6='k'">still image</xsl:when>\r
+                                       <xsl:when test="$leader6='g'">moving image</xsl:when>\r
+                                       <xsl:when test="$leader6='r'">three dimensional object</xsl:when>\r
+                                       <xsl:when test="$leader6='m'">software, multimedia</xsl:when>\r
+                                       <xsl:when test="$leader6='p'">mixed material</xsl:when>\r
+                               </xsl:choose>\r
+                       </dc:type>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=655]">\r
+                               <dc:type>\r
+                                       <xsl:value-of select="."/>\r
+                               </dc:type>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=260]">\r
+                               <dc:publisher>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ab</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:publisher>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=260]/marc:subfield[@code='c']">\r
+                               <dc:date>\r
+                                       <xsl:value-of select="."/>\r
+                               </dc:date>                              \r
+                       </xsl:for-each>\r
+\r
+                       <dc:language>\r
+                               <xsl:value-of select="substring($controlField008,36,3)"/>\r
+                       </dc:language>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=856]/marc:subfield[@code='q']">\r
+                               <dc:format>\r
+                                       <xsl:value-of select="."/>\r
+                               </dc:format>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=520]">\r
+                               <dc:description>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </dc:description>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=521]">\r
+                               <dc:description>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </dc:description>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[500&lt;@tag][@tag&lt;=599][not(@tag=506 or @tag=530 or @tag=540 or @tag=546)]">\r
+                               <dc:description>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </dc:description>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=600]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=610]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=611]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+               \r
+                       <xsl:for-each select="marc:datafield[@tag=630]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=650]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=653]">\r
+                               <dc:subject>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdq</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:subject>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=752]">\r
+                               <dc:coverage>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcd</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:coverage>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=530]">\r
+                               <dc:relation type="original">\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">abcdu</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:relation>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=760]|marc:datafield[@tag=762]|marc:datafield[@tag=765]|marc:datafield[@tag=767]|marc:datafield[@tag=770]|marc:datafield[@tag=772]|marc:datafield[@tag=773]|marc:datafield[@tag=774]|marc:datafield[@tag=775]|marc:datafield[@tag=776]|marc:datafield[@tag=777]|marc:datafield[@tag=780]|marc:datafield[@tag=785]|marc:datafield[@tag=786]|marc:datafield[@tag=787]">\r
+                               <dc:relation>\r
+                                       <xsl:call-template name="subfieldSelect">\r
+                                               <xsl:with-param name="codes">ot</xsl:with-param>\r
+                                       </xsl:call-template>\r
+                               </dc:relation>  \r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=856]">\r
+                               <dc:identifier>\r
+                                       <xsl:value-of select="marc:subfield[@code='u']"/>\r
+                               </dc:identifier>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=506]">\r
+                               <dc:rights>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </dc:rights>\r
+                       </xsl:for-each>\r
+\r
+                       <xsl:for-each select="marc:datafield[@tag=540]">\r
+                               <dc:rights>\r
+                                       <xsl:value-of select="marc:subfield[@code='a']"/>\r
+                               </dc:rights>\r
+                       </xsl:for-each>\r
+               </rdf:Description>\r
+       </xsl:template>\r
+</xsl:stylesheet><!-- Stylus Studio meta-information - (c)1998-2002 eXcelon Corp.\r
+<metaInformation>\r
+<scenarios ><scenario default="no" name="MODS Website Samples" userelativepaths="yes" externalpreview="no" url="..\xml\MARC21slim\modswebsitesamples.xml" htmlbaseurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="no" name="Ray Charles" userelativepaths="yes" externalpreview="no" url="..\xml\MARC21slim\raycharles.xml" htmlbaseurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="yes" name="s6" userelativepaths="yes" externalpreview="no" url="..\ifla\sally6.xml" htmlbaseurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="no" name="s7" userelativepaths="yes" externalpreview="no" url="..\ifla\sally7.xml" htmlbaseurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/><scenario default="no" name="s12" userelativepaths="yes" externalpreview="no" url="..\ifla\sally12.xml" htmlbaseurl="" processortype="internal" commandline="" additionalpath="" additionalclasspath="" postprocessortype="none" postprocesscommandline="" postprocessadditionalpath="" postprocessgeneratedext=""/></scenarios><MapperInfo srcSchemaPath="" srcSchemaRoot="" srcSchemaPathIsRelative="yes" srcSchemaInterpretAsXML="no" destSchemaPath="" destSchemaRoot="" destSchemaPathIsRelative="yes" destSchemaInterpretAsXML="no"/>\r
+</metaInformation>\r
+-->
\ No newline at end of file
diff --git a/etc/MARC21slimUtils.xsl b/etc/MARC21slimUtils.xsl
new file mode 100644 (file)
index 0000000..acfe598
--- /dev/null
@@ -0,0 +1,65 @@
+<?xml version='1.0'?>\r
+<xsl:stylesheet version="1.0" xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">\r
+       <xsl:template name="datafield">\r
+               <xsl:param name="tag"/>\r
+               <xsl:param name="ind1"><xsl:text> </xsl:text></xsl:param>\r
+               <xsl:param name="ind2"><xsl:text> </xsl:text></xsl:param>\r
+               <xsl:param name="subfields"/>\r
+               <xsl:element name="datafield">\r
+                       <xsl:attribute name="tag">\r
+                               <xsl:value-of select="$tag"/>\r
+                       </xsl:attribute>\r
+                       <xsl:attribute name="ind1">\r
+                               <xsl:value-of select="$ind1"/>\r
+                       </xsl:attribute>\r
+                       <xsl:attribute name="ind2">\r
+                               <xsl:value-of select="$ind2"/>\r
+                       </xsl:attribute>\r
+                       <xsl:copy-of select="$subfields"/>\r
+               </xsl:element>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="subfieldSelect">\r
+               <xsl:param name="codes"/>\r
+               <xsl:param name="delimeter"><xsl:text> </xsl:text></xsl:param>\r
+               <xsl:variable name="str">\r
+                       <xsl:for-each select="marc:subfield">\r
+                               <xsl:if test="contains($codes, @code)">\r
+                                       <xsl:value-of select="text()"/><xsl:value-of select="$delimeter"/>\r
+                               </xsl:if>\r
+                       </xsl:for-each>\r
+               </xsl:variable>\r
+               <xsl:value-of select="substring($str,1,string-length($str)-string-length($delimeter))"/>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="buildSpaces">\r
+               <xsl:param name="spaces"/>\r
+               <xsl:param name="char"><xsl:text> </xsl:text></xsl:param>\r
+               <xsl:if test="$spaces>0">\r
+                       <xsl:value-of select="$char"/>\r
+                       <xsl:call-template name="buildSpaces">\r
+                               <xsl:with-param name="spaces" select="$spaces - 1"/>\r
+                               <xsl:with-param name="char" select="$char"/>\r
+                       </xsl:call-template>\r
+               </xsl:if>\r
+       </xsl:template>\r
+\r
+       <xsl:template name="chopPunctuation">\r
+               <xsl:param name="chopString"/>\r
+               <xsl:variable name="length" select="string-length($chopString)"/>\r
+               <xsl:choose>\r
+                       <xsl:when test="$length=0"/>\r
+                       <xsl:when test="contains('.:,;/ ', substring($chopString,$length,1))">\r
+                               <xsl:call-template name="chopPunctuation">\r
+                                       <xsl:with-param name="chopString" select="substring($chopString,1,$length - 1)"/>\r
+                               </xsl:call-template>\r
+                       </xsl:when>\r
+                       <xsl:when test="not($chopString)"/>\r
+                       <xsl:otherwise><xsl:value-of select="$chopString"/></xsl:otherwise>\r
+               </xsl:choose>\r
+       </xsl:template>\r
+</xsl:stylesheet><!-- Stylus Studio meta-information - (c)1998-2002 eXcelon Corp.\r
+<metaInformation>\r
+<scenarios/><MapperInfo srcSchemaPath="" srcSchemaRoot="" srcSchemaPathIsRelative="yes" srcSchemaInterpretAsXML="no" destSchemaPath="" destSchemaRoot="" destSchemaPathIsRelative="yes" destSchemaInterpretAsXML="no"/>\r
+</metaInformation>\r
+-->
\ No newline at end of file
diff --git a/etc/Makefile.am b/etc/Makefile.am
new file mode 100644 (file)
index 0000000..fa4b417
--- /dev/null
@@ -0,0 +1,9 @@
+# $Id: Makefile.am,v 1.1 2003-01-06 08:20:27 adam Exp $
+
+EXTRA_DIST=maps.xml \
+ MARC21slim2DC.xsl \
+ MARC21slim2MODS.xsl \
+ MARC21slim2RDFDC.xsl \
+ MARC21slimUtils.xsl \
+ pqf.properties
+
diff --git a/etc/maps.xml b/etc/maps.xml
new file mode 100644 (file)
index 0000000..72c7227
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0"?>
+<!-- 
+  $Id: maps.xml,v 1.1 2003-01-06 08:20:27 adam Exp $
+  XSLT for each schema conversion.
+-->
+<schema-mappings xmlns="http://indexdata.dk/srw/schema-mappings/v1.0/">
+ <map>
+   <schema source="MARC21"/>
+   <schema target="http://www.loc.gov/marcxml/"/>
+ </map>
+ <map>
+   <schema source="MARC21"/>
+   <schema target="http://www.loc.gov/MARC21/slim"/>
+ </map>
+ <map>
+   <schema source="MARC21"/>
+   <schema target="http://www.loc.gov/zing/srw/dcschema/v1.0/"/>
+   <schema alias="dc"/>
+   <schema alias="DC"/>
+   <stylesheet filename="MARC21slim2DC.xsl"/>
+ </map>
+ <map>
+   <schema source="MARC21"/>
+   <schema target="rdfdc"/>
+   <schema alias="RDFDC"/>
+   <stylesheet filename="MARC21slim2RDFDC.xsl"/>
+ </map>
+ <map>
+   <schema source="MARC21"/>
+   <schema target="http://www.loc.gov/mods/"/>
+   <schema alias="mods"/>
+   <schema alias="MODS"/>
+   <stylesheet filename="MARC21slim2MODS.xsl"/>
+ </map>
+</schema-mappings>
diff --git a/etc/pqf.properties b/etc/pqf.properties
new file mode 100644 (file)
index 0000000..76f046b
--- /dev/null
@@ -0,0 +1,111 @@
+# $Id: pqf.properties,v 1.1 2003-01-06 08:20:27 adam Exp $
+#
+# Propeties file to drive org.z3950.zing.cql.CQLNode's toPQF()
+# back-end.  This specifies the interpretation of various CQL
+# qualifiers, relations, etc. in terms of Type-1 query attributes.
+#
+# See http://www.loc.gov/z3950/agency/zing/cql/dc-indexes.html
+# for the Maintenance Agency's work-in-progress mapping of Dublic Core
+# qualifiers to Attribute Architecture (util, XD and BIB-2)
+# attributes.
+
+# Identifiers for prefixes used in this file. (qualifier.*)
+set.srw                = http://www.loc.gov/zing/cql/srw-indexes/v1.0/
+set.dc         = http://www.loc.gov/zing/cql/dc-indexes/v1.0/
+# default set (in query)
+set             = http://www.loc.gov/zing/cql/dc-indexes/v1.0/
+
+# The default access point and result-set references
+qualifier.srw.serverChoice             = 1=1016
+       # "any"
+
+qualifier.dc.title                     = 1=4
+qualifier.dc.subject                   = 1=21
+qualifier.dc.creator                   = 1=1003
+qualifier.dc.author                    = 1=1003
+       ### Unofficial synonym for "creator"
+qualifier.dc.editor                    = 1=1020
+qualifier.dc.publisher                 = 1=1018
+qualifier.dc.description               = 1=62
+       # "abstract"
+qualifier.dc.date                      = 1=30
+qualifier.dc.resourceType              = 1=1031
+       # guesswork: "Material-type"
+qualifier.dc.format                    = 1=1034
+       # guesswork: "Content-type"
+qualifier.dc.resourceIdentifier                = 1=12
+       # "Local number"
+qualifier.dc.source                    = 1=1019
+       # "Record-source"
+qualifier.dc.language                  = 1=54
+       # "Code--language"
+qualifier.dc.relation                  = 1=?
+       ### No idea how to represent this
+qualifier.dc.coverage                  = 1=?
+       ### No idea how to represent this
+qualifier.dc.rights                    = 1=?
+       ### No idea how to represent this
+
+### These aren't right: I've just put them here for the Generator
+qualifier.bath.subject                 = 1=21
+qualifier.bath.author                  = 1=1003
+qualifier.foo>bar                      = 1=2000
+
+# Relation attributes are selected according to the CQL relation by
+# looking up the "relation.<relation>" property:
+#
+relation.<                             = 2=1
+relation.le                            = 2=2
+relation.eq                            = 2=3
+relation.exact                         = 2=3
+relation.ge                            = 2=4
+relation.>                             = 2=5
+relation.<>                            = 2=6
+
+### These two are not really right:
+relation.all                           = 2=3
+relation.any                           = 2=3
+
+# BIB-1 doesn't have a server choice relation, so we just make the
+# choice here, and use equality (which is clearly correct).
+relation.scr                           = 2=3
+
+# Relation modifiers.
+#
+relationModifier.relevant              = 2=102
+relationModifier.fuzzy                 = 2=100
+       ### 100 is "phonetic", which is not quite the same thing
+relationModifier.stem                  = 2=101
+relationModifier.phonetic              = 2=100
+
+# Position attributes may be specified for anchored terms (those
+# beginning with "^", which is stripped) and unanchored (those not
+# beginning with "^").  This may change when we get a BIB-1 truncation
+# attribute that says "do what CQL does".
+#
+position.first                         = 3=1 6=1
+       # "first in field"
+position.any                           = 3=3 6=1
+       # "any position in field"
+position.last                          = 3=4 6=1
+       # not a standard BIB-1 attribute
+position.firstAndLast                  = 3=3 6=3
+       # search term is anchored to be complete field
+
+# Structure attributes may be specified for individual relations; a
+# default structure attribute my be specified by the pseudo-relation
+# "*", to be used whenever a relation not listed here occurs.
+#
+structure.exact                                = 4=108
+       # string
+structure.all                          = 4=2
+structure.any                          = 4=2
+structure.*                            = 4=1
+       # phrase
+
+# Finally, any additional attributes that should always be included
+# with each term can be specified in the "always" property.
+#
+always                                 = 5=105 6=1
+# 5=105: the not-yet-standarised CQL-like trunction attribute
+# 6=1: completeness = incomplete subfield
index 275489a..5bf7713 100644 (file)
@@ -1,8 +1,8 @@
-## $Id: Makefile.am,v 1.18 2002-12-16 13:13:53 adam Exp $
+## $Id: Makefile.am,v 1.19 2003-01-06 08:20:27 adam Exp $
 
-pkginclude_HEADERS= backend.h ccl.h comstack.h \
+pkginclude_HEADERS= backend.h ccl.h cql.h comstack.h \
  diagbib1.h sortspec.h log.h logrpn.h marcdisp.h nmem.h odr.h oid.h \
- options.h otherinfo.h pquery.h prt-ext.h readconf.h statserv.h \
+ options.h otherinfo.h pquery.h prt-ext.h readconf.h srw-util.h statserv.h \
  tcpip.h unix.h tpath.h wrbuf.h xmalloc.h \
  yaz-ccl.h yaz-iconv.h yaz-util.h yaz-version.h yconfig.h proto.h \
  \
index 866b468..27343c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: backend.h,v 1.16 2002-09-16 10:48:06 adam Exp $
+ * $Id: backend.h,v 1.17 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef BACKEND_H
diff --git a/include/yaz/cql.h b/include/yaz/cql.h
new file mode 100644 (file)
index 0000000..9ae7b6b
--- /dev/null
@@ -0,0 +1,199 @@
+/* $Id: cql.h,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#ifndef CQL_H_INCLUDED
+#define CQL_H_INCLUDED
+#include <stdio.h>
+
+typedef struct cql_parser *CQL_parser;
+
+/**
+ * cql_parser_create:
+ *
+ * creates a CQL parser.
+ *
+ * Returns CQL parser or NULL if parser could not be created.
+ */
+CQL_parser cql_parser_create(void);
+
+/**
+ * cql_parser_destroy:
+ * @cp:  A CQL parser
+ *
+ * Destroy CQL parser. This function does nothing if
+ * NULL pointer is received.
+ */
+void cql_parser_destroy(CQL_parser cp);
+
+/**
+ * cql_parser_string:
+ * @cp:  A CQL parser.
+ * @str:  A query string to be parsed.
+ *
+ * Parses a CQL query string.
+ *
+ * Returns 0 if parsing was succesful; non-zero (error code) if
+ * unsuccesful.
+ */
+int cql_parser_string(CQL_parser cp, const char *str);
+
+/**
+ * cql_parser_stream:
+ * @cp:  A CQL parser.
+ * @getbyte:  Handler to read one character (for parsing).
+ * @ungetbyte: Handler to unread one byte (for parsing).
+ * @client_data:  User data associated with getbyte/ungetbyte handlers.
+ *
+ * Parses a CQL query from a user defined stream.
+ *
+ * Returns 0 if parsing was succesful; non-zero (error code) if
+ * unsuccesful.
+ */
+int cql_parser_stream(CQL_parser cp,
+                      int (*getbyte)(void *client_data),
+                      void (*ungetbyte)(int b, void *client_data),
+                      void *client_data);
+
+/**
+ * cql_parser_stdio:
+ * @cp:  A CQL parser.
+ * @f: FILE handler in read mode.
+ *
+ * Parses a CQL query from a file.
+ *
+ * Returns 0 if parsing was succesful; non-zero (error code) if
+ * unsuccesful.
+ */
+int cql_parser_stdio(CQL_parser cp, FILE *f);
+
+#define CQL_NODE_ST 1
+#define CQL_NODE_BOOL 2
+#define CQL_NODE_MOD 3
+struct cql_node {
+    int which;
+    union {
+        struct {
+            char *index;
+            char *term;
+            char *relation;
+            struct cql_node *modifiers;
+            struct cql_node *prefixes;
+        } st;
+        struct {
+            char *value;
+            struct cql_node *left;
+            struct cql_node *right;
+            struct cql_node *modifiers;
+            struct cql_node *prefixes;
+        } bool;
+        struct {
+            char *name;
+            char *value;
+            struct cql_node *next;
+        } mod;
+    } u;
+};
+
+struct cql_properties;
+
+struct cql_buf_write_info {
+    int max;
+    int off;
+    char *buf;
+};
+
+void cql_buf_write_handler (const char *b, void *client_data);
+
+void cql_node_print(struct cql_node *cn);
+struct cql_node *cql_node_mk_sc(const char *index,
+                                const char *relation,
+                                const char *term);
+struct cql_node *cql_node_mk_boolean(const char *op);
+void cql_node_destroy(struct cql_node *cn);
+struct cql_node *cql_node_prefix(struct cql_node *n, const char *prefix,
+                                 const char *uri);
+struct cql_node *cql_node_mk_mod(const char *name,
+                                 const char *value);
+
+struct cql_node *cql_node_dup (struct cql_node *cp);
+struct cql_node *cql_parser_result(CQL_parser cp);
+
+void cql_to_xml(struct cql_node *cn, 
+                void (*pr)(const char *buf, void *client_data),
+                void *client_data);
+void cql_to_xml_stdio(struct cql_node *cn, FILE *f);
+int cql_to_xml_buf(struct cql_node *cn, char *out, int max);
+
+struct cql_node *cql_node_mk_proxargs(const char *relation,
+                                      const char *distance,
+                                      const char *unit,
+                                      const char *ordering);
+
+
+void cql_fputs(const char *buf, void *client_data);
+
+typedef struct cql_transform_t_ *cql_transform_t;
+
+cql_transform_t cql_transform_open_FILE (FILE *f);
+cql_transform_t cql_transform_open_fname(const char *fname);
+void cql_transform_close(cql_transform_t ct);
+
+void cql_transform_pr(cql_transform_t ct,
+                      struct cql_node *cn,
+                      void (*pr)(const char *buf, void *client_data),
+                      void *client_data);
+
+int cql_transform_FILE(cql_transform_t ct,
+                       struct cql_node *cn, FILE *f);
+
+int cql_transform_buf(cql_transform_t ct,
+                      struct cql_node *cn, char *out, int max);
+int cql_transform_error(cql_transform_t ct, const char **addinfo);
+
+/*
+10 Illegal query
+11 Unsupported query type (XCQL vs CQL)
+12 Too many characters in query
+13 Unbalanced or illegal use of parentheses
+14 Unbalanced or illegal use of quotes
+15 Illegal or unsupported index set
+16 Illegal or unsupported index
+17 Illegal or unsupported combination of index and index set
+18 Illegal or unsupported combination of indexes
+19 Illegal or unsupported relation
+20 Illegal or unsupported relation modifier
+21 Illegal or unsupported combination of relation modifers
+22 Illegal or unsupported combination of relation and index
+23 Too many characters in term
+24 Illegal combination of relation and term
+25 Special characters not quoted in term
+26 Non special character escaped in term
+27 Empty term unsupported
+28 Masking character not supported
+29 Masked words too short
+30 Too many masking characters in term
+31 Anchoring character not supported
+32 Anchoring character in illegal or unsupported position
+33 Combination of proximity/adjacency and masking characters not supported
+34 Combination of proximity/adjacency and anchoring characters not supported
+35 Terms only exclusion (stop) words
+36 Term in invalid format for index or relation
+37 Illegal or unsupported boolean operator
+38 Too many boolean operators in query
+39 Proximity not supported
+40 Illegal or unsupported proximity relation
+41 Illegal or unsupported proximity distance
+42 Illegal or unsupported proximity unit
+43 Illegal or unsupported proximity ordering
+44 Illegal or unsupported combination of proximity modifiers
+45 Index set name (prefix) assigned to multiple identifiers
+*/
+
+#endif
+/* CQL_H_INCLUDED */
index 6b41af3..6925d78 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: log.h,v 1.7 2002-08-29 09:58:42 adam Exp $
+ * $Id: log.h,v 1.8 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef LOG_H
index e5e7552..d1f4c07 100644 (file)
@@ -4,7 +4,10 @@
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: logrpn.h,v $
- * Revision 1.2  2000-02-28 11:20:06  adam
+ * Revision 1.3  2003-01-06 08:20:27  adam
+ * SRW, CQL, 2003
+ *
+ * Revision 1.2  2000/02/28 11:20:06  adam
  * Using autoconf. New definitions: YAZ_BEGIN_CDECL/YAZ_END_CDECL.
  *
  * Revision 1.1  1999/11/30 13:47:11  adam
@@ -26,6 +29,7 @@ YAZ_BEGIN_CDECL
 
 YAZ_EXPORT void log_rpn_query (Z_RPNQuery *rpn);
 YAZ_EXPORT void log_scan_term (Z_AttributesPlusTerm *zapt, oid_value ast);
+YAZ_EXPORT void yaz_log_zquery (Z_Query *q);
 
 YAZ_END_CDECL
 
index 3760a2f..afbe121 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: marcdisp.h,v 1.7 2002-12-16 13:13:53 adam Exp $
+ * $Id: marcdisp.h,v 1.8 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef MARCDISP_H
index 1a0a260..2a11b2b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: nmem.h,v 1.9 2002-12-05 12:19:23 adam Exp $
+ * $Id: nmem.h,v 1.10 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef NMEM_H
index 895d635..629b7f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: odr.h,v 1.6 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr.h,v 1.7 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef ODR_H
index e418f6c..d9f18df 100644 (file)
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: oid.h,v 1.12 2002-08-30 15:39:40 mike Exp $
+ * $Id: oid.h,v 1.13 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef OID_H
@@ -209,6 +209,7 @@ typedef enum oid_value
     VAL_IDXPATH,
     VAL_BIB2,
     VAL_ZEEREX,
+    VAL_CQL,
 
 /* VAL_DYNAMIC must have highest value */
     VAL_DYNAMIC,
index 5237b7e..bbb6975 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: pquery.h,v 1.3 2002-09-02 13:59:07 adam Exp $
+ * $Id: pquery.h,v 1.4 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef PQUERY_H
index 2350c57..cf3858b 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1998-2002, Index Data
+ * Copyright (c) 1998-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: proto.h,v 1.5 2002-12-05 12:07:00 adam Exp $
+ * $Id: proto.h,v 1.6 2003-01-06 08:20:27 adam Exp $
  */
 #ifndef Z_PROTO_H
 #define Z_PROTO_H
index 9bfd485..48bacb1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -85,6 +85,7 @@ struct Z_External
 #define Z_External_acfDes1 24
 #define Z_External_acfKrb1 25
 #define Z_External_multisrch2 26
+#define Z_External_CQL 27
     union
     {
        /* Generic types */
@@ -122,6 +123,7 @@ struct Z_External
 
         Z_KRBObject *acfKrb1;
         Z_MultipleSearchTerms_2 *multipleSearchTerms_2;
+        Z_InternationalString *cql;
     } u;
 };
 
diff --git a/include/yaz/srw-util.h b/include/yaz/srw-util.h
new file mode 100644 (file)
index 0000000..6e03390
--- /dev/null
@@ -0,0 +1,48 @@
+/* $Id: srw-util.h,v 1.1 2003-01-06 08:20:27 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include "srw_H.h"
+#include <yaz/cql.h>
+struct cql_node *xcql_to_cqlnode(struct xcql__operandType *p);
+
+typedef struct xslt_maps_info *xslt_maps;
+typedef struct xslt_map_result_info *xslt_map_result;
+
+xslt_maps xslt_maps_create(void);
+int xslt_maps_file(xslt_maps m, const char *f);
+void xslt_maps_free(xslt_maps m);
+
+xslt_map_result xslt_map (xslt_maps m, const char *schema_source,
+                          const char *scheme_target,
+                          const char *in_buf, int in_len);
+void xslt_map_free (xslt_map_result res);
+
+char *xslt_map_result_buf(xslt_map_result res);
+int xslt_map_result_len(xslt_map_result res);
+char *xslt_map_result_schema(xslt_map_result res);
+const char *yaz_srw_diag_str (int code);
+
+void yaz_srw_serve (struct soap *soap,
+                    void *userinfo,
+                    int (*sr_h)(void *userinfo,
+                                struct soap * soap,
+                                xsd__string  *query,
+                                struct xcql__operandType *xQuery,      
+                                xsd__string *sortKeys,
+                                struct xsort__xSortKeysType *xSortKeys,
+                                xsd__integer *startRecord,
+                                xsd__integer *maximumRecords,
+                                xsd__string *recordSchema,
+                                xsd__string *recordPacking,
+                                struct zs__searchRetrieveResponse *res),
+                    int (*e_h)(void *userinfo,
+                               struct soap *soap,
+                               struct zs__explainResponse *explainResponse));
+
+extern struct Namespace srw_namespaces[];
index 5f9e907..e6b240e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: tpath.h,v 1.4 2002-04-05 12:46:07 adam Exp $
+ * $Id: tpath.h,v 1.5 2003-01-06 08:20:27 adam Exp $
  *
  */
 
index 93998af..7b7054b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: unix.h,v 1.1 2002-06-04 11:36:11 adam Exp $
+ * $Id: unix.h,v 1.2 2003-01-06 08:20:27 adam Exp $
  * UNIX socket COMSTACK. By Morten Bøgeskov.
  * 
  */
index 79c568d..3b6258d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: wrbuf.h,v 1.7 2002-12-03 10:03:27 adam Exp $
+ * $Id: wrbuf.h,v 1.8 2003-01-06 08:20:27 adam Exp $
  *
  */
 
index 5b4dd5f..a039280 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: yaz-iconv.h,v 1.1 2002-12-16 13:13:53 adam Exp $
+ * $Id: yaz-iconv.h,v 1.2 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef YAZ_ICONV_H
index bbba458..8db1ed7 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: yaz-util.h,v 1.7 2002-12-16 13:13:53 adam Exp $
+ * $Id: yaz-util.h,v 1.8 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef YAZ_UTIL_H
index f0a9b74..956bd51 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Public header for ZOOM C.
- * $Id: zoom.h,v 1.15 2002-12-09 23:32:29 adam Exp $
+ * $Id: zoom.h,v 1.16 2003-01-06 08:20:27 adam Exp $
  */
 
 #include <yaz/yconfig.h>
@@ -92,6 +92,7 @@ ZOOM_diag_str (int error);
 #define ZOOM_ERROR_INIT 10005
 #define ZOOM_ERROR_INTERNAL 10006
 #define ZOOM_ERROR_TIMEOUT 10007
+#define ZOOM_ERROR_UNSUPPORTED_PROTOCOL 10008
 
 ZOOM_API(int)
 ZOOM_connection_last_event(ZOOM_connection cs);
@@ -166,7 +167,10 @@ ZOOM_query_create(void);
 /* destroy it */
 ZOOM_API(void)
 ZOOM_query_destroy(ZOOM_query s);
-/* specify prefix query for search */
+/* CQL */
+ZOOM_API(int)
+ZOOM_query_cql(ZOOM_query s, const char *str);
+/* PQF */
 ZOOM_API(int)
 ZOOM_query_prefix(ZOOM_query s, const char *str);
 /* specify sort criteria for search */
index ca46b69..8fd9e3b 100644 (file)
@@ -1,4 +1,10 @@
-## $Id: Makefile.am,v 1.24 2002-10-22 12:51:18 adam Exp $
+## $Id: Makefile.am,v 1.25 2003-01-06 08:20:27 adam Exp $
+
+if SRW
+libsrw=../srw/libsrw.la
+else
+libsrw=
+endif
 
 if ISTHR
 extra=libyazthread.la
@@ -74,6 +80,6 @@ tcpip.o: $(top_srcdir)/comstack/tcpip.c
 
 libyaz_la_LIBADD=../odr/libodr.la \
  ../comstack/libcomstack.la ../server/libserver.la \
- ../util/libutil.la ../ccl/libccl.la ../zutil/libzutil.la \
- ../ill/libill.la ../z39.50/libz39.50.la
+ ../util/libutil.la ../ccl/libccl.la ../cql/libcql.la ../zutil/libzutil.la \
+ ../ill/libill.la ../z39.50/libz39.50.la $(libsrw)
 
index 6ae67d0..1280040 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: ber_any.c,v 1.19 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_any.c,v 1.20 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 1733226..e82c2d5 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_bit.c,v 1.13 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_bit.c,v 1.14 2003-01-06 08:20:27 adam Exp $
  *
  */
 #if HAVE_CONFIG_H
index 289d681..20a8a35 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_bool.c,v 1.12 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_bool.c,v 1.13 2003-01-06 08:20:27 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index 6fa7a41..e5a59ab 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_int.c,v 1.20 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_int.c,v 1.21 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 6fd3f9b..88602bd 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 1995-2002, Index Data.
+ * Copyright (C) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_len.c,v 1.10 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_len.c,v 1.11 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index bd334c9..a883a81 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_null.c,v 1.12 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_null.c,v 1.13 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 4f04960..e2ba432 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_oct.c,v 1.19 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_oct.c,v 1.20 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 0f48b31..0f744fa 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_oid.c,v 1.13 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_oid.c,v 1.14 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 61a6872..9172075 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: ber_tag.c,v 1.23 2002-07-25 12:51:08 adam Exp $
+ * $Id: ber_tag.c,v 1.24 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 1fbdecf..de57132 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: dumpber.c,v 1.13 2002-07-25 12:51:08 adam Exp $
+ * $Id: dumpber.c,v 1.14 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index d8ad03c..0c60940 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation, in whole or in part, for any purpose, is hereby granted,
@@ -23,7 +23,7 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  * OF THIS SOFTWARE.
  *
- * $Id: odr-priv.h,v 1.2 2002-08-28 07:53:51 adam Exp $
+ * $Id: odr-priv.h,v 1.3 2003-01-06 08:20:27 adam Exp $
  */
 
 #ifndef ODR_PRIV_H
index a0f34e1..22f9b21 100644 (file)
--- a/odr/odr.c
+++ b/odr/odr.c
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: odr.c,v 1.38 2002-09-24 08:05:41 adam Exp $
+ * $Id: odr.c,v 1.39 2003-01-06 08:20:27 adam Exp $
  *
  */
 #if HAVE_CONFIG_H
index 3c5c067..aa5b08f 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_any.c,v 1.11 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_any.c,v 1.12 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index aa10414..0a1426f 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_bit.c,v 1.15 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_bit.c,v 1.16 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 597293c..f1cb60a 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_bool.c,v 1.13 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_bool.c,v 1.14 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index d752714..15ef87c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_choice.c,v 1.20 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_choice.c,v 1.21 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 0bda85a..b02842b 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: odr_cons.c,v 1.23 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_cons.c,v 1.24 2003-01-06 08:20:27 adam Exp $
  *
  */
 #if HAVE_CONFIG_H
index b60014b..8dc6e84 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_enum.c,v 1.6 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_enum.c,v 1.7 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 3637174..04ffbee 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_int.c,v 1.16 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_int.c,v 1.17 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 9b2c7cc..a032d4b 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: odr_mem.c,v 1.20 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_mem.c,v 1.21 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 8158421..76e3b05 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_null.c,v 1.14 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_null.c,v 1.15 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index b1c400d..73b7088 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_oct.c,v 1.19 2002-09-24 08:05:41 adam Exp $
+ * $Id: odr_oct.c,v 1.20 2003-01-06 08:20:27 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index cbb968e..5081f73 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_oid.c,v 1.17 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_oid.c,v 1.18 2003-01-06 08:20:28 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 191b97e..c23614b 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_seq.c,v 1.28 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_seq.c,v 1.29 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index 288403b..6fa0eb4 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_tag.c,v 1.12 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_tag.c,v 1.13 2003-01-06 08:20:28 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 972d5f7..5ae1e9c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: odr_use.c,v 1.12 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_use.c,v 1.13 2003-01-06 08:20:28 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 5f7d7e5..3f450ca 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: odr_util.c,v 1.21 2002-07-25 12:51:08 adam Exp $
+ * $Id: odr_util.c,v 1.22 2003-01-06 08:20:28 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index 90b1a70..59361f5 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: seshigh.c,v 1.132 2002-09-25 12:37:07 adam Exp $
+ * $Id: seshigh.c,v 1.133 2003-01-06 08:20:28 adam Exp $
  */
 
 /*
@@ -1047,11 +1047,8 @@ static Z_APDU *process_searchRequest(association *assoc, request *reqb,
        for (i = 0; i < req->num_databaseNames; i++)
            yaz_log (LOG_LOG, "Database '%s'", req->databaseNames[i]);
     }
-    switch (req->query->which)
-    {
-    case Z_Query_type_1: case Z_Query_type_101:
-       log_rpn_query (req->query->u.type_1);
-    }
+    yaz_log_zquery(req->query);
+
     if (assoc->init->bend_search)
     {
        bsrr->setname = req->resultSetName;
@@ -1593,7 +1590,7 @@ int bend_backend_respond (bend_association a, bend_request req)
     int r;
     r = process_request (a, req, &msg);
     if (r < 0)
-       logf (LOG_WARN, "%s", msg);
+       yaz_log (LOG_WARN, "%s", msg);
     return r;
 }
 
index 45d5cb0..6e8f8b0 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 1995-2002, Index Data
+ * Copyright (C) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: session.h,v 1.26 2002-11-26 13:15:42 adam Exp $
+ * $Id: session.h,v 1.27 2003-01-06 08:20:28 adam Exp $
  */
 
 #ifndef SESSION_H
index c694443..5922a2b 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * NT threaded server code by
  *   Chas Woodfield, Fretwell Downing Informatics.
  *
- * $Id: statserv.c,v 1.87 2002-11-26 16:04:15 adam Exp $
+ * $Id: statserv.c,v 1.88 2003-01-06 08:20:28 adam Exp $
  */
 
 #include <stdio.h>
@@ -719,7 +719,7 @@ int statserv_start(int argc, char **argv)
        inetd_connection(control_block.default_proto);
     else
     {
-       logf (LOG_LOG, "Starting server %s pid=%d", me, getpid());
+       yaz_log (LOG_LOG, "Starting server %s pid=%d", me, getpid());
 #if 0
        sigset_t sigs_to_block;
        
diff --git a/srw/.cvsignore b/srw/.cvsignore
new file mode 100644 (file)
index 0000000..9db4dc3
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+Makefile
+Makefile.in
+srw_*
+*.lo
+*.la
diff --git a/srw/Makefile.am b/srw/Makefile.am
new file mode 100644 (file)
index 0000000..bb4c9fc
--- /dev/null
@@ -0,0 +1,28 @@
+# $Id: Makefile.am,v 1.1 2003-01-06 08:20:28 adam Exp $
+AM_CPPFLAGS = -I$(top_srcdir)/include $(GSOAP_INCLUDE) $(XSLT_CFLAGS)
+
+if SRW
+noinst_LTLIBRARIES = libsrw.la
+endif
+
+libsrw_la_SOURCES = srw_C.c srw-namespace.c srw-xcql.c srw-xslt.c srw_Client.c srw-diag.c srw-server.c srw_Server.c
+
+include_HEADERS = srw_H.h srw_Stub.h 
+
+LDADD = $(GSOAP_LIB)
+
+EXTRA_DIST = zing.h
+
+# Dependency for stdsoap2.h needed!
+stdsoap2.h srw_C.c srw_Client.c srw_Server.c srw_H.h srw_Stub.h: zing.h
+       $(GSOAP_PREFIX)/bin/soapcpp2 -p srw_ -c zing.h
+
+srw-namespace.o: srw_H.h
+
+srw_C.o: srw_C.c
+       $(COMPILE) -c soapC.c 
+srw_Client.o: soapClient.c
+       $(COMPILE) -c srw_Client.c 
+srw_Server.o: srw_Server.c
+       $(COMPILE) -c srw_Server.c 
+
diff --git a/srw/srw-diag.c b/srw/srw-diag.c
new file mode 100644 (file)
index 0000000..e514c95
--- /dev/null
@@ -0,0 +1,108 @@
+/* $Id: srw-diag.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <yaz/srw-util.h>
+
+static struct {
+    int code;
+    char *msg;
+} msg_tab[] = {
+/* General Diagnostics*/
+{1, "Permanent system error"},
+{2, "System temporarily unavailable"},
+{3, "Authentication error"},
+/* Diagnostics Relating to CQL*/
+{10, "Illegal query"},
+{11, "Unsupported query type (XCQL vs CQL)"},
+{12, "Too many characters in query"},
+{13, "Unbalanced or illegal use of parentheses"},
+{14, "Unbalanced or illegal use of quotes"},
+{15, "Illegal or unsupported index set"},
+{16, "Illegal or unsupported index"},
+{17, "Illegal or unsupported combination of index and index set"},
+{18, "Illegal or unsupported combination of indexes"},
+{19, "Illegal or unsupported relation"},
+{20, "Illegal or unsupported relation modifier"},
+{21, "Illegal or unsupported combination of relation modifers"},
+{22, "Illegal or unsupported combination of relation and index"},
+{23, "Too many characters in term"},
+{24, "Illegal combination of relation and term"},
+{25, "Special characters not quoted in term"},
+{26, "Non special character escaped in term"},
+{27, "Empty term unsupported"},
+{28, "Masking character not supported"},
+{29, "Masked words too short"},
+{30, "Too many masking characters in term"},
+{31, "Anchoring character not supported"},
+{32, "Anchoring character in illegal or unsupported position"},
+{33, "Combination of proximity/adjacency and masking characters not supported"},
+{34, "Combination of proximity/adjacency and anchoring characters not supported"},
+{35, "Terms only exclusion (stop) words"},
+{36, "Term in invalid format for index or relation"},
+{37, "Illegal or unsupported boolean operator"},
+{38, "Too many boolean operators in query"},
+{39, "Proximity not supported"},
+{40, "Illegal or unsupported proximity relation"},
+{41, "Illegal or unsupported proximity distance"},
+{42, "Illegal or unsupported proximity unit"},
+{43, "Illegal or unsupported proximity ordering"},
+{44, "Illegal or unsupported combination of proximity modifiers"},
+{45, "Index set name (prefix) assigned to multiple identifiers"},
+/* Diagnostics Relating to Result Sets*/
+{50, "Result sets not supported"},
+{51, "Result set does not exist"},
+{52, "Result set temporarily unavailable"},
+{53, "Result sets only supported for retrieval"},
+{54, "Retrieval may only occur from an existing result set"},
+{55, "Combination of result sets with search terms not supported"},
+{56, "Only combination of single result set with search terms supported"},
+{57, "Result set created but no records available"},
+{58, "Result set created with unpredictable partial results available"},
+{59, "Result set created with valid partial results available"},
+/* Diagnostics Relating to Records*/
+{60, "Too many records retrieved"},
+{61, "First record position out of range"},
+{62, "Negative number of records requested"},
+{63, "System error in retrieving records"},
+{64, "Record temporarily unavailable"},
+{65, "Record does not exist"},
+{66, "Unknown schema for retrieval"},
+{67, "Record not available in this schema"},
+{68, "Not authorised to send record"},
+{69, "Not authorised to send record in this schema"},
+{70, "Record too large to send"},
+/* Diagnostics Relating to Sorting*/
+{80, "Sort not supported"},
+{81, "Unsupported sort type (sortKeys vs xSortKeys)"},
+{82, "Illegal or unsupported sort sequence"},
+{83, "Too many records"},
+{84, "Too many sort keys"},
+{85, "Duplicate sort keys"},
+{86, "Incompatible record formats"},
+{87, "Unsupported schema for sort"},
+{88, "Unsupported tag path for sort"},
+{89, "Tag path illegal or unsupported for schema"},
+{90, "Illegal or unsupported direction value"},
+{91, "Illegal or unsupported case value"},
+{92, "Illegal or unsupported missing value action"},
+/* Diagnostics Relating to Explain*/
+{100, "Explain not supported"},
+{101, "Explain request type not supported (SOAP vs GET)"},
+{102, "Explain record temporarily unavailable"},
+{0, 0}
+};
+
+const char *yaz_srw_diag_str (int code)
+{
+    int i;
+    for (i=0; msg_tab[i].msg; i++)
+        if (msg_tab[i].code == code)
+            return msg_tab[i].msg;
+    return "Unknown error";
+}
diff --git a/srw/srw-namespace.c b/srw/srw-namespace.c
new file mode 100644 (file)
index 0000000..1659536
--- /dev/null
@@ -0,0 +1,29 @@
+/* $Id: srw-namespace.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include "srw_H.h"
+
+struct Namespace srw_namespaces[] =
+{
+  {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/"},
+  {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/"},
+#if 1
+  {"xsi", "http://schemas.xmlsoap.org/wsdl/"},
+  {"xsd", "http://www.w3.org/2001/XMLSchema"},
+#else
+  {"xsi", "http://www.w3.org/1999/XMLSchema-instance"},
+  {"xsd", "http://www.w3.org/1999/XMLSchema"},
+#endif
+  {"zs",       "http://www.loc.gov/zing/srw/v1.0/"},
+  {"zt",       "http://www.loc.gov/zing/srw/v1.0/types/"},
+  {"xcql",     "http://www.loc.gov/zing/cql/v1.0/xcql/"},
+  {"xsortkeys","http://www.loc.gov/zing/srw/v1.0/xsortkeys/"},
+  {"diag",     "http://www.loc.gov/zing/srw/v1.0/diagnostic/"},
+  {NULL, NULL}
+};
diff --git a/srw/srw-server.c b/srw/srw-server.c
new file mode 100644 (file)
index 0000000..2d09052
--- /dev/null
@@ -0,0 +1,74 @@
+
+#include <yaz/srw-util.h>
+#include <yaz/xmalloc.h>
+
+struct srw_info {
+    int (*sr_h)(void *userinfo,
+                struct soap * soap,
+                xsd__string  *query,
+                struct xcql__operandType *xQuery,      
+                xsd__string *sortKeys,
+                struct xsort__xSortKeysType *xSortKeys,
+                xsd__integer *startRecord,
+                xsd__integer *maximumRecords,
+                xsd__string *recordSchema,
+                xsd__string *recordPacking,
+                struct zs__searchRetrieveResponse *res);
+    int (*e_h)(void *userinfo,
+              struct soap *soap,
+              struct zs__explainResponse *explainResponse);
+    void *userinfo;
+};
+
+int zs__explainRequest (struct soap *soap,
+                       struct zs__explainResponse *explainResponse)
+{
+    struct srw_info *info = (struct srw_info *) soap->user;
+    return (*info->e_h)(info->userinfo, soap, explainResponse);
+}
+
+int zs__searchRetrieveRequest(struct soap * soap,
+                              xsd__string  *query,
+                             struct xcql__operandType *xQuery, 
+                              xsd__string *sortKeys,
+                             struct xsort__xSortKeysType *xSortKeys,
+                              xsd__integer *startRecord,
+                              xsd__integer *maximumRecords,
+                              xsd__string *recordSchema,
+                              xsd__string *recordPacking,
+                              struct zs__searchRetrieveResponse *res)
+{
+    struct srw_info *info = (struct srw_info *) soap->user;
+    return (*info->sr_h)(info->userinfo, soap,
+                         query, xQuery, sortKeys, xSortKeys,
+                         startRecord, maximumRecords,
+                         recordSchema, recordPacking,
+                         res);
+}
+
+void yaz_srw_serve (struct soap *soap,
+                    void *userinfo,
+                    int (*sr_h)(void *userinfo,
+                                struct soap * soap,
+                                xsd__string  *query,
+                                struct xcql__operandType *xQuery,      
+                                xsd__string *sortKeys,
+                                struct xsort__xSortKeysType *xSortKeys,
+                                xsd__integer *startRecord,
+                                xsd__integer *maximumRecords,
+                                xsd__string *recordSchema,
+                                xsd__string *recordPacking,
+                                struct zs__searchRetrieveResponse *res),
+                    int (*e_h)(void *userinfo,
+                                struct soap *soap,
+                               struct zs__explainResponse *explainResponse))
+{
+    struct srw_info info;
+
+    info.sr_h = sr_h;
+    info.e_h = e_h;
+    info.userinfo = userinfo;
+    soap->user = &info;
+    soap->namespaces = srw_namespaces;
+    soap_serve(soap);
+}
diff --git a/srw/srw-xcql.c b/srw/srw-xcql.c
new file mode 100644 (file)
index 0000000..bdd16fd
--- /dev/null
@@ -0,0 +1,84 @@
+/* $Id: srw-xcql.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#include <yaz/srw-util.h>
+
+struct cql_node *xcql_to_cqlnode(struct xcql__operandType *p)
+{
+    struct cql_node *cn = 0;
+    if (p && p->searchClause)
+    {
+        cn = cql_node_mk_sc(p->searchClause->index,
+                            p->searchClause->relation->value,
+                            p->searchClause->term);
+        if (p->searchClause->relation->modifiers)
+        {
+            struct xcql__modifiersType *mods =
+                p->searchClause->relation->modifiers;
+            struct cql_node **cnp = &cn->u.st.modifiers;
+
+            int i;
+            for (i = 0; i < mods->__sizeModifier; i++)
+            {
+                *cnp = cql_node_mk_mod(mods->modifier[i]->type,
+                                       mods->modifier[i]->value);
+                cnp = &(*cnp)->u.mod.next;
+            }
+        }
+        if (p->searchClause->prefixes)
+        {
+            struct xcql__prefixesType *prefixes = p->searchClause->prefixes;
+            struct cql_node **cnp = &cn->u.st.prefixes;
+
+            int i;
+            for (i = 0; i < prefixes->__sizePrefix; i++)
+            {
+                *cnp = cql_node_mk_mod(prefixes->prefix[i]->name,
+                                       prefixes->prefix[i]->identifier);
+                cnp = &(*cnp)->u.mod.next;
+            }
+        }
+    }
+    else if (p && p->triple)
+    {
+        cn = cql_node_mk_boolean(p->triple->boolean->value);
+
+        if (p->triple->boolean->modifiers)
+        {
+            struct xcql__modifiersType *mods =
+                p->triple->boolean->modifiers;
+            struct cql_node **cnp = &cn->u.bool.modifiers;
+
+            int i;
+            for (i = 0; i < mods->__sizeModifier; i++)
+            {
+                *cnp = cql_node_mk_mod(mods->modifier[i]->type,
+                                       mods->modifier[i]->value);
+                cnp = &(*cnp)->u.mod.next;
+            }
+        }
+        if (p->triple->prefixes)
+        {
+            struct xcql__prefixesType *prefixes = p->triple->prefixes;
+            struct cql_node **cnp = &cn->u.bool.prefixes;
+
+            int i;
+            for (i = 0; i < prefixes->__sizePrefix; i++)
+            {
+                *cnp = cql_node_mk_mod(prefixes->prefix[i]->name,
+                                       prefixes->prefix[i]->identifier);
+                cnp = &(*cnp)->u.mod.next;
+            }
+        }
+        cn->u.bool.left = xcql_to_cqlnode(p->triple->leftOperand);
+        cn->u.bool.right = xcql_to_cqlnode(p->triple->rightOperand);
+    }
+    return cn;
+}
+
diff --git a/srw/srw-xslt.c b/srw/srw-xslt.c
new file mode 100644 (file)
index 0000000..c3dbac0
--- /dev/null
@@ -0,0 +1,209 @@
+/* $Id: srw-xslt.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+#if HAVE_XSLT
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+#endif
+
+#include <yaz/srw-util.h>
+
+struct xslt_maps_info {
+#if HAVE_XSLT
+    xmlDocPtr doc;
+#else
+    int dummy;
+#endif
+};
+
+struct xslt_map_result_info {
+#if HAVE_XSLT
+    xmlChar *buf;
+#else
+    char *buf;
+#endif
+    int len;
+    char *schema;
+};
+
+xslt_maps xslt_maps_create()
+{
+    xslt_maps m = malloc(sizeof(*m));
+#if HAVE_XSLT
+    m->doc = 0;
+#endif
+    return m;
+}
+
+void xslt_maps_free(xslt_maps m)
+{
+#if HAVE_XSLT
+    xmlFreeDoc(m->doc);
+#endif
+    free (m);
+}
+
+int xslt_maps_file(xslt_maps m, const char *f)
+{
+#if HAVE_XSLT
+    if (m->doc)
+        xmlFreeDoc(m->doc);
+    m->doc = xmlParseFile(f);
+    if (!m->doc)
+        return -1;
+    return 0;
+#else
+    return -2;
+#endif
+}
+
+void xslt_map_free (xslt_map_result res)
+{
+    if (res)
+    {
+        free (res->schema);
+#if HAVE_XSLT
+        xmlFree(res->buf);
+#endif
+        free (res);
+    }
+}
+
+xslt_map_result xslt_map (xslt_maps m, const char *schema_source,
+                          const char *schema_target,
+                          const char *in_buf, int in_len)
+{
+#if HAVE_XSLT
+    const char *map_ns = "http://indexdata.dk/srw/schema-mappings/v1.0/";
+    xmlNodePtr ptr;
+
+    if (!m)
+        return 0;
+    ptr = xmlDocGetRootElement(m->doc);
+    while (ptr && ptr->type == XML_ELEMENT_NODE)
+    {
+        if (!strcmp(ptr->name, "schema-mappings"))
+        {
+            ptr = ptr->children;
+            break;
+        }
+    }
+    for (; ptr; ptr = ptr->next)
+    {
+        if (ptr->type == XML_ELEMENT_NODE &&  !strcmp(ptr->name, "map")
+            && !strcmp(ptr->ns->href, map_ns) && ptr->children)
+        {
+            xmlNodePtr src = ptr->children;
+            int source_ok = 0;
+            int target_ok = 0;
+            const char *full_target = 0;
+            const char *filename = 0;
+            
+            for (; src; src = src->next)
+            {
+                if (src->type == XML_ELEMENT_NODE &&
+                    !strcmp(src->name, "schema") &&
+                    !strcmp(src->ns->href, map_ns))
+                {
+                    struct _xmlAttr *attr = src->properties;
+                    for (; attr; attr = attr->next)
+                        if (!strcmp(attr->name, "target") &&
+                            attr->children &&
+                            attr->children->type == XML_TEXT_NODE)
+                        {
+                            full_target = attr->children->content;
+                            if (!strcmp(attr->children->content,
+                                        schema_target))
+                                target_ok = 1;
+                        }
+                        else if (!strcmp(attr->name, "source")
+                                 && attr->children
+                                 && attr->children->type == XML_TEXT_NODE)
+                            
+                        {
+                            if (!strcmp(schema_source,
+                                        attr->children->content))
+                                source_ok = 1;
+                        }
+                        else if (!strcmp(attr->name, "alias")
+                                 && attr->children
+                                 && attr->children->type == XML_TEXT_NODE)
+                        {
+                            if (!strcmp(attr->children->content, schema_target))
+                                target_ok = 1;
+                        }
+                }
+                if (src->type == XML_ELEMENT_NODE &&
+                    !strcmp(src->name, "stylesheet") &&
+                    !strcmp(src->ns->href, map_ns))
+                {
+                    struct _xmlAttr *attr = src->properties;
+                    for (; attr; attr = attr->next)
+                        if (!strcmp(attr->name, "filename") &&
+                            attr->children &&
+                            attr->children->type == XML_TEXT_NODE)
+                        {
+                            filename = attr->children->content;
+                        }
+                }
+            }
+            if (source_ok && target_ok)
+            {
+                if (filename)
+                {
+                    xslt_map_result out = malloc(sizeof(*out));
+                    xmlDocPtr res, doc = xmlParseMemory(in_buf, in_len);
+                    xmlDocPtr xslt_doc = xmlParseFile(filename);
+                    xsltStylesheetPtr xsp;
+                    
+                    xsp = xsltParseStylesheetDoc(xslt_doc);
+                    
+                    res = xsltApplyStylesheet(xsp, doc, 0);
+                    
+                    xmlDocDumpMemory (res, &out->buf, &out->len);
+                
+                    xsltFreeStylesheet(xsp);
+                    
+                    xmlFreeDoc(doc);
+                    xmlFreeDoc(res);
+                    
+                    out->schema = strdup(full_target);
+                    return out;
+                }
+                else
+                {
+                    xslt_map_result out = malloc(sizeof(*out));
+                    out->buf = xmlMalloc(in_len);
+                    memcpy (out->buf, in_buf, in_len);
+                    out->len = in_len;
+                    out->schema = strdup(full_target);
+                    return out; 
+                }
+            }
+        }
+    }
+#endif
+    return 0;
+}
+
+char *xslt_map_result_buf(xslt_map_result res)
+{
+    return res->buf;
+}
+int xslt_map_result_len(xslt_map_result res)
+{
+    return res->len;
+}
+
+char *xslt_map_result_schema(xslt_map_result res)
+{
+    return res->schema;
+}
diff --git a/srw/zing.h b/srw/zing.h
new file mode 100644 (file)
index 0000000..8224be3
--- /dev/null
@@ -0,0 +1,136 @@
+/* $Id: zing.h,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+See file LICENSE for details.
+*/
+//gsoap zs service name: SRW
+//gsoap zs service encoding: literal
+//gsoap zs service namespace: http://www.loc.gov/zing/srw/v1.0/
+//gsoap zs schema namespace: http://www.loc.gov/zing/srw/v1.0/
+//gsoap xcql schema namespace: http://www.loc.gov/zing/cql/v1.0/xcql/
+//gsoap xsort schema namespace: http://www.loc.gov/zing/srw/v1.0/xsortkeys/
+//gsoap diag schema namespace: http://www.loc.gov/zing/srw/v1.0/diagnostic/
+
+typedef char *xsd__string;
+typedef int xsd__integer;
+typedef int xsd__boolean;
+
+typedef xsd__string zs__idType;
+typedef char *XML;
+
+struct zs__recordType {
+    xsd__string recordSchema;  
+    xsd__string recordData;
+    xsd__integer recordPosition 0; 
+};
+
+struct zs__records {
+    int __sizeRecords;
+    struct zs__recordType **record;
+};
+
+struct diag__diagnosticType {
+    xsd__integer code;
+    xsd__string details 0;
+};
+
+struct zs__diagnostics {
+    int __sizeDiagnostics;
+    struct diag__diagnosticType **diagnostic;
+};
+
+struct zs__searchRetrieveResponse {
+    xsd__integer numberOfRecords;
+    xsd__string resultSetId 1; 
+    xsd__integer resultSetIdleTime 0;
+    
+    struct zs__records records 0;
+    struct zs__diagnostics diagnostics 0;
+    xsd__integer *nextRecordPosition 0;
+    xsd__string debugInfo;
+};
+
+struct xcql__prefixType {
+    xsd__string name;
+    xsd__string identifier;
+};
+
+struct xcql__prefixesType {
+    int __sizePrefix;
+    struct xcql__prefixType **prefix;
+};
+
+struct xcql__relationType {
+    xsd__string value;
+    struct xcql__modifiersType *modifiers 0;
+};
+
+struct xcql__searchClauseType {
+    struct xcql__prefixesType *prefixes 0;
+    xsd__string index 0;
+    struct xcql__relationType *relation 0;
+    xsd__string term;
+}; 
+
+struct xcql__modifierType {
+    xsd__string type 0;
+    xsd__string value;
+};
+
+struct xcql__modifiersType {
+    int __sizeModifier;
+    struct xcql__modifierType **modifier; 
+};
+
+struct xcql__booleanType {
+    xsd__string value;
+    struct xcql__modifiersType *modifiers 0;
+};
+
+struct xcql__operandType {
+    struct xcql__searchClauseType *searchClause 0;
+    struct xcql__tripleType *triple 0;
+};
+
+struct xcql__tripleType {
+    struct xcql__prefixesType *prefixes 0;
+    struct xcql__booleanType *boolean;
+    struct xcql__operandType *leftOperand;
+    struct xcql__operandType *rightOperand;
+};
+
+struct xsort__sortKeyType {
+    xsd__string path;
+    xsd__string schema 0;
+    xsd__boolean ascending 0;
+    xsd__boolean caseSensitive 0;
+    xsd__string missingValue 0;
+};
+
+struct xsort__xSortKeysType {
+    int __sizeSortKey;
+    struct xsort__sortKeyType **sortKey; 
+};
+
+int zs__searchRetrieveRequest (
+    xsd__string *query,
+    struct xcql__operandType *xQuery,
+    xsd__string *sortKeys,
+    struct xsort__xSortKeysType *xSortKeys,
+    xsd__integer *startRecord,
+    xsd__integer *maximumRecords,
+    xsd__string *recordSchema,
+    xsd__string *recordPacking,
+    struct zs__searchRetrieveResponse *searchRetrieveResponse
+);
+
+struct zs__explainResponse {
+    xsd__string Explain;
+};
+
+int zs__explainRequest (
+    struct zs__explainResponse *explainResponse
+);
diff --git a/srwapps/.cvsignore b/srwapps/.cvsignore
new file mode 100644 (file)
index 0000000..da7b481
--- /dev/null
@@ -0,0 +1,5 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
diff --git a/srwapps/Makefile.am b/srwapps/Makefile.am
new file mode 100644 (file)
index 0000000..a024153
--- /dev/null
@@ -0,0 +1,18 @@
+## $Id: Makefile.am,v 1.1 2003-01-06 08:20:28 adam Exp $
+## Copyright (C) 2002-2003, Index Data
+
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/srw $(CFLAGSTHREADS)
+
+if SRW
+bin_PROGRAMS = srw-gateway srw-client
+endif
+
+if ISTHR
+extra=../lib/libyazthread.la
+endif
+
+LDADD = $(extra) ../lib/libyaz.la $(GSOAP_LIB) $(XSLT_LIB) $(LIBTHREAD)
+
+srw_gateway_SOURCES = srw-gateway.c 
+srw_client_SOURCES = srw-client.c
+
diff --git a/srwapps/srw-client.c b/srwapps/srw-client.c
new file mode 100644 (file)
index 0000000..b1c4c6d
--- /dev/null
@@ -0,0 +1,179 @@
+/* $Id: srw-client.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See file LICENSE for details.
+*/
+
+#include <stdio.h>
+
+#include <yaz/srw-util.h>
+
+int main (int argc, char **argv)
+{
+    struct soap soap;
+    char *action;
+    int ret;
+    struct zs__searchRetrieveResponse res;
+    char * query = 0;
+    struct xcql__operandType *xQuery = 0;
+    xsd__integer startRecord = 1;
+    xsd__integer maximumRecord = 0;
+    char *recordSchema = "http://www.loc.gov/marcxml/";
+    xsd__string recordPacking = 0;
+    char *service = 0;
+    int xcql = 0;
+    int explain = 0;
+    char *arg;
+
+    while ((ret = options("er:xs:", argv, argc, &arg)) != -2)
+    {
+        switch(ret)
+        {
+        case 0:
+            if (!service)
+                service = arg;
+            else if (!query)
+                query = arg;
+            break;
+        case 'e':
+            explain = 1;
+            break;
+        case 'r':
+            sscanf (arg, "%d,%d", &startRecord, &maximumRecord);
+            break;
+        case 'x':
+            xcql = 1;
+            break;
+        case 's':
+            recordSchema = arg;
+        }
+    }
+    if (!query)
+    {
+        printf ("usage:\n srw-client");
+        printf (" [-e] [-r start,number] [-x] [-s schema] <service> <query>\n");
+        printf ("  http://localhost:8001/indexdata.dk/gils computer\n");
+        exit (1);
+    }
+    soap_init(&soap);
+    soap.namespaces = srw_namespaces;
+
+    if (explain)
+    {
+        struct zs__explainResponse eres;
+        ret = soap_call_zs__explainRequest(&soap, service, action,
+                                           &eres);
+        if (ret == SOAP_OK)
+        {
+            if (eres.Explain)
+                printf ("%s\n", eres.Explain);
+            else
+                printf ("no record\n");
+        }
+        else
+            soap_print_fault(&soap, stderr);
+    }
+
+    if (xcql)   /* xquery */
+    {   /* just a hacked query for testing .. */
+        struct xcql__searchClauseType *sc1, *sc2;
+        struct xcql__relationType *relation;
+        struct xcql__tripleType *triple;
+        xQuery = soap_malloc (&soap, sizeof(*xQuery));
+        sc1 = soap_malloc (&soap, sizeof(*sc1));
+        sc1->prefixes = 0;
+        sc1->index = "dc.title";
+        relation = sc1->relation = soap_malloc(&soap, sizeof(*relation));
+        sc1->term = "computer";
+        relation->value = "=";
+        relation->modifiers = 0;
+        
+        sc2 = soap_malloc (&soap, sizeof(*sc2));
+        sc2->prefixes = 0;
+        sc2->index = "dc.author";
+        relation = sc2->relation = soap_malloc(&soap, sizeof(*relation));
+        sc2->term = "knuth";
+        relation->value = "=";
+        relation->modifiers =
+            soap_malloc (&soap, sizeof(*relation->modifiers));
+        relation->modifiers->__sizeModifier = 1;
+        relation->modifiers->modifier = 
+            soap_malloc (&soap, sizeof(*relation->modifiers->modifier));
+        relation->modifiers->modifier[0] = 
+                soap_malloc (&soap, sizeof(**relation->modifiers->modifier));
+        relation->modifiers->modifier[0]->type = 0;
+        relation->modifiers->modifier[0]->value =  soap_malloc (&soap, 6);
+        strcpy(relation->modifiers->modifier[0]->value, "fuzzy");
+        ;
+        triple = soap_malloc (&soap, sizeof(*triple));
+        triple->prefixes = 0;
+        triple->boolean = soap_malloc (&soap, sizeof(*triple->boolean));
+        triple->boolean->value = "and";
+        triple->boolean->modifiers = 0;
+        triple->leftOperand =
+            soap_malloc (&soap, sizeof(*triple->leftOperand));
+        triple->leftOperand->searchClause = sc1;
+        triple->rightOperand =
+            soap_malloc (&soap, sizeof(*triple->rightOperand));
+        triple->rightOperand->searchClause = sc2;
+        xQuery->triple = triple;
+        query = 0;
+    }
+
+    ret = soap_call_zs__searchRetrieveRequest(&soap, service, action,
+                                              &query, xQuery, 
+                                              0, 0,
+                                              &startRecord,
+                                              &maximumRecord,
+                                              &recordSchema,
+                                              &recordPacking,
+                                              &res);
+
+    if (ret == SOAP_OK)
+    {
+        if (res.diagnostics.__sizeDiagnostics > 0)
+        {
+            int i;
+            for (i = 0; i < 
+                     res.diagnostics.__sizeDiagnostics;
+                 i++)
+            {
+                int code = res.diagnostics.diagnostic[i]->code;
+                char *details =
+                    res.diagnostics.diagnostic[i]->details;
+                printf ("error = %d", code);
+                if (details)
+                    printf (" details = %s", details);
+                printf ("\n");
+            }
+        }
+        else
+        {
+            int i;
+            if (res.resultSetId)
+                printf ("set: %s\n", res.resultSetId);
+            printf ("numberOfRecords: %d\n", res.numberOfRecords);
+            for (i = 0; i<res.records.__sizeRecords;
+                 i++)
+            {
+                if (res.records.record[i]->recordData)
+                {
+                    printf ("rec %d schema=%s string:\n%s\n", i+1,
+                            res.records.record[i]->recordSchema,
+                            res.records.record[i]->recordData);
+                }
+            }
+        }
+    }
+    else
+    {
+        soap_print_fault(&soap, stderr);
+    }
+    soap_end(&soap);
+    exit (0);
+    return 0;
+}
+
diff --git a/srwapps/srw-gateway.c b/srwapps/srw-gateway.c
new file mode 100644 (file)
index 0000000..77591db
--- /dev/null
@@ -0,0 +1,903 @@
+/* $Id: srw-gateway.c,v 1.1 2003-01-06 08:20:28 adam Exp $
+   Copyright (C) 2002-2003
+   Index Data Aps
+
+This file is part of the YAZ toolkit.
+
+See the file LICENSE.
+*/
+
+/*
+ * TODO:
+ *
+ * TTL for targets. Separate thread for cleanup.
+ * External target config and aliases.
+ */
+
+/* note that soapH.h defines _REENTRANT so we check for it here */
+#ifdef _REENTRANT
+#include <pthread.h>
+#define USE_THREADS 1
+#else
+#define USE_THREADS 0
+#endif
+
+#include <yaz/srw-util.h>
+#include <yaz/xmalloc.h>
+#include <yaz/zoom.h>
+#include <yaz/log.h>
+#include <yaz/options.h>
+#include <yaz/wrbuf.h>
+
+#define RESULT_SETS 0
+#define SRW_DEBUG 1
+
+struct tset {
+    ZOOM_resultset m_r;
+    long m_expiry_sec;   /* date of creation */
+    int m_idle_time;
+    char *m_query;
+    char *m_schema;
+    struct tset *m_next;
+};
+
+struct target {
+    ZOOM_connection m_c;
+    char *m_name;
+    int m_in_use;
+    struct tset *m_sets;
+    struct target *next;
+};
+
+struct srw_prop {
+    int optimize_level;
+    int idle_time;
+    int max_sets;
+    xslt_maps maps;
+};
+
+static cql_transform_t cql_transform_handle = 0;
+static struct target *target_list = 0;
+#if USE_THREADS
+static pthread_mutex_t target_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define mylock(x) pthread_mutex_lock(x)
+#define myunlock(x) pthread_mutex_unlock(x)
+#else
+#define mylock(x)
+#define myunlock(x)
+#endif
+
+#define ERROR_NO_TARGET -1
+#define ERROR_BAD_CQL   10
+
+static int diag_bib1_to_srw (int code)
+{
+    static int map[] = {
+        1, 1,
+        2, 2,
+        3, 11,
+        4, 35,
+        5, 12,
+        6, 30,
+        7, 30,
+        8, 32,
+        9, 29,
+        10, 10,
+        11, 12,
+        13, 61,
+        14, 63,
+        15, 68,
+        16, 70,
+        17, 70,
+        18, 50,
+        19, 55,
+        20, 56, 
+        21, 52,
+        22, 50,
+        /* 23-26 no map */
+        27, 51,
+        28, 52,
+        29, 52,
+        30, 51,
+        31, 52,
+        32, 52,
+        33, 52,
+        /* 100 -105 */
+        106, 66,
+        107, 11,
+        108, 10,
+        109, 2,
+        110, 37,
+        /* 111- 112 */
+        113, 10,
+        114, 16,
+        115, 16,
+        116, 16,
+        117, 19,
+        118, 22,
+        119, 32,
+        120, 28,
+        121, 15,
+        122, 32,
+        123, 22,
+        124, 24,
+        125, 36,
+        126, 36, 
+        127, 36,
+        128, 51,
+        129, 39,
+        130, 43,
+        131, 40,
+        132, 42,
+        201, 44,
+        202, 41,
+        203, 43,
+        /* 205 */
+        0
+    };
+    const int *p = map;
+    while (*p)
+    {
+        if (code == *p)
+            return p[1];
+        p += 2;
+    }
+    return 0;
+}
+
+static int searchRetrieve(void *userinfo,
+                          struct soap * soap,
+                          xsd__string  *query,
+                          struct xcql__operandType *xQuery,    
+                          xsd__string *sortKeys,
+                          struct xsort__xSortKeysType *xSortKeys,
+                          xsd__integer *startRecord,
+                          xsd__integer *maximumRecords,
+                          xsd__string *recordSchema,
+                          xsd__string *recordPacking,
+                          struct zs__searchRetrieveResponse *res);
+static int explain (void *userinfo,
+                    struct soap *soap,
+                    struct zs__explainResponse *explainResponse);
+
+struct target *target_use (const char *action, const char *query,
+                           const char *schema, struct tset **set,
+                           struct srw_prop *prop)
+{
+    char name[80];
+    struct target *l = 0;
+    struct timeval tv;
+    struct tset **ssp = 0;
+    long now;
+    int no_sets = 0;
+
+    gettimeofday(&tv, 0);
+    now = tv.tv_sec;
+
+    if (strlen(action) >= 80)
+        action = "localhost:210";
+    if (strchr(action, '/') || strchr(action, ':'))
+        strcpy (name, action);
+    else
+    {
+        strcpy (name, "localhost/");
+        if (*action == '\0')
+            strcat (name, "Default");
+        else
+            strcat (name, action);
+    }
+
+    /* See if we have the target and the same query */
+    if (query)
+        for (l = target_list; l; l = l->next)
+            if (!l->m_in_use && !strcmp (l->m_name, name))
+            {
+                struct tset *s = l->m_sets;
+                for (; s; s = s->m_next)
+                    if (!strcmp(s->m_query, query) && 
+                        !strcmp (s->m_schema, schema))
+                    {
+                        *set = s;
+                        return l;
+                    }
+            }
+    
+    /* OK, see if we have the target, then.. */
+    for (l = target_list; l; l = l->next)
+        if (!strcmp (l->m_name, name) && !l->m_in_use)
+        {
+            struct tset *s = l->m_sets;
+            for (; s; s = s->m_next)
+                /* if m_expiry_sec is 0, the condition is true below */
+                if (s->m_expiry_sec < now)
+                {
+                    xfree (s->m_query);
+                    s->m_query = xstrdup("");
+                    xfree (s->m_schema);
+                    s->m_schema = xstrdup("");
+                    ZOOM_resultset_destroy(s->m_r);
+                    s->m_r = 0;
+                    *set = s;
+                    return l;
+                }
+            break;
+        }
+    if (!l)
+    {
+        /* allright. Have to make a new one */
+        l = xmalloc (sizeof(*l));
+        l->m_name = xstrdup (name);
+        l->m_in_use = 1;
+        l->m_c = 0;
+        l->m_sets = 0;
+        l->next = target_list;
+        target_list = l;
+    }
+    for (ssp = &l->m_sets; *ssp; ssp = &(*ssp)->m_next)
+        no_sets++;
+    *ssp = xmalloc(sizeof(**ssp));
+    (*ssp)->m_next = 0;
+    (*ssp)->m_query = xstrdup("");
+    (*ssp)->m_schema = xstrdup("");
+    (*ssp)->m_r = 0;
+    (*ssp)->m_expiry_sec = 0;
+    (*ssp)->m_idle_time = (no_sets >= prop->max_sets ? 0 : prop->idle_time);
+    *set = *ssp;
+    return l;
+}
+
+static void target_destroy (struct target *t)
+{
+    struct target **tp;
+
+    mylock(&target_mutex);
+
+    for (tp = &target_list; *tp; tp = &(*tp)->next)
+        if (*tp == t)
+        {
+            struct tset *s = t->m_sets;
+            while (s)
+            {
+                struct tset *s_next = s->m_next;
+                xfree (s->m_query);
+                xfree (s->m_schema);
+                ZOOM_resultset_destroy (s->m_r);
+                xfree (s);
+                s = s_next;
+            }
+
+            *tp = t->next;
+
+            ZOOM_connection_destroy (t->m_c);
+
+            xfree (t->m_name);
+            xfree (t);
+            break;
+        }
+    myunlock(&target_mutex);
+}
+    
+static void target_leave (struct target *l)
+{
+    mylock(&target_mutex);
+    l->m_in_use = 0;
+
+    if (1)
+    {
+        struct tset *s = l->m_sets;
+        for (; s; s = s->m_next)
+            yaz_log(LOG_LOG, " set %s q=%s", 
+                    (s->m_r ? ZOOM_resultset_option_get(s->m_r,"setname"):""),
+                    s->m_query);
+    }
+    myunlock(&target_mutex);
+}
+
+static void standalone(struct soap *soap, const char *host, int port,
+                       int max_thr, struct srw_prop *properties)
+{
+    struct soap **soap_thr = malloc (sizeof(*soap_thr) * max_thr);
+#if USE_THREADS
+    pthread_t *tid = malloc (sizeof(pthread_t) * max_thr);
+#endif
+    int m, s, i;
+    int cno = 0;
+    int stop = 0;
+    char fname[40];
+    
+    m = soap_bind(soap, 0, port, 100);
+    if (m < 0)
+    {
+        yaz_log (LOG_WARN|LOG_ERRNO, "Cannot bind to %d", port);
+        stop = 1;
+    }
+
+    for (i = 0; i<max_thr; i++)
+        soap_thr[i] = 0;
+
+    while (!stop)
+    {
+        for (i = 0; i<max_thr; i++)
+        {
+            s = soap_accept(soap);
+            if (s < 0)
+                break;
+            cno++;
+            if (!soap_thr[i])
+            {
+                soap_thr[i] = soap_new();
+                if (!soap_thr[i])
+                {
+                    stop = 1;
+                    break;
+                }
+            }
+            else
+            {
+#if USE_THREADS
+                if (max_thr > 1)          /* static mode for max_thr <= 1 */
+                    pthread_join(tid[i], 0);
+#endif
+                soap_end(soap_thr[i]);
+            }
+
+#if SRW_DEBUG
+            sprintf (fname, "srw.recv.%05d.log", cno);
+           remove (fname);
+            soap_set_recv_logfile(soap_thr[i], fname);
+            
+            sprintf (fname, "srw.sent.%05d.log", cno);
+           remove (fname);
+            soap_set_sent_logfile(soap_thr[i], fname);
+            
+            sprintf (fname, "srw.test.%05d.log", cno);
+           remove (fname);
+            soap_set_test_logfile(soap_thr[i], fname);
+
+            yaz_log (LOG_LOG, "starting session %d %ld.%ld.%ld.%ld", cno,
+                     (long) (soap->ip>>24) & 0xff,
+                     (long) (soap->ip>>16) & 0xff,
+                     (long) (soap->ip>>8) & 0xff,
+                     (long) soap->ip & 0xff);
+#endif
+            soap_thr[i]->encodingStyle = 0;
+            soap_thr[i]->socket = s;
+            soap_thr[i]->user = properties;
+#if USE_THREADS
+            if (max_thr <= 1)
+                yaz_srw_serve(soap_thr[i], properties,
+                              searchRetrieve, explain);  /* static mode .. */
+            else
+                pthread_create(&tid[i], 0, (void*(*)(void*))soap_serve,
+                               soap_thr[i]);
+#else
+            yaz_srw_serve(soap_thr[i], properties,
+                          searchRetrieve, explain);  /* static mode .. */
+#endif
+        }
+    }
+#if USE_THREADS
+    free (tid);
+#endif
+    free (soap_thr);
+}
+
+static void reconnect (struct target *t)
+{
+    struct tset *s;
+
+    for (s = t->m_sets; s; s = s->m_next)
+    {
+        ZOOM_resultset_destroy(s->m_r);
+        s->m_r = 0;
+    }
+    ZOOM_connection_destroy (t->m_c);
+
+    t->m_c = ZOOM_connection_create (0);
+    ZOOM_connection_connect (t->m_c, t->m_name, 0);
+}
+
+int explain (void *userinfo,
+             struct soap *soap,
+             struct zs__explainResponse *explainResponse)
+{
+    explainResponse->Explain = 
+        "<explain>\n"
+        "  <!-- not implemented -->\n"
+        "</explain>\n";
+    return SOAP_OK;
+}
+
+int fetchone(struct soap *soap, struct srw_prop *properties,
+             ZOOM_record zrec, const char *schema,
+             char **rec_data, char **rec_schema)
+{
+    xslt_map_result res;
+    int xml_len;
+    const char *xml_rec = ZOOM_record_get(zrec, "xml", &xml_len);
+    if (!xml_rec)
+    {
+        return 65;
+    }
+    if (!strcmp(schema, "MARC21"))
+    {
+        *rec_data = soap_malloc (soap, xml_len+1);
+        memcpy (*rec_data, xml_rec, xml_len);
+        (*rec_data)[xml_len] = 0;
+        *rec_schema = "http://www.loc.gov/marcxml/";
+    }
+    else if ((res = xslt_map (properties->maps, "MARC21",
+                              schema, xml_rec, xml_len)))
+    {
+        int len = xslt_map_result_len(res);
+        char *buf = xslt_map_result_buf(res);
+
+        *rec_data = soap_malloc (soap, len+1);
+        memcpy (*rec_data, buf, len);
+        (*rec_data)[len] = 0;
+        
+        *rec_schema = soap_malloc(soap,
+                                  strlen(xslt_map_result_schema(res)) + 1);
+        strcpy(*rec_schema, xslt_map_result_schema(res));
+        
+        xslt_map_free (res);
+    }
+    else
+    {
+        *rec_data = soap_malloc(soap, strlen(schema)+1);
+        strcpy(*rec_data, schema);
+        return 66;
+    }
+    return 0;
+}
+                
+int searchRetrieve(void *userinfo,
+                   struct soap * soap,
+                   xsd__string  *query,
+                   struct xcql__operandType *xQuery,   
+                   xsd__string *sortKeys,
+                   struct xsort__xSortKeysType *xSortKeys,
+                   xsd__integer *startRecord,
+                   xsd__integer *maximumRecords,
+                   xsd__string *recordSchema,
+                   xsd__string *recordPacking,
+                   struct zs__searchRetrieveResponse *res)
+{
+    const char *msg = 0, *addinfo = 0;
+    const char *schema = recordSchema ? *recordSchema : "";
+    struct target *t = 0;
+    struct tset *s = 0;
+    int error = 0;
+    struct srw_prop *properties = (struct srw_prop*) userinfo;
+    WRBUF wr_log = wrbuf_alloc();
+
+    char pqf_buf[1024];
+    char zurl[81];
+
+    *pqf_buf = '\0';
+    *zurl = '\0';
+    yaz_log (LOG_LOG, "HTTP: %s", soap->endpoint);
+    if (*soap->endpoint)
+    {
+        const char *cp = strstr(soap->endpoint, "//");
+       if (cp)
+            cp = cp+2;             /* skip method// */
+       else
+            cp = soap->endpoint;
+       cp = strstr(cp, "/"); 
+       if (cp)
+        {
+            size_t len;
+            cp++;
+            len = strlen(cp);
+            if (len > 80)
+                len = 80;
+            if (len)
+                memcpy (zurl, cp, len);
+            zurl[len] = '\0';
+        }
+    }
+    else
+    {
+        const char *cp = getenv("PATH_INFO");
+        if (cp && cp[0] && cp[1])
+        {
+            size_t len;
+            cp++;  /* skip / */
+            len = strlen(cp);
+            if (len > 80)
+                len = 80;
+            if (len)
+                memcpy (zurl, cp, len);
+            zurl[len] = '\0';
+        }
+    }
+    if (query)
+    {
+        CQL_parser cql_parser = cql_parser_create();
+        int r = cql_parser_string(cql_parser, *query);
+
+        if (r)
+        {
+            yaz_log (LOG_LOG, "cql failed: %s", *query);
+            error = ERROR_BAD_CQL;
+        }
+        else
+        {
+            struct cql_node *tree = cql_parser_result(cql_parser);
+            error = cql_transform_buf (cql_transform_handle, tree,
+                                       pqf_buf, sizeof(pqf_buf));
+            if (error)
+                cql_transform_error(cql_transform_handle, &addinfo);
+            cql_parser_destroy(cql_parser);
+            yaz_log (LOG_LOG, "cql OK: %s", *query);
+        }
+    }
+    else if (xQuery)
+    {
+        struct cql_node *tree = xcql_to_cqlnode(xQuery);
+        yaz_log (LOG_LOG, "xcql");
+        cql_transform_buf (cql_transform_handle, tree,
+                           pqf_buf, sizeof(pqf_buf));
+        cql_node_destroy(tree);
+    }
+    if (!error)
+    {
+        mylock(&target_mutex);
+        t = target_use (zurl, *pqf_buf ? pqf_buf : 0, schema, &s, properties);
+        myunlock(&target_mutex);
+    }
+
+    if (!error && !t->m_c)
+    {
+        reconnect(t);
+        if (ZOOM_connection_error (t->m_c, &msg, &addinfo))
+        {
+            yaz_log (LOG_LOG, "%s: connect failed", t->m_name);
+            error = ERROR_NO_TARGET;
+        }
+        else
+            yaz_log (LOG_LOG, "%s: connect ok", t->m_name);
+    }
+    if (!error && t->m_c &&  *pqf_buf)
+    {
+        if (properties->optimize_level <=1 ||
+            strcmp (pqf_buf, s->m_query) ||
+            strcmp (schema, s->m_schema))
+        {
+            /* not the same query: remove result set .. */
+            ZOOM_resultset_destroy (s->m_r);
+            s->m_r = 0;
+        }
+        else
+        {
+            /* same query: retrieve (instead of doing search) */
+            if (maximumRecords && *maximumRecords > 0)
+            {
+                int start = startRecord ? *startRecord : 1;
+                yaz_log (LOG_LOG, "%s: present start=%d count=%d pqf=%s",
+                         t->m_name, start, *maximumRecords, pqf_buf);
+                wrbuf_printf (wr_log, "%s: present start=%d count=%d pqf=%s",
+                              t->m_name, start, *maximumRecords, pqf_buf);
+                ZOOM_resultset_records (s->m_r, 0, start-1, *maximumRecords);
+                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
+                if (error == ZOOM_ERROR_CONNECTION_LOST ||
+                    error == ZOOM_ERROR_CONNECT)
+                {
+                    reconnect (t);
+                    if ((error = ZOOM_connection_error (t->m_c, &msg,
+                                                    &addinfo)))
+                    {
+                        yaz_log (LOG_LOG, "%s: connect failed", t->m_name);
+                        error = ERROR_NO_TARGET;
+                    }
+                }
+                else if (error)
+                {
+                    yaz_log (LOG_LOG, "%s: present failed bib1-code=%d",
+                             t->m_name, error);
+                    error = diag_bib1_to_srw(error);
+                }
+            }
+            else
+            {
+                yaz_log (LOG_LOG, "%s: matched search pqf=%s",
+                         t->m_name, pqf_buf);
+                wrbuf_printf (wr_log, "%s: matched search pqf=%s",
+                         t->m_name, pqf_buf);
+            }
+        }
+        if (!error && !s->m_r) 
+        {   /* no result set usable. We must search ... */
+            int pass;
+            for (pass = 0; pass < 2; pass++)
+            {
+                char val[30];
+                int start = startRecord ? *startRecord : 1;
+                int count = maximumRecords ? *maximumRecords : 0;
+                
+                sprintf (val, "%d", start-1);
+                ZOOM_connection_option_set (t->m_c, "start", val);
+                
+                sprintf (val, "%d", count);
+                ZOOM_connection_option_set (t->m_c, "count", val);
+                
+                ZOOM_connection_option_set (t->m_c, "preferredRecordSyntax", 
+                                            "usmarc");
+                
+                xfree (s->m_query);
+                s->m_query = xstrdup (pqf_buf);
+
+                xfree (s->m_schema);
+                s->m_schema = xstrdup (schema);
+                
+                yaz_log (LOG_LOG, "%s: search start=%d count=%d pqf=%s",
+                         t->m_name, start, count, pqf_buf);
+                
+                wrbuf_printf (wr_log, "%s: search start=%d count=%d pqf=%s",
+                              t->m_name, start, count, pqf_buf);
+                
+                s->m_r = ZOOM_connection_search_pqf (t->m_c, s->m_query);
+                
+                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
+                if (!error)
+                    break;
+                if (error != ZOOM_ERROR_CONNECTION_LOST &&
+                    error != ZOOM_ERROR_CONNECT)
+                {
+                    yaz_log (LOG_LOG, "%s: search failed bib1-code=%d",
+                             t->m_name, error);
+                    error = diag_bib1_to_srw(error);
+                    break;
+                }
+                yaz_log (LOG_LOG, "%s: reconnect (search again)", t->m_name);
+
+                /* try once more */
+                reconnect(t);
+
+                error = ZOOM_connection_error (t->m_c, &msg, &addinfo);
+
+                if (error)
+                {
+                    error = ERROR_NO_TARGET;
+                    break;
+                }
+            }
+        }
+    }
+    
+    if (!error && t->m_c && s->m_r)
+    {
+        yaz_log (LOG_LOG, "%s: %d hits", t->m_name,
+                 ZOOM_resultset_size(s->m_r));
+        res->numberOfRecords = ZOOM_resultset_size(s->m_r);
+        
+        if (maximumRecords)
+        {
+            int i, j = 0;
+            int offset = startRecord ? *startRecord -1 : 0;
+            res->records.record =
+                soap_malloc(soap, sizeof(*res->records.record) *
+                            *maximumRecords);
+            
+            for (i = 0; i < *maximumRecords; i++)
+            {
+                char *rec_data = 0;
+                char *rec_schema = 0;
+                ZOOM_record zrec = ZOOM_resultset_record (s->m_r, offset + i);
+                if (!zrec)
+                {
+                    error = 65;
+                    addinfo = schema;
+                    break;
+                }
+                error = fetchone(soap, properties, zrec, schema,
+                                 &rec_data, &rec_schema);
+                if (error)
+                {
+                    addinfo = rec_data;
+                    break;
+                }
+                res->records.record[j] = 
+                    soap_malloc(soap, sizeof(**res->records.record));
+                res->records.record[j]->recordData = rec_data;
+                res->records.record[j]->recordSchema = rec_schema;
+                j++;
+            }
+            res->records.__sizeRecords = j;
+        }
+        else
+            res->numberOfRecords = 0;
+    }
+    if (error)
+    {
+        if (s)
+        {
+            ZOOM_resultset_destroy (s->m_r);
+            s->m_r = 0;
+        }
+        if (error == ERROR_NO_TARGET)
+        {
+            addinfo = zurl;
+            ZOOM_connection_destroy (t->m_c);
+            t->m_c = 0;
+        }
+        else
+        {
+            res->diagnostics.__sizeDiagnostics = 1;
+            res->diagnostics.diagnostic =
+                soap_malloc (soap, sizeof(*res->diagnostics.diagnostic));
+            res->diagnostics.diagnostic[0] =
+                soap_malloc (soap, sizeof(**res->diagnostics.diagnostic));
+            
+            res->diagnostics.diagnostic[0]->code = error;
+            if (addinfo)
+            {
+                res->diagnostics.diagnostic[0]->details =
+                    soap_malloc (soap, strlen(addinfo) + 1);
+                strcpy (res->diagnostics.diagnostic[0]->details, addinfo);
+            }
+            else
+                res->diagnostics.diagnostic[0]->details = 0;
+        }
+    }
+    else
+    {
+        if (s->m_r)
+        {
+            struct timeval tv;
+            const char *setname = ZOOM_resultset_option_get(s->m_r, "setname");
+            if (strcmp(setname, "default") && s->m_idle_time)
+            {
+                res->resultSetId = soap_malloc(soap, strlen(setname));
+                strcpy(res->resultSetId, setname);
+                res->resultSetIdleTime = s->m_idle_time;
+                gettimeofday(&tv, 0);
+                s->m_expiry_sec = res->resultSetIdleTime + tv.tv_sec + 2;
+            } else {
+                s->m_expiry_sec = 0;
+            }
+        }
+    }
+
+    if (t)
+    {
+        if (properties->optimize_level > 0)
+            target_leave(t);
+        else
+            target_destroy(t);
+    }
+    wrbuf_free(wr_log, 1);
+    if (error == ERROR_NO_TARGET)
+        return soap_receiver_fault(soap, "Cannot connect to Z39.50 target", 0);
+    return SOAP_OK;
+}
+
+int main(int argc, char **argv)
+{
+    struct soap soap;
+    int ret;
+    int port = 0;
+    int no_threads = 40;
+    char *arg;
+    const char *host = 0;
+    struct srw_prop properties;
+
+    properties.optimize_level = 2;
+    properties.idle_time = 300;
+    properties.max_sets = 30;
+    properties.maps = 0;
+            
+    while ((ret = options("dO:T:l:hVp:s:x:i:", argv, argc, &arg)) != -2)
+    {
+        switch(ret)
+        {
+        case 0:
+            port = atoi(arg);
+            break;
+        case 'O':
+            properties.optimize_level = atoi(arg);
+            break;
+        case 'T':
+            no_threads = atoi(arg);
+            if (no_threads < 1 || no_threads > 200)
+                no_threads = 40;
+            break;
+        case 's':
+            if (!properties.maps)
+            {
+                properties.maps = xslt_maps_create();
+                if (xslt_maps_file(properties.maps, arg))
+                {
+                    fprintf (stderr, "maps file %s could not be opened\n",
+                             arg);
+                    exit(1);
+                }
+            }
+            break;
+        case 'l':
+            yaz_log_init_file(arg);
+            break;
+        case 'V':
+            puts ("Version: $Id: srw-gateway.c,v 1.1 2003-01-06 08:20:28 adam Exp $"
+#if SRW_DEBUG
+            " DEBUG"
+#endif
+                );
+            exit (0);
+        case 'p':
+            if (cql_transform_handle == 0)
+                cql_transform_handle = cql_transform_open_fname(arg);
+            break;
+        case 'x':
+            properties.max_sets = atoi(arg);
+            break;
+        case 'i':
+            properties.idle_time = atoi(arg);
+            break;
+        case 'h':
+            printf ("srw-gateway [options] <port>\n");
+            printf ("  port  port for standalone service; If port is omitted, CGI is used.\n");
+            printf ("  -O n     optimize level. >= 1 cache connections, >=2 cache result sets.\n");
+#if USE_THREADS
+            printf ("  -T n     number of threads.\n");
+#else
+            printf ("  -T       unsupported in this version.\n");
+#endif
+            printf ("  -l file  log to file (instead of stderr).\n");
+            printf ("  -p file  PQF properties.\n");
+            printf ("  -s file  schema maps.\n");
+            printf ("  -i time  idle time.\n");
+            printf ("  -x sets  live sets.\n");
+            printf ("  -V       show version.\n");
+            exit (1);
+        default:
+            fprintf (stderr, "srw-gateway: bad option -%s ; use -h for help\n",
+                     arg);
+            exit (1);
+            break;
+            
+        }
+    }
+    if (!cql_transform_handle)
+        cql_transform_handle = cql_transform_open_fname("pqf.properties");
+    if (!properties.maps)
+    {
+        properties.maps = xslt_maps_create();
+        xslt_maps_file(properties.maps, "maps.xml");
+    }
+    soap.encodingStyle = 0;
+    if (port == 0 && getenv("QUERY_STRING"))
+    {
+        properties.optimize_level = 0;
+
+        yaz_log_init_file("srw.log");
+        yaz_log (LOG_LOG, "CGI begin");
+        soap_init(&soap);
+        soap.user = &properties;
+
+        yaz_srw_serve(&soap, &properties, searchRetrieve, explain);
+
+        soap_end(&soap);
+        yaz_log (LOG_LOG, "CGI end");
+    }
+    else if (port)
+    {
+        if (!cql_transform_handle)
+        {
+            fprintf(stderr, "no properties file; use option -p to specify\n");
+            exit (1);
+        }
+        yaz_log (LOG_LOG, "standalone service on port %d", port);
+        
+        soap_init(&soap);
+
+        standalone(&soap, host, port, no_threads, &properties);
+    }
+    else
+    {
+        fprintf(stderr, "srw-gateway: no port specified. Use -h for help\n");
+    }
+    xslt_maps_free(properties.maps);
+    return 0;
+}
index d2bb9bf..c72fc55 100644 (file)
@@ -1,6 +1,6 @@
-## Copyright (C) 1994-2002, Index Data
+## Copyright (C) 1994-2003, Index Data
 ## All rights reserved.
-## $Id: Makefile.am,v 1.14 2002-12-16 13:13:53 adam Exp $
+## $Id: Makefile.am,v 1.15 2003-01-06 08:20:28 adam Exp $
 
 noinst_LTLIBRARIES = libutil.la
 
index a99a6c1..57f9561 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1997-2002, Index Data
+ * Copyright (c) 1997-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: atoin.c,v 1.5 2002-08-27 13:18:26 adam Exp $
+ * $Id: atoin.c,v 1.6 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index 5fa4d5e..4332e92 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: log.c,v 1.32 2002-12-05 12:19:24 adam Exp $
+ * $Id: log.c,v 1.33 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index 3259d6c..8b72818 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: marcdisp.c,v 1.27 2002-12-17 13:32:04 adam Exp $
+ * $Id: marcdisp.c,v 1.28 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index f28a99b..d8fc19f 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: marcdump.c,v 1.19 2002-12-16 13:13:53 adam Exp $
+ * $Id: marcdump.c,v 1.20 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index f91ecc1..8415772 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: nmem.c,v 1.38 2002-12-05 12:19:24 adam Exp $
+ * $Id: nmem.c,v 1.39 2003-01-06 08:20:28 adam Exp $
  */
 
 /*
@@ -460,7 +460,7 @@ void yaz_strerror(char *buf, int max)
     else
        *buf = '\0';
 #else
-#if YAZ_POSIX_THREADS
+#if HAVE_STRERROR_R
     strerror_r(errno, buf, max);
 #else
     strcpy(buf, strerror(yaz_errno()));
index db08d6b..a8c485b 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: oid.c,v 1.58 2002-12-01 23:22:10 mike Exp $
+ * $Id: oid.c,v 1.59 2003-01-06 08:20:28 adam Exp $
  */
 
 /*
@@ -295,6 +295,8 @@ static oident standard_oids[] =
      "Zthes-tagset"},
     {PROTO_Z3950,   CLASS_NEGOT,   VAL_CHARNEG3,     {15,3,-1},
      "CharSetandLanguageNegotiation-3"},
+    {PROTO_Z3950,   CLASS_USERINFO,VAL_CQL,          {16, 2, -1},
+     "CQL"},
     {PROTO_GENERAL, CLASS_GENERAL, VAL_UCS2,    {1,0,10646,1,0,2,-1},
      "UCS-2"},
     {PROTO_GENERAL, CLASS_GENERAL, VAL_UCS4,    {1,0,10646,1,0,4,-1},
index b0e5611..73d7148 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1997-2002, Index Data
+ * Copyright (c) 1997-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: siconv.c,v 1.8 2002-12-16 13:13:53 adam Exp $
+ * $Id: siconv.c,v 1.9 2003-01-06 08:20:28 adam Exp $
  */
 
 /* mini iconv and wrapper for system iconv library (if present) */
index bc394b8..9f7038e 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1997-2002, Index Data
+ * Copyright (c) 1997-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: siconvtst.c,v 1.7 2002-12-16 13:13:53 adam Exp $
+ * $Id: siconvtst.c,v 1.8 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index e205321..f04df3e 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: tpath.c,v 1.8 2002-04-05 12:49:13 adam Exp $
+ * $Id: tpath.c,v 1.9 2003-01-06 08:20:28 adam Exp $
  */
 #if HAVE_CONFIG_H
 #include <config.h>
index c3fea1f..338ce09 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: wrbuf.c,v 1.11 2002-10-22 14:40:21 adam Exp $
+ * $Id: wrbuf.c,v 1.12 2003-01-06 08:20:28 adam Exp $
  */
 
 /*
index dc9b431..96bc73a 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 1994-2002, Index Data
+ * Copyright (C) 1994-2003, Index Data
  * All rights reserved.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: xmalloc.c,v 1.17 2002-06-18 21:30:39 adam Exp $
+ * $Id: xmalloc.c,v 1.18 2003-01-06 08:20:28 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index 9e177c7..478dc66 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 1995-2002, Index Data.
+Copyright (c) 1995-2003, Index Data.
 
 Permission to use, copy, modify, distribute, and sell this software and its documentation, in whole or in part, for any purpose, is hereby granted, provided that:
 
index 366020d..98567de 100644 (file)
@@ -75,7 +75,7 @@ BEGIN
             VALUE "FileDescription", "YAZ Toolkit\0"
             VALUE "FileVersion", "1, 9, 2, 1\0"
             VALUE "InternalName", "YAZ\0"
-            VALUE "LegalCopyright", "Copyright Â© 1995-2002 Index Data\0"
+            VALUE "LegalCopyright", "Copyright Â© 1995-2003 Index Data\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "yaz.rc\0"
             VALUE "PrivateBuild", "\0"
index efa7398..5faf6d0 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: yaz-config.in,v 1.14 2002-12-09 23:29:00 adam Exp $
+# $Id: yaz-config.in,v 1.15 2003-01-06 08:20:26 adam Exp $
 yazprefix=@prefix@
 yaz_echo_cflags=no
 yaz_echo_libs=no
@@ -10,7 +10,7 @@ yaz_echo_comp=no
 yaz_src_root=@YAZ_SRC_ROOT@
 yaz_build_root=@YAZ_BUILD_ROOT@
 
-yazextralibs="@LIBS@"
+yazextralibs="@GSOAP_LIB@ @XSLT_LIB@ @LIBS@"
 YAZVERSION=@VERSION@
 
 usage()
index 03c1cf5..7e9bc41 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: prt-ext.c,v 1.4 2002-12-05 12:07:00 adam Exp $
+ * $Id: prt-ext.c,v 1.5 2003-01-06 08:20:28 adam Exp $
  */
 
 #include <yaz/proto.h>
@@ -38,6 +38,7 @@ static Z_ext_typeent type_table[] =
     {VAL_DES1, Z_External_acfDes1, (Odr_fun) z_DES_RN_Object},
     {VAL_KRB1, Z_External_acfKrb1, (Odr_fun) z_KRBObject},
     {VAL_MULTISRCH2, Z_External_multisrch2, (Odr_fun) z_MultipleSearchTerms_2},
+    {VAL_CQL, Z_External_CQL, (Odr_fun) z_InternationalString},
     {VAL_NONE, 0, 0}
 };
 
@@ -117,6 +118,8 @@ int z_External(ODR o, Z_External **p, int opt, const char *name)
          (Odr_fun)z_KRBObject, 0},
         {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_multisrch2,
          (Odr_fun)z_MultipleSearchTerms_2, 0},
+        {ODR_EXPLICIT, ODR_CONTEXT, 0, Z_External_CQL,
+         (Odr_fun)z_InternationalString, 0},
        {-1, -1, -1, -1, 0, 0}
     };
     
index 875e548..42c7ee8 100644 (file)
@@ -140,7 +140,9 @@ IdAuthentication ::=
         type-2      [2]  OCTET STRING,
         type-100  [100]  OCTET STRING,
         type-101  [101]  IMPLICIT RPNQuery,
-       type-102  [102]  OCTET STRING}
+       type-102  [102]  OCTET STRING,
+       type-104  [104]  IMPLICIT EXTERNAL
+}
 --
 -- Definitions for RPN query
      RPNQuery ::= SEQUENCE{
index cbb8301..235e489 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am,v 1.6 2002-09-24 08:00:50 adam Exp $
+## $Id: Makefile.am,v 1.7 2003-01-06 08:20:28 adam Exp $
 ## Copyright (C) 2001, Index Data
 
 AM_CPPFLAGS = -I$(top_srcdir)/include
@@ -6,15 +6,15 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
 noinst_PROGRAMS = zoomtst1 zoomtst2 zoomtst3 zoomtst4 zoomtst5 zoomtst6 zoomtst7 zoomtst8
 bin_PROGRAMS = zoomsh
 
-zoomtst1_LDADD = ../lib/libyaz.la
-zoomtst2_LDADD = ../lib/libyaz.la
-zoomtst3_LDADD = ../lib/libyaz.la
-zoomtst4_LDADD = ../lib/libyaz.la
-zoomtst5_LDADD = ../lib/libyaz.la
-zoomtst6_LDADD = ../lib/libyaz.la
-zoomtst7_LDADD =../lib/libyazmalloc.la ../lib/libyaz.la 
-zoomtst8_LDADD = ../lib/libyaz.la 
-zoomsh_LDADD = ../lib/libyaz.la $(READLINE_LIBS)
+zoomtst1_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst2_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst3_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst4_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst5_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst6_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst7_LDADD = ../lib/libyazmalloc.la ../lib/libyaz.la $(GSOAP_LIB)
+zoomtst8_LDADD = ../lib/libyaz.la $(GSOAP_LIB)
+zoomsh_LDADD = ../lib/libyaz.la $(GSOAP_LIB) $(READLINE_LIBS) 
 
 zoomtst1_SOURCES = zoomtst1.c
 zoomtst2_SOURCES = zoomtst2.c
index 6aedbd0..bf35f6a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: zoomsh.c,v 1.11 2002-06-05 21:09:20 adam Exp $
+ * $Id: zoomsh.c,v 1.12 2003-01-06 08:20:28 adam Exp $
  *
  * ZOOM-C Shell
  */
@@ -168,14 +168,14 @@ static void cmd_show (ZOOM_connection *c, ZOOM_resultset *r,
     for (i = 0; i<MAX_CON; i++)
     {
        int error;
-       const char *errmsg, *addinfo;
+       const char *errmsg, *addinfo, *dset;
        /* display errors if any */
        if (!c[i])
            continue;
-       if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
-           fprintf (stderr, "%s error: %s (%d) %s\n",
+       if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
+           fprintf (stderr, "%s error: %s (%s:%d) %s\n",
                     ZOOM_connection_option_get(c[i], "host"), errmsg,
-                    error, addinfo);
+                    dset, error, addinfo);
        else if (r[i])
        {
            /* OK, no major errors. Display records... */
@@ -211,14 +211,14 @@ static void cmd_ext (ZOOM_connection *c, ZOOM_resultset *r,
     for (i = 0; i<MAX_CON; i++)
     {
        int error;
-       const char *errmsg, *addinfo;
+       const char *errmsg, *addinfo, *dset;
        /* display errors if any */
        if (!p[i])
            continue;
-       if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
-           fprintf (stderr, "%s error: %s (%d) %s\n",
+       if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
+           fprintf (stderr, "%s error: %s (%s:%d) %s\n",
                     ZOOM_connection_option_get(c[i], "host"), errmsg,
-                    error, addinfo);
+                    dset, error, addinfo);
        else if (p[i])
        {
             printf ("ok\n");
@@ -232,12 +232,19 @@ static void cmd_search (ZOOM_connection *c, ZOOM_resultset *r,
                        const char **args)
 {
     ZOOM_query s;
+    const char *query_str = *args;
     int i;
     
     s = ZOOM_query_create ();
-    if (ZOOM_query_prefix (s, *args))
+    while (*query_str == ' ')
+        query_str++;
+    if (memcmp(query_str, "cql:", 4) == 0)
     {
-       fprintf (stderr, "Bad PQF: %s\n", *args);
+        ZOOM_query_cql (s, query_str + 4);
+    }
+    else if (ZOOM_query_prefix (s, query_str))
+    {
+       fprintf (stderr, "Bad PQF: %s\n", query_str);
        return;
     }
     for (i = 0; i<MAX_CON; i++)
@@ -257,14 +264,14 @@ static void cmd_search (ZOOM_connection *c, ZOOM_resultset *r,
     for (i = 0; i<MAX_CON; i++)
     {
        int error;
-       const char *errmsg, *addinfo;
+       const char *errmsg, *addinfo, *dset;
        /* display errors if any */
        if (!c[i])
            continue;
-       if ((error = ZOOM_connection_error(c[i], &errmsg, &addinfo)))
-           fprintf (stderr, "%s error: %s (%d) %s\n",
+       if ((error = ZOOM_connection_error_x(c[i], &errmsg, &addinfo, &dset)))
+           fprintf (stderr, "%s error: %s (%s:%d) %s\n",
                     ZOOM_connection_option_get(c[i], "host"), errmsg,
-                    error, addinfo);
+                    dset, error, addinfo);
        else if (r[i])
        {
            /* OK, no major errors. Look at the result count */
index 9cc9c48..2bc09f9 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: read-grs.c,v 1.7 2002-03-18 21:33:48 adam Exp $
+ * $Id: read-grs.c,v 1.8 2003-01-06 08:20:29 adam Exp $
  */
 
 /*
index 7241d5f..d476d0c 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: ztest.c,v 1.53 2002-07-31 14:06:29 adam Exp $
+ * $Id: ztest.c,v 1.54 2003-01-06 08:20:29 adam Exp $
  */
 
 /*
index c51847a..2b848ba 100644 (file)
@@ -1,7 +1,7 @@
-## $Id: Makefile.am,v 1.13 2002-10-22 10:05:36 adam Exp $
+## $Id: Makefile.am,v 1.14 2003-01-06 08:20:29 adam Exp $
 noinst_LTLIBRARIES = libzutil.la
 
-AM_CPPFLAGS=-I$(top_srcdir)/include 
+AM_CPPFLAGS=-I$(top_srcdir)/include -I$(top_srcdir)/srw
 
 libzutil_la_SOURCES = zget.c yaz-ccl.c diagbib1.c logrpn.c \
   otherinfo.c pquery.c sortspec.c z3950oid.c charneg.c \
index 234dd7b..8da3884 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: diagbib1.c,v 1.5 2002-09-13 11:28:17 adam Exp $
+ * $Id: diagbib1.c,v 1.6 2003-01-06 08:20:29 adam Exp $
  */
 
 #include <stdio.h>
index 95460cb..229c59f 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-2001, Index Data
  * All rights reserved.
  *
- * $Id: logrpn.c,v 1.8 2002-12-28 12:13:03 adam Exp $
+ * $Id: logrpn.c,v 1.9 2003-01-06 08:20:29 adam Exp $
  */
 #include <stdio.h>
 
@@ -350,3 +350,17 @@ void log_scan_term (Z_AttributesPlusTerm *zapt, oid_value ast)
        yaz_log (LOG_LOG, "%*.0s term (not general)", level, "");
     zlog_attributes (zapt, level+2, ast);
 }
+
+void yaz_log_zquery (Z_Query *q)
+{
+    static int cql_oid[] = {1, 2, 840, 10003, 16, 2, -1};
+    switch (q->which)
+    {
+    case Z_Query_type_1: case Z_Query_type_101:
+       log_rpn_query (q->u.type_1);
+        break;
+    case Z_Query_type_104:
+        if (q->u.type_104->which == Z_External_CQL)
+            yaz_log (LOG_LOG, "CQL: %s", q->u.type_104->u.cql);
+    }
+}
index 2ba4303..9ee8550 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1999-2002, Index Data
+ * Copyright (c) 1999-2003, Index Data
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: otherinfo.c,v 1.6 2002-02-11 23:25:27 adam Exp $
+ * $Id: otherinfo.c,v 1.7 2003-01-06 08:20:29 adam Exp $
  */
 
 #include <stdio.h>
index 59e2833..2840557 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: pquery.c,v 1.19 2002-12-05 12:07:00 adam Exp $
+ * $Id: pquery.c,v 1.20 2003-01-06 08:20:29 adam Exp $
  */
 
 #include <stdio.h>
index 7da9fbd..12456d3 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1996-2002, Index Data.
+ * Copyright (c) 1996-2003, Index Data.
  * See the file LICENSE for details.
  *
- * $Id: yaz-ccl.c,v 1.17 2002-12-28 12:16:26 adam Exp $
+ * $Id: yaz-ccl.c,v 1.18 2003-01-06 08:20:29 adam Exp $
  */
 
 #include <stdio.h>
index 90f6b66..95687a0 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * Copyright (c) 1995-2002, Index Data
+ * Copyright (c) 1995-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: z3950oid.c,v 1.4 2002-09-20 22:30:01 adam Exp $
+ * $Id: z3950oid.c,v 1.5 2003-01-06 08:20:29 adam Exp $
  */
 
 #if HAVE_CONFIG_H
index dfbb2a6..9ee6801 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 1995-2002, Index Data.
+ * Copyright (c) 1995-2003, Index Data.
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
- * $Id: zget.c,v 1.12 2002-04-25 08:34:08 adam Exp $
+ * $Id: zget.c,v 1.13 2003-01-06 08:20:29 adam Exp $
  */
 
 #include <yaz/proto.h>
index 8506a26..cf5b67f 100644 (file)
@@ -1,12 +1,15 @@
 /*
- * Copyright (c) 2000-2002, Index Data
+ * Copyright (c) 2000-2003, Index Data
  * See the file LICENSE for details.
  *
- * $Id: zoom-c.c,v 1.12 2002-12-16 13:13:54 adam Exp $
+ * $Id: zoom-c.c,v 1.13 2003-01-06 08:20:29 adam Exp $
  *
  * ZOOM layer for C, connections, result sets, queries.
  */
 #include <assert.h>
+#include <string.h>
+#include "zoom-p.h"
+
 #include <yaz/xmalloc.h>
 #include <yaz/otherinfo.h>
 #include <yaz/log.h>
@@ -16,7 +19,6 @@
 #include <yaz/charneg.h>
 #include <yaz/ill.h>
 
-#include "zoom-p.h"
 
 #if HAVE_SYS_POLL_H
 #include <sys/poll.h>
@@ -27,7 +29,6 @@ typedef enum {
     zoom_complete
 } zoom_ret;
 
-
 static zoom_ret ZOOM_connection_send_init (ZOOM_connection c);
 static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out);
 
@@ -88,6 +89,17 @@ static void set_bib1_error (ZOOM_connection c, int error)
     c->diagset = "Bib-1";
 }
 
+static void set_ZOOM_error (ZOOM_connection c, int error,
+                           const char *addinfo)
+{
+    xfree (c->addinfo);
+    c->addinfo = 0;
+    c->error = error;
+    c->diagset = "ZOOM";
+    if (addinfo)
+        c->addinfo = xstrdup(addinfo);
+}
+
 static void clear_error (ZOOM_connection c)
 {
 
@@ -99,9 +111,10 @@ static void clear_error (ZOOM_connection c)
     case ZOOM_ERROR_CONNECTION_LOST:
     case ZOOM_ERROR_INIT:
     case ZOOM_ERROR_INTERNAL:
+    case ZOOM_ERROR_UNSUPPORTED_PROTOCOL:
         break;
     default:
-        set_bib1_error(c, ZOOM_ERROR_NONE);
+        set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     }
 }
 
@@ -174,12 +187,13 @@ ZOOM_connection_create (ZOOM_options options)
 {
     ZOOM_connection c = (ZOOM_connection) xmalloc (sizeof(*c));
 
+    c->soap = 0;
     c->cs = 0;
     c->mask = 0;
     c->reconnect_ok = 0;
     c->state = STATE_IDLE;
     c->addinfo = 0;
-    set_bib1_error(c, ZOOM_ERROR_NONE);
+    set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
     c->buf_in = 0;
     c->len_in = 0;
     c->buf_out = 0;
@@ -333,7 +347,7 @@ ZOOM_connection_connect(ZOOM_connection c,
 
     c->async = ZOOM_options_get_bool (c->options, "async", 0);
  
-    set_bib1_error(c, ZOOM_ERROR_NONE);
+    set_ZOOM_error(c, ZOOM_ERROR_NONE, 0);
 
     task = ZOOM_connection_add_task (c, ZOOM_TASK_CONNECT);
 
@@ -350,7 +364,7 @@ ZOOM_query_create(void)
     ZOOM_query s = (ZOOM_query) xmalloc (sizeof(*s));
 
     s->refcount = 1;
-    s->query = 0;
+    s->z_query = 0;
     s->sort_spec = 0;
     s->odr = odr_createmem (ODR_ENCODE);
 
@@ -375,15 +389,35 @@ ZOOM_query_destroy(ZOOM_query s)
 ZOOM_API(int)
 ZOOM_query_prefix(ZOOM_query s, const char *str)
 {
-    s->query = (Z_Query *) odr_malloc (s->odr, sizeof(*s->query));
-    s->query->which = Z_Query_type_1;
-    s->query->u.type_1 =  p_query_rpn(s->odr, PROTO_Z3950, str);
-    if (!s->query->u.type_1)
+    s->z_query = (Z_Query *) odr_malloc (s->odr, sizeof(*s->z_query));
+    s->z_query->which = Z_Query_type_1;
+    s->z_query->u.type_1 =  p_query_rpn(s->odr, PROTO_Z3950, str);
+    if (!s->z_query->u.type_1)
        return -1;
     return 0;
 }
 
 ZOOM_API(int)
+ZOOM_query_cql(ZOOM_query s, const char *str)
+{
+    Z_External *ext;
+    char *buf;
+    int len;
+
+    ext = (Z_External *) odr_malloc(s->odr, sizeof(*ext));
+    ext->direct_reference = odr_getoidbystr(s->odr, "1.2.840.10003.16.2");
+    ext->indirect_reference = 0;
+    ext->descriptor = 0;
+    ext->which = Z_External_CQL;
+    ext->u.cql = odr_strdup(s->odr, str);
+    
+    s->z_query = (Z_Query *) odr_malloc (s->odr, sizeof(*s->z_query));
+    s->z_query->which = Z_Query_type_104;
+    s->z_query->u.type_104 =  ext;
+    return 0;
+}
+
+ZOOM_API(int)
 ZOOM_query_sortby(ZOOM_query s, const char *criteria)
 {
     s->sort_spec = yaz_sort_spec (s->odr, criteria);
@@ -400,6 +434,10 @@ ZOOM_connection_destroy(ZOOM_connection c)
     ZOOM_resultset r;
     if (!c)
        return;
+#if HAVE_GSOAP
+    if (c->soap)
+        soap_end(c->soap);
+#endif
     if (c->cs)
        cs_close (c->cs);
     for (r = c->resultsets; r; r = r->next)
@@ -444,7 +482,7 @@ ZOOM_resultset ZOOM_resultset_create ()
     r->count = 0;
     r->record_cache = 0;
     r->r_sort_spec = 0;
-    r->r_query = 0;
+    r->z_query = 0;
     r->search = 0;
     r->connection = 0;
     r->next = 0;
@@ -472,7 +510,7 @@ ZOOM_connection_search(ZOOM_connection c, ZOOM_query q)
     const char *cp;
 
     r->r_sort_spec = q->sort_spec;
-    r->r_query = q->query;
+    r->z_query = q->z_query;
     r->search = q;
 
     r->options = ZOOM_options_create_with_parent(c->options);
@@ -611,32 +649,46 @@ static zoom_ret do_connect (ZOOM_connection c)
     yaz_log (LOG_DEBUG, "do_connect host=%s", effective_host);
 
     assert (!c->cs);
-    c->cs = cs_create_host (effective_host, 0, &add);
 
-    if (c->cs)
+    if (memcmp(c->host_port, "http:", 5) == 0)
+    {
+#if HAVE_GSOAP
+        c->soap = soap_new();
+        c->soap->namespaces = srw_namespaces;
+#else
+        c->state = STATE_IDLE;
+        set_ZOOM_error(c, ZOOM_ERROR_UNSUPPORTED_PROTOCOL, "SRW");
+#endif
+    }
+    else
     {
-       int ret = cs_connect (c->cs, add);
-        if (ret == 0)
+        c->cs = cs_create_host (effective_host, 0, &add);
+        
+        if (c->cs)
         {
-            ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
-            ZOOM_connection_put_event(c, event);
-            ZOOM_connection_send_init(c);
-            c->state = STATE_ESTABLISHED;
-            return zoom_pending;
+            int ret = cs_connect (c->cs, add);
+            if (ret == 0)
+            {
+                ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_CONNECT);
+                ZOOM_connection_put_event(c, event);
+                ZOOM_connection_send_init(c);
+                c->state = STATE_ESTABLISHED;
+                return zoom_pending;
+            }
+            else if (ret > 0)
+            {
+                c->state = STATE_CONNECTING; 
+                c->mask = ZOOM_SELECT_EXCEPT;
+                if (c->cs->io_pending & CS_WANT_WRITE)
+                    c->mask += ZOOM_SELECT_WRITE;
+                if (c->cs->io_pending & CS_WANT_READ)
+                    c->mask += ZOOM_SELECT_READ;
+                return zoom_pending;
+            }
         }
-        else if (ret > 0)
-       {
-           c->state = STATE_CONNECTING; 
-            c->mask = ZOOM_SELECT_EXCEPT;
-            if (c->cs->io_pending & CS_WANT_WRITE)
-                c->mask += ZOOM_SELECT_WRITE;
-            if (c->cs->io_pending & CS_WANT_READ)
-                c->mask += ZOOM_SELECT_READ;
-           return zoom_pending;
-       }
+        c->state = STATE_IDLE;
+        set_ZOOM_error(c, ZOOM_ERROR_CONNECT, effective_host);
     }
-    c->state = STATE_IDLE;
-    set_bib1_error(c, ZOOM_ERROR_CONNECT);
     return zoom_complete;
 }
 
@@ -715,7 +767,7 @@ static int encode_APDU(ZOOM_connection c, Z_APDU *a, ODR out)
            odr_destroy(odr_pr);
        }
         yaz_log (LOG_DEBUG, "encoding failed");
-        set_bib1_error(c, ZOOM_ERROR_ENCODE);
+        set_ZOOM_error(c, ZOOM_ERROR_ENCODE, 0);
        odr_reset(out);
        return -1;
     }
@@ -880,10 +932,10 @@ static zoom_ret ZOOM_connection_send_search (ZOOM_connection c)
        mediumSetElementSetName = elementSetName;
 
     assert (r);
-    assert (r->r_query);
+    assert (r->z_query);
 
     /* prepare query for the search request */
-    search_req->query = r->r_query;
+    search_req->query = r->z_query;
 
     search_req->databaseNames =
        set_DatabaseNames (c, r->options, &search_req->num_databaseNames);
@@ -979,7 +1031,7 @@ static void response_diag (ZOOM_connection c, Z_DiagRec *p)
     c->addinfo = 0;
     if (p->which != Z_DiagRec_defaultFormat)
     {
-        set_bib1_error(c, ZOOM_ERROR_DECODE);
+        set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
        return;
     }
     r = p->u.defaultFormat;
@@ -1235,7 +1287,6 @@ static void record_cache_add (ZOOM_resultset r, Z_NamePlusRecord *npr, int pos)
     const char *syntax = 
         ZOOM_resultset_option_get (r, "preferredRecordSyntax");
     
-
     for (rc = r->record_cache; rc; rc = rc->next)
     {
        if (pos == rc->pos)
@@ -1332,7 +1383,7 @@ static void handle_records (ZOOM_connection c, Z_Records *sr,
        if (sr->u.multipleNonSurDiagnostics->num_diagRecs >= 1)
            response_diag(c, sr->u.multipleNonSurDiagnostics->diagRecs[0]);
        else
-            set_bib1_error(c, ZOOM_ERROR_DECODE);
+            set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
     }
     else 
     {
@@ -1357,13 +1408,13 @@ static void handle_records (ZOOM_connection c, Z_Records *sr,
            if (present_phase && p->num_records == 0)
            {
                /* present response and we didn't get any records! */
-               c->error = ZOOM_ERROR_DECODE;
+                set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
            }
        }
        else if (present_phase)
        {
            /* present response and we didn't get any records! */
-            set_bib1_error(c, ZOOM_ERROR_DECODE);
+            set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
        }
     }
 }
@@ -1936,6 +1987,84 @@ ZOOM_package_option_get (ZOOM_package p, const char *key)
     return ZOOM_options_get (p->options, key);
 }
 
+#if HAVE_GSOAP
+static zoom_ret ZOOM_srw_search(ZOOM_connection c, ZOOM_resultset r,
+                                const char *cql)
+{
+    int ret;
+    struct xcql__operandType *xQuery = 0;
+    char *action = 0;
+    xsd__integer startRecord = r->start + 1;
+    xsd__integer maximumRecord = r->count;
+    const char *schema = ZOOM_resultset_option_get (r, "schema");
+    struct zs__searchRetrieveResponse res;
+    xsd__string recordPacking = 0;
+    
+
+    if (!schema)
+        schema = "http://www.loc.gov/marcxml/";
+
+    ret = soap_call_zs__searchRetrieveRequest(c->soap, c->host_port,
+                                              action,
+                                              &r->z_query->u.type_104->u.cql,
+                                              xQuery, 
+                                              0, 0,
+                                              &startRecord, &maximumRecord,
+                                              (char **) &schema,
+                                              &recordPacking,
+                                              &res);
+    if (ret != SOAP_OK)
+    {
+        const char **s = soap_faultdetail(c->soap);
+        xfree (c->addinfo);
+        c->addinfo = 0;
+        if (s && *s)
+            c->addinfo = xstrdup(*s);
+        c->diagset = "SOAP";
+        c->error = ret;
+    }
+    else
+    {
+        if (res.diagnostics.__sizeDiagnostics > 0)
+        {
+            int i = 0;
+            xfree (c->addinfo);
+            c->addinfo = 0;
+            c->diagset = "SRW";
+            c->error = res.diagnostics.diagnostic[i]->code;
+            if (res.diagnostics.diagnostic[i]->details)
+                c->addinfo =
+                    xstrdup(res.diagnostics.diagnostic[i]->details);
+            
+        }
+        else
+        {
+            int i;
+            r->size = res.numberOfRecords;
+            if (res.resultSetId)
+                r->setname = xstrdup(res.resultSetId);
+            for (i = 0; i < res.records.__sizeRecords; i++)
+            {
+                char *rdata = res.records.record[i]->recordData;
+                if (rdata)
+                {
+                    Z_NamePlusRecord *npr =
+                        odr_malloc(r->odr, sizeof(*npr));
+                    Z_External *ext =
+                        z_ext_record(r->odr, VAL_TEXT_XML,
+                                     rdata, strlen(rdata));
+                    npr->databaseName = 0;
+                    npr->which = Z_NamePlusRecord_databaseRecord;
+                    npr->u.databaseRecord = ext;
+                    record_cache_add (r, npr, r->start + i);
+                }
+            }
+        }
+    }
+    return zoom_complete;
+}
+#endif
+
 ZOOM_API(void)
 ZOOM_package_option_set (ZOOM_package p, const char *key,
                               const char *val)
@@ -1955,8 +2084,7 @@ static int ZOOM_connection_exec_task (ZOOM_connection c)
     }
     yaz_log (LOG_DEBUG, "ZOOM_connection_exec_task type=%d run=%d",
              task->which, task->running);
-    if (c->error != ZOOM_ERROR_NONE ||
-        (!c->cs && task->which != ZOOM_TASK_CONNECT))
+    if (c->error != ZOOM_ERROR_NONE)
     {
         yaz_log (LOG_DEBUG, "remove tasks because of error = %d", c->error);
         ZOOM_connection_remove_tasks (c);
@@ -1968,23 +2096,67 @@ static int ZOOM_connection_exec_task (ZOOM_connection c)
        return 0;
     }
     task->running = 1;
-    switch (task->which)
+    ret = zoom_complete;
+    if (c->soap)
     {
-    case ZOOM_TASK_SEARCH:
-       ret = ZOOM_connection_send_search (c);
-       break;
-    case ZOOM_TASK_RETRIEVE:
-       ret = send_present (c);
-       break;
-    case ZOOM_TASK_CONNECT:
-        ret = do_connect(c);
-        break;
-    case ZOOM_TASK_SCAN:
-        ret = send_scan(c);
-        break;
-    case ZOOM_TASK_PACKAGE:
-        ret = send_package(c);
-        break;
+#if HAVE_GSOAP
+        ZOOM_resultset resultset;
+        switch (task->which)
+        {
+        case ZOOM_TASK_SEARCH:
+            resultset = c->tasks->u.search.resultset;
+            if (resultset->z_query && 
+                resultset->z_query->which == Z_Query_type_104
+                && resultset->z_query->u.type_104->which == Z_External_CQL)
+                ret = ZOOM_srw_search(c, resultset, 
+                                      resultset->z_query->u.type_104->u.cql);
+            break;
+        case ZOOM_TASK_RETRIEVE:
+            resultset = c->tasks->u.retrieve.resultset;
+            resultset->start = c->tasks->u.retrieve.start;
+            resultset->count = c->tasks->u.retrieve.count;
+
+            if (resultset->start >= resultset->size)
+                return zoom_complete;
+            if (resultset->start + resultset->count > resultset->size)
+                resultset->count = resultset->size - resultset->start;
+
+            if (resultset->z_query && 
+                resultset->z_query->which == Z_Query_type_104
+                && resultset->z_query->u.type_104->which == Z_External_CQL)
+                ret = ZOOM_srw_search(c, resultset, 
+                                      resultset->z_query->u.type_104->u.cql);
+            break;
+        }
+#else
+        ;
+#endif
+    }
+    else if (c->cs || task->which == ZOOM_TASK_CONNECT)
+    {
+        switch (task->which)
+        {
+        case ZOOM_TASK_SEARCH:
+            ret = ZOOM_connection_send_search(c);
+            break;
+        case ZOOM_TASK_RETRIEVE:
+            ret = send_present (c);
+            break;
+        case ZOOM_TASK_CONNECT:
+            ret = do_connect(c);
+            break;
+        case ZOOM_TASK_SCAN:
+            ret = send_scan(c);
+            break;
+        case ZOOM_TASK_PACKAGE:
+            ret = send_package(c);
+            break;
+        }
+    }
+    else
+    {
+        yaz_log (LOG_DEBUG, "remove tasks because no connection exist");
+        ZOOM_connection_remove_tasks (c);
     }
     if (ret == zoom_complete)
     {
@@ -2046,7 +2218,7 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
                                    initrs->implementationVersion : "");
        if (!*initrs->result)
        {
-            set_bib1_error(c, ZOOM_ERROR_INIT);
+            set_ZOOM_error(c, ZOOM_ERROR_INIT, 0);
        }
        else
        {
@@ -2124,12 +2296,12 @@ static void handle_apdu (ZOOM_connection c, Z_APDU *apdu)
         }
         else
         {
-            set_bib1_error(c, ZOOM_ERROR_CONNECTION_LOST);
+            set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, 0);
             do_close(c);
         }
         break;
     default:
-        set_bib1_error(c, ZOOM_ERROR_DECODE);
+        set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
         do_close(c);
     }
 }
@@ -2160,7 +2332,7 @@ static int do_read (ZOOM_connection c)
         }
         else
         {
-            c->error= ZOOM_ERROR_CONNECTION_LOST;
+            set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, 0);
             do_close (c);
         }
     }
@@ -2173,7 +2345,7 @@ static int do_read (ZOOM_connection c)
         ZOOM_connection_put_event (c, event);
        if (!z_APDU (c->odr_in, &apdu, 0, 0))
        {
-            set_bib1_error(c, ZOOM_ERROR_DECODE);
+            set_ZOOM_error(c, ZOOM_ERROR_DECODE, 0);
            do_close (c);
        }
        else
@@ -2204,9 +2376,9 @@ static zoom_ret do_write_ex (ZOOM_connection c, char *buf_out, int len_out)
             return zoom_complete;
         }
        if (c->state == STATE_CONNECTING)
-           set_bib1_error(c, ZOOM_ERROR_CONNECT);
+           set_ZOOM_error(c, ZOOM_ERROR_CONNECT, 0);
        else
-            set_bib1_error(c, ZOOM_ERROR_CONNECTION_LOST);
+            set_ZOOM_error(c, ZOOM_ERROR_CONNECTION_LOST, 0);
        do_close (c);
        return zoom_complete;
     }
@@ -2305,6 +2477,8 @@ ZOOM_diag_str (int error)
        return "Internal failure";
     case ZOOM_ERROR_TIMEOUT:
        return "Timeout";
+    case ZOOM_ERROR_UNSUPPORTED_PROTOCOL:
+       return "Unsupported protocol";
     default:
        return diagbib1_str (error);
     }
@@ -2317,7 +2491,22 @@ ZOOM_connection_error_x (ZOOM_connection c, const char **cp,
     int error = c->error;
     if (cp)
     {
-       *cp = ZOOM_diag_str(error);
+        if (!c->diagset)
+            *cp = ZOOM_diag_str(error);
+#if HAVE_GSOAP
+        else if (!strcmp(c->diagset, "SRW"))
+            *cp = yaz_srw_diag_str(error);
+        else if (c->soap && !strcmp(c->diagset, "SOAP"))
+        {
+            const char **s = soap_faultstring(c->soap);
+            if (s && *s)
+                *cp = *s;
+            else
+                *cp = "unknown";
+        }
+#endif
+        else
+            *cp = ZOOM_diag_str(error);
     }
     if (addinfo)
         *addinfo = c->addinfo ? c->addinfo : "";
@@ -2343,7 +2532,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
     if (r == CS_NONE)
     {
         event = ZOOM_Event_create (ZOOM_EVENT_CONNECT);
-       set_bib1_error(c, ZOOM_ERROR_CONNECT);
+       set_ZOOM_error(c, ZOOM_ERROR_CONNECT, 0);
        do_close (c);
         ZOOM_connection_put_event (c, event);
     }
@@ -2371,7 +2560,7 @@ static int ZOOM_connection_do_io(ZOOM_connection c, int mask)
         }
         else
         {
-            set_bib1_error(c, ZOOM_ERROR_CONNECT);
+            set_ZOOM_error(c, ZOOM_ERROR_CONNECT, 0);
             do_close (c);
             ZOOM_connection_put_event (c, event);
         }
@@ -2520,7 +2709,7 @@ ZOOM_event (int no, ZOOM_connection *cs)
         {
             ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
            /* timeout and this connection was waiting */
-           set_bib1_error(c, ZOOM_ERROR_TIMEOUT);
+           set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT, 0);
             do_close (c);
             ZOOM_connection_put_event(c, event);
         }
@@ -2556,7 +2745,7 @@ ZOOM_event (int no, ZOOM_connection *cs)
        {
             ZOOM_Event event = ZOOM_Event_create(ZOOM_EVENT_TIMEOUT);
            /* timeout and this connection was waiting */
-           set_bib1_error(c, ZOOM_ERROR_TIMEOUT);
+           set_ZOOM_error(c, ZOOM_ERROR_TIMEOUT);
             do_close (c);
             yaz_log (LOG_DEBUG, "timeout");
             ZOOM_connection_put_event(c, event);
index 9e789b6..02a7ae0 100644 (file)
@@ -1,14 +1,13 @@
 /*
- * $Id: zoom-opt.c,v 1.2 2002-09-24 08:05:42 adam Exp $
+ * $Id: zoom-opt.c,v 1.3 2003-01-06 08:20:29 adam Exp $
  *
  * ZOOM layer for C, options handling
  */
 #include <assert.h>
-#include <yaz/xmalloc.h>
-#include <yaz/log.h>
-
 #include "zoom-p.h"
 
+#include <yaz/xmalloc.h>
+
 ZOOM_API(ZOOM_options)
 ZOOM_options_create_with_parent (ZOOM_options parent)
 {
index c8210e0..0f7a81e 100644 (file)
@@ -1,17 +1,25 @@
 /*
  * Private C header for ZOOM C.
- * $Id: zoom-p.h,v 1.2 2002-12-09 23:32:29 adam Exp $
+ * $Id: zoom-p.h,v 1.3 2003-01-06 08:20:29 adam Exp $
  */
+
+#if HAVE_GSOAP
+#include <yaz/srw-util.h>
+#else
+struct soap {
+    int dummy;
+};
+#endif
+
 #include <yaz/proto.h>
 #include <yaz/comstack.h>
 #include <yaz/wrbuf.h>
 #include <yaz/zoom.h>
 #include <yaz/sortspec.h>
-
 typedef struct ZOOM_Event_p *ZOOM_Event;
 
 struct ZOOM_query_p {
-    Z_Query *query;
+    Z_Query *z_query;
     Z_SortKeySpecList *sort_spec;
     int refcount;
     ODR odr;
@@ -26,6 +34,7 @@ struct ZOOM_query_p {
 #define ZOOM_SELECT_EXCEPT 4
 
 struct ZOOM_connection_p {
+    struct soap *soap;
     COMSTACK cs;
     char *host_port;
     int error;
@@ -75,7 +84,7 @@ struct ZOOM_options_p {
 typedef struct ZOOM_record_cache_p *ZOOM_record_cache;
 
 struct ZOOM_resultset_p {
-    Z_Query *r_query;
+    Z_Query *z_query;
     Z_SortKeySpecList *r_sort_spec;
     ZOOM_query search;
     int refcount;