Back-ported the rsbetween from zebra 1.4
authorHeikki Levanto <heikki@indexdata.dk>
Thu, 16 Dec 2004 19:11:41 +0000 (19:11 +0000)
committerHeikki Levanto <heikki@indexdata.dk>
Thu, 16 Dec 2004 19:11:41 +0000 (19:11 +0000)
Still quite ugly, but seems to work

rset/rsbetween.c
test/xpath/Makefile.am
test/xpath/assembled.abs [new file with mode: 0644]
test/xpath/rec61.xml [new file with mode: 0644]
test/xpath/rec62.xml [new file with mode: 0644]
test/xpath/test6.sh [new file with mode: 0755]
test/xpath/zebra6.cfg [new file with mode: 0644]

index 91d1ece..dcd681a 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: rsbetween.c,v 1.15.2.1 2004-10-27 09:35:02 heikki Exp $
+/* $Id: rsbetween.c,v 1.15.2.2 2004-12-16 19:11:41 heikki Exp $
    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
    Index Data Aps
 
@@ -28,6 +28,7 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  * specified, they must match the "left" rset (start tag). "Hamlet" between
  * "<title lang=eng>" and "</title>". (This assumes that the attributes are
  * indexed to the same seqno as the tags).
+
 */ 
 
 #include <stdio.h>
@@ -38,7 +39,10 @@ Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include <rsbetween.h>
 #include <zebrautl.h>
 
-#define RSBETWEEN_DEBUG 0
+#define RSBETWEEN_DEBUG 1
+#if RSBETWEEN_DEBUG
+#define log_level LOG_DEBUG
+#endif
 
 static void *r_create_between(RSET ct, const struct rset_control *sel, void *parms);
 static RSFD r_open_between (RSET ct, int flag);
@@ -48,7 +52,7 @@ static void r_rewind_between (RSFD rfd);
 static int r_forward_between(RSET ct, RSFD rfd, void *buf, int *term_index,
                      int (*cmpfunc)(const void *p1, const void *p2),
                      const void *untilbuf);
-static int r_read_between (RSFD rfd, void *buf, int *term_index);
+static int r_read (RSFD rfd, void *buf, int *term_index);
 static int r_write_between (RSFD rfd, const void *buf);
 
 static const struct rset_control control_between = 
@@ -59,15 +63,20 @@ static const struct rset_control control_between =
     r_close_between,
     r_delete_between,
     r_rewind_between,
-    r_forward_between, /* rset_default_forward, */
+    r_forward_between,  /* rset_default_forward,  */
     rset_default_pos,
-    r_read_between,
+    r_read,
     r_write_between,
 };
 
 
 const struct rset_control *rset_kind_between = &control_between;
 
+#define WHICH_L 0
+#define WHICH_M 1
+#define WHICH_R 2
+#define WHICH_A 3
+
 struct rset_between_info {
     int key_size;
     RSET rset_l;
@@ -99,6 +108,20 @@ struct rset_between_rfd {
     int level;
     struct rset_between_rfd *next;
     struct rset_between_info *info;
+    /* 1.4 backport */
+    void *recbuf; /* a key that tells which record we are in */
+    void *startbuf; /* the start tag */
+    int startbufok; /* we have seen the first start tag */
+    void *attrbuf;  /* the attr tag. If these two match, we have attr match */
+    int attrbufok; /* we have seen the first attr tag, can compare */
+    int depth; /* number of start-tags without end-tags */
+    int attrdepth; /* on what depth the attr matched */
+    int hits; /* number of hits returned so far */
+    /* Stuff for the multi-and read, also backported */
+    /* uses more_l/m/r/a etc from above */
+    int tailcount;
+    int tailbits[4]; 
+    int and_eof; 
 };    
 
 #if RSBETWEEN_DEBUG
@@ -210,6 +233,20 @@ static RSFD r_open_between (RSET ct, int flag)
                                     rfd->buf_attr, &dummy);
     }
     rfd->level=0;
+    rfd->recbuf=xmalloc (info->key_size); 
+    rfd->startbuf=xmalloc (info->key_size);
+    rfd->attrbuf=xmalloc (info->key_size); 
+    rfd->startbufok=0; 
+    rfd->attrbufok=0; 
+    rfd->depth=0;
+    rfd->attrdepth=0;
+    rfd->hits=-1; /* signals uninitialized */
+    rfd->tailcount=0;
+    rfd->tailbits[WHICH_L]=0; 
+    rfd->tailbits[WHICH_M]=0; 
+    rfd->tailbits[WHICH_R]=0; 
+    rfd->tailbits[WHICH_A]=0; 
+    rfd->and_eof=0; 
     return rfd;
 }
 
@@ -225,6 +262,9 @@ static void r_close_between (RSFD rfd)
             xfree ((*rfdp)->buf_m);
             xfree ((*rfdp)->buf_r);
             xfree ((*rfdp)->buf_attr);
+            xfree ((*rfdp)->recbuf);
+            xfree ((*rfdp)->startbuf);
+            xfree ((*rfdp)->attrbuf);
             rset_close (info->rset_l, (*rfdp)->rfd_l);
             rset_close (info->rset_m, (*rfdp)->rfd_m);
             rset_close (info->rset_r, (*rfdp)->rfd_r);
@@ -297,7 +337,8 @@ static int r_forward_between(RSET ct, RSFD rfd, void *buf, int *term_index,
 #if RSBETWEEN_DEBUG
     log2( p, "fwd: after forward M", 0,0);
 #endif
-    rc = r_read_between(rfd, buf, term_index);
+    /* rc = r_read_between(rfd, buf, term_index);*/
+    rc = r_read(rfd, buf, term_index);
 #if RSBETWEEN_DEBUG
     log2( p, "fwd: after forward", 0,0);
 #endif
@@ -306,221 +347,228 @@ static int r_forward_between(RSET ct, RSFD rfd, void *buf, int *term_index,
 
 
 
-
-static int r_read_between (RSFD rfd, void *buf, int *term_index)
+static int r_write_between (RSFD rfd, const void *buf)
 {
-    struct rset_between_rfd *p = (struct rset_between_rfd *) rfd;
-    struct rset_between_info *info = p->info;
-    int cmp_l=0;
-    int cmp_r=0;
-    int attr_match = 0;
+    logf (LOG_FATAL, "between set type is read-only");
+    return -1;
+}
 
-    while (p->more_m)
-    {
-#if RSBETWEEN_DEBUG
-        log2( p, "start of loop", cmp_l, cmp_r);
-#endif
 
-        /* forward L until past m, count levels, note rec boundaries */
-        if (p->more_l)
-            cmp_l= (*info->cmp)(p->buf_l, p->buf_m);
-        else
+
+/* Heikki's back-port of the cleaner 1.4 algorithm */
+
+static void checkattr(struct rset_between_rfd *p)
+{
+    p->attrdepth=-1; /* matches always */
+
+#ifdef SKIPTHIS /* not yet backported */
+    struct rset_between_info *info =p->info;
+    int cmp;
+    if (p->attrdepth)
+        return; /* already found one */
+    if (!info->attrterm) 
+    {
+        p->attrdepth=-1; /* matches always */
+        return;
+    }
+    if ( p->startbufok && p->attrbufok )
+    { /* have buffers to compare */
+        cmp=(kctrl->cmp)(p->startbuf,p->attrbuf);
+        if (0==cmp) /* and the keys match */
         {
-            p->level = 0;
-            cmp_l=2; /* past this record */
+            p->attrdepth=p->depth;
+            yaz_log(log_level, "found attribute match at depth %d",p->attrdepth);
         }
-#if RSBETWEEN_DEBUG
-        log2( p, "after first L", cmp_l, cmp_r);
+    }
 #endif
+}
 
-        while (cmp_l < 0)   /* l before m */
-        {
-            if (cmp_l == -2)
-                p->level=0; /* earlier record */
-            if (cmp_l == -1)
-            {
-                p->level++; /* relevant start tag */
 
-                if (!info->rset_attr)
-                    attr_match = 1;
-                else
-                {
-                    int cmp_attr;
-                    int dummy_term;
-                    attr_match = 0;
-                    while (p->more_attr)
-                    {
-                        cmp_attr = (*info->cmp)(p->buf_attr, p->buf_l);
-                        if (cmp_attr == 0)
-                        {
-                            attr_match = 1;
-                            break;
-                        }
-                        else if (cmp_attr > 0)
-                            break;
-                        else if (cmp_attr==-1) 
-                            p->more_attr = rset_read (info->rset_attr, p->rfd_attr,
-                                                  p->buf_attr, &dummy_term);
-                            /* if we had a forward that went all the way to
-                             * the seqno, we could use that. But fwd only goes
-                             * to the sysno */
-                        else if (cmp_attr==-2) 
-                        {
-                            p->more_attr = rset_forward(
-                                      info->rset_attr, p->rfd_attr,
-                                      p->buf_attr, &dummy_term,
-                                      info->cmp, p->buf_l);
-#if RSBETWEEN_DEBUG
-                            logf(LOG_DEBUG, "btw: after frowarding attr m=%d",p->more_attr);
-#endif
-                        }
-                    } /* while more_attr */
-                }
-            }
-#define NEWCODE 1 
-#if NEWCODE                
-            if (cmp_l==-2)
+/* Implements a multi-and between the l,r, and m rfds. Returns all */
+/* hits from those, provided that all three point to the same record */
+/* See rsmultiandor.c in zebra 1.4 for details */
+static int read_anded(struct rset_between_rfd *p,void *buf,
+                      int *term, int *which) {
+    RSFD rfds[4];
+    RSET rsets[4];
+    void *bufs[4];
+    int *terms[4];
+    int dummyterm;
+    struct rset_between_info *info =p->info;
+    int i, mintail;
+    int n;
+    int cmp;
+
+    /* make the individual args into arrays, to match rsmultiandor */
+    rfds[WHICH_L]=p->rfd_l;
+    rfds[WHICH_M]=p->rfd_m;
+    rfds[WHICH_R]=p->rfd_r;
+    rfds[WHICH_A]=p->rfd_attr;
+    rsets[WHICH_L]=info->rset_l;
+    rsets[WHICH_M]=info->rset_m;
+    rsets[WHICH_R]=info->rset_r;
+    rsets[WHICH_A]=info->rset_attr;
+    bufs[WHICH_L]=p->buf_l;
+    bufs[WHICH_M]=p->buf_m;
+    bufs[WHICH_R]=p->buf_r;
+    bufs[WHICH_A]=p->buf_attr;
+    terms[WHICH_L]=&(p->term_index_l);
+    terms[WHICH_M]=&(p->term_index_m);
+    terms[WHICH_R]=&(p->term_index_r);
+    terms[WHICH_A]=&dummyterm;
+    dummyterm=0;
+    if (info->rset_attr)
+        n=4;
+    else
+        n=3;
+    while (1) {
+        if (p->tailcount)
+        { /* we are tailing */
+            mintail=0;
+            while ((mintail<n) && !p->tailbits[mintail])
+                mintail++; /* first tail */
+            for (i=mintail+1;i<n;i++)
             {
-                if (p->more_l) 
+                if (p->tailbits[i])
                 {
-                    p->more_l=rset_forward(
-                                      info->rset_l, p->rfd_l,
-                                      p->buf_l, &p->term_index_l,
-                                      info->cmp, p->buf_m);
-                    if (p->more_l)
-                        cmp_l= (*info->cmp)(p->buf_l, p->buf_m);
-                    else
-                        cmp_l=2;
-#if RSBETWEEN_DEBUG
-                    log2( p, "after forwarding L", cmp_l, cmp_r);
-#endif
+                    cmp=(*info->cmp)(bufs[i],bufs[mintail]);
+                    if (cmp<0)
+                        mintail=i;
                 }
-            } else
+            }
+            /* return the lowest tail */
+            memcpy(buf, bufs[mintail], info->key_size);
+            *which=mintail;
+            *term=*terms[mintail];
+            /* and read that one further */
+            if (!rset_read(rsets[mintail],rfds[mintail], 
+                           bufs[mintail],terms[mintail]))
             {
-                p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l,
-                              &p->term_index_l);
+                p->and_eof=1; 
+                p->tailbits[mintail]=0;
+                (p->tailcount)--;
+                return 1;
             }
-#else
-            p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l,
-                              &p->term_index_l);
-#endif
-            if (p->more_l)
+            /* still a tail? */
+            cmp=(info->cmp)(bufs[mintail],buf);
+            if (cmp>=2) 
             {
-                cmp_l= (*info->cmp)(p->buf_l, p->buf_m);
+                p->tailbits[mintail]=0;
+                (p->tailcount)--;
             }
-            else
-                cmp_l=2; 
-#if RSBETWEEN_DEBUG
-            log2( p, "end of L loop", cmp_l, cmp_r);
-#endif
-        } /* forward L */
-
-            
-        /* forward R until past m, count levels */
-#if RSBETWEEN_DEBUG
-        log2( p, "Before moving R", cmp_l, cmp_r);
-#endif
-        if (p->more_r)
-            cmp_r= (*info->cmp)(p->buf_r, p->buf_m);
+            return 1;
+        }
         else
-            cmp_r=2; 
-#if RSBETWEEN_DEBUG
-        log2( p, "after first R", cmp_l, cmp_r);
-#endif
-        while (cmp_r < 0)   /* r before m */
-        {
-             /* -2, earlier record, don't count level */
-            if (cmp_r == -1)
-                p->level--; /* relevant end tag */
-            if (p->more_r)
+        { /* not tailing */
+            if (p->and_eof)
+                return 0; /* game over */
+            i=1; /* assume items[0] is highest up */
+            while (i<n) 
             {
-#if NEWCODE                
-                if (cmp_r==-2)
-                {
-                    p->more_r=rset_forward(
-                                      info->rset_r, p->rfd_r,
-                                      p->buf_r, &p->term_index_r,
-                                      info->cmp, p->buf_m);
-                } else
-                {
-                    p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r,
-                                       &p->term_index_r);
+                cmp=(*info->cmp)(bufs[0],bufs[i]);
+                if (cmp<=-2)
+                { /* [0] was behid, forward it and start anew */
+                    if (!rset_forward(rsets[0],rfds[0], bufs[0], 
+                                      terms[0], info->cmp, bufs[i])) 
+                    {
+                        p->and_eof=1;
+                        return 0;
+                    }
+                    i=0; /* all over again */
                 }
-                if (p->more_r)
-                    cmp_r= (*info->cmp)(p->buf_r, p->buf_m);
+                else if (cmp>=2)
+                {/* [0] was ahead, forward i */
+                    if (!rset_forward(rsets[i],rfds[i], bufs[i], 
+                                      terms[i], info->cmp, bufs[0])) 
+                    {
+                        p->and_eof=1;
+                        return 0;
+                    }
 
-#else
-                p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r,
-                                       &p->term_index_r);
-                cmp_r= (*info->cmp)(p->buf_r, p->buf_m);
-#endif
-            }
-            else
-                cmp_r=2; 
-#if RSBETWEEN_DEBUG
-        log2( p, "End of R loop", cmp_l, cmp_r);
-#endif
-        } /* forward R */
-        
-        if ( ( p->level <= 0 ) && ! p->more_l)
-            return 0; /* no more start tags, nothing more to find */
-        
-        if ( attr_match && p->level > 0)  /* within a tag pair (or deeper) */
-        {
-            memcpy (buf, p->buf_m, info->key_size);
-            *term_index = p->term_index_m + info->rset_m->no_rset_terms;
-#if RSBETWEEN_DEBUG
-            log2( p, "Returning a hit (and forwarding m)", cmp_l, cmp_r);
-#endif
-            p->more_m = rset_read (info->rset_m, p->rfd_m, p->buf_m,
-                                   &p->term_index_m);
-            if (cmp_l == 2)
-                p->level = 0;
-            return 1;
+                } else
+                    i++; 
+            } /* while i */
+            /* now all are within the same records, set tails and let upper 
+             * if return hits */
+            for (i=0; i<n;i++)
+                p->tailbits[i]=1;
+            p->tailcount=n;
+        }
+    } 
+} /* read_anded */
+
+static int r_read (RSFD rfd, void *buf, int *term)
+{
+    struct rset_between_rfd *p=(struct rset_between_rfd *)rfd;
+    struct rset_between_info *info =p->info;
+    int cmp;
+    int thisterm=0;
+    int which; 
+    *term=0; /* just in case, should not be necessary */
+    yaz_log(log_level,"btw: == read: term=%p",term);
+    while ( read_anded(p,buf,&thisterm,&which) )
+    {
+        yaz_log(log_level,"btw: read loop term=%p d=%d ad=%d",
+                term, p->depth, p->attrdepth);
+        if (p->hits<0) 
+        {/* first time? */
+            memcpy(p->recbuf,buf,info->key_size);
+            p->hits=0;
+            cmp=2;
+        }
+        else {
+            cmp=(*info->cmp)(buf,p->recbuf);
+            yaz_log(log_level, "btw: cmp=%d",cmp);
         }
-        else if ( ! p->more_l )  /* not in data, no more starts */
+
+        if (cmp>=2)
+        { 
+            yaz_log(log_level,"btw: new record");
+            p->depth=0;
+            p->attrdepth=0;
+            memcpy(p->recbuf,buf,info->key_size);
+        }
+
+        yaz_log(log_level,"btw:  which: %d", which); 
+        if (which==WHICH_L)
         {
-#if RSBETWEEN_DEBUG
-            log2( p, "no more starts, exiting without a hit", cmp_l, cmp_r);
-#endif
-            return 0;  /* ergo, nothing can be found. stop scanning */
+            p->depth++;
+            yaz_log(log_level,"btw: read start tag. d=%d",p->depth);
+            memcpy(p->startbuf,buf,info->key_size);
+            p->startbufok=1;
+            checkattr(rfd);  /* in case we already saw the attr here */
         }
-#if NEWCODE                
-        if (cmp_l == 2)
+        else if (which==WHICH_R)  
         {
-            p->level = 0;
-            p->more_m=rset_forward(
-                              info->rset_m, p->rfd_m,
-                              p->buf_m, &p->term_index_m,
-                              info->cmp, p->buf_l);
-        } else
+            if (p->depth == p->attrdepth)
+                p->attrdepth=0; /* ending the tag with attr match */
+            p->depth--;
+            yaz_log(log_level,"btw: read end tag. d=%d ad=%d",p->depth, p->attrdepth);
+        }
+        else if (which==WHICH_A)
         {
-            p->more_m = rset_read (info->rset_m, p->rfd_m, p->buf_m,
-                               &p->term_index_m);
+            yaz_log(log_level,"btw: read attr");
+            memcpy(p->attrbuf,buf,info->key_size);
+            p->attrbufok=1;
+            checkattr(rfd); /* in case the start tag came first */
         }
-#else
-        if (cmp_l == 2)
-            p->level = 0;
-        p->more_m = rset_read (info->rset_m, p->rfd_m, p->buf_m,
-                               &p->term_index_m);
-#endif
-#if RSBETWEEN_DEBUG
-        log2( p, "End of M loop", cmp_l, cmp_r);
-#endif
-    } /* while more_m */
-    
-#if RSBETWEEN_DEBUG
-    log2( p, "Exiting, nothing more in m", cmp_l, cmp_r);
-#endif
-    return 0;  /* no more data possible */
+        else 
+        { /* mut be a real hit */
+            if (p->depth && p->attrdepth)
+            {
+                p->hits++;
+                yaz_log(log_level,"btw: got a hit h=%d d=%d ad=%d t=%d+%d", 
+                        p->hits,p->depth,p->attrdepth,
+                        info->rset_m->no_rset_terms,thisterm);
+                *term= info->rset_m->no_rset_terms + thisterm;
+                return 1; /* everything else is in place already */
+            } else
+                yaz_log(log_level, "btw: Ignoring hit. h=%d d=%d ad=%d",
+                        p->hits,p->depth,p->attrdepth);
+        }
+    } /* while read */
 
+    return 0;
 
 }  /* r_read */
 
-
-static int r_write_between (RSFD rfd, const void *buf)
-{
-    logf (LOG_FATAL, "between set type is read-only");
-    return -1;
-}
-
index caac315..a5caad0 100644 (file)
@@ -1,9 +1,10 @@
-# $Id: Makefile.am,v 1.7 2004-05-25 08:49:11 adam Exp $
+# $Id: Makefile.am,v 1.7.2.1 2004-12-16 19:11:41 heikki Exp $
 
-check_SCRIPTS = simple1.sh test1.sh test2.sh test3.sh test4.sh test5.sh
+check_SCRIPTS = simple1.sh test1.sh test2.sh test3.sh test4.sh test5.sh test6.sh
 
 TESTS = $(check_SCRIPTS)
 
 EXTRA_DIST = zebra.cfg rec.xml Zthes.abs zthes-b.est \
- simple1.xml rec4.xml rec5.xml $(check_SCRIPTS)
+ simple1.xml rec4.xml rec5.xml \
+ rec61.xml rec62.xml zebra6.cfg assembled.abs $(check_SCRIPTS)
 
diff --git a/test/xpath/assembled.abs b/test/xpath/assembled.abs
new file mode 100644 (file)
index 0000000..72e6c26
--- /dev/null
@@ -0,0 +1,5 @@
+attset bib1.att
+
+xpath enable
+
+xelm /assembled/basic/names/CASno !:w,!:p,!:s,NAL-call-number:p,Title-key:s
diff --git a/test/xpath/rec61.xml b/test/xpath/rec61.xml
new file mode 100644 (file)
index 0000000..90afca5
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assembled org="46">
+  <cwd>KBA/localreg/367-93-1</cwd>
+  <orgs>
+    <org>1</org>
+    <org>46</org>
+  </orgs>
+  <basic>
+    <names org="46">
+      <title>Isopropopyl-beta-D-thiogalactoside</title>
+      <CASno>367-93-1</CASno>
+    </names>
+    <register creator="46" created="2003-10-14, 14:12:48" status="1">
+  
+  
+</register>
+  </basic>
+</assembled>
diff --git a/test/xpath/rec62.xml b/test/xpath/rec62.xml
new file mode 100644 (file)
index 0000000..20a9593
--- /dev/null
@@ -0,0 +1,755 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<assembled org="0">
+  <cwd>KBA/oldkba/CAS/367-93-1</cwd>
+  <orgs>
+    <org>0</org>
+    <org>1</org>
+    <org>147</org>
+    <org>41</org>
+    <org>46</org>
+    <org>86</org>
+  </orgs>
+  <basic>
+    <names org="0">
+      <title>ISOPROPYL-β-D-THIOGALACTOPYRANOSID- DIOXAN FRI</title>
+      <CASno>367-93-1</CASno>
+      <synonyms>
+    <synonym>IPTG</synonym>
+  </synonyms>
+    </names>
+    <searchmodified>20010918</searchmodified>
+    <register creator="autoconv" lastmodifier="autoconv" modifier="autoconv" release_dan="2003-09-19" release_eng="" public="0" status="0" lastmodified="2001-09-18">
+  <robotinfo indextype="1" selfcontained="1" class="kba"/>
+  <searchprelastmodified>20010918</searchprelastmodified>
+  
+  <kbandoc>
+    <daop navn="Dato oprettet">20010918</daop>
+    <dare navn="Dato rettet">20000407</dare>
+    <dafr navn="Det originale filnavn">367931</dafr>
+    <casn navn="CAS nummer">367-93-1</casn>
+    <titl navn="Titel">ISOPROPYL-β-D-THIOGALACTOPYRANOSID- DIOXAN
+      FRI</titl>
+    <tial navn="Titel">IPTG</tial>
+    <orga navn="Originaltekst A">
+        <p>pr.nr.:</p>
+        <p>bruttoformel: C
+        <sub>9</sub>
+        H
+        <sub>18</sub>
+        O
+        <sub>5</sub>
+        S</p>
+        <p>molvægt: 238,3</p>
+        <p>kogepunkt:</p>
+        <p>smeltepunkt: ca 110°C</p>
+        <p>massefylde:</p>
+      </orga>
+    <orgb navn="Originaltekst B">
+        <p align="center"> </p>
+      </orgb>
+    <orgc navn="Originaltekst C">
+        <p>
+          <font face="Arial,Univers">Der foreligger ikke information, der
+          gør det muligt at klassificere dette stof.</font>
+        </p>
+      </orgc>
+    <orgd navn="Originaltekst D">
+      <center>
+        <font size="5" face="Arial,Univers ">Data til brug ved substitution
+        m.m.</font>
+      </center>
+      <br/>
+      <table border="1" cellspacing="3" width="100%">
+        <tr>
+          <td align="center" valign="top">
+            <p align="center">
+              <font size="3" face="Arial,Univers ">
+                <font face="Arial,Univers"> GRÆNSE-</font>
+              </font>
+            </p>
+            <p align="center">VÆRDI </p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">FLAMME-</font>
+            </p>
+            <p align="center">PUNKT</p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">EKSPLO-</font>
+            </p>
+            <p align="center">SIONS-</p>
+            <p align="center">GRÆNSE</p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">DAMPTRYK</font>
+            </p>
+            <p align="center">
+              <font face="Arial,Univers">mmHg</font>
+            </p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">FORDAMP-</font>
+            </p>
+            <p align="center">NINGS-</p>
+            <p align="center">HASTIGHED</p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">VHI</font>
+            </p>
+            <p align="center">
+              <font face="Arial,Univers">(VHR)</font>
+            </p>
+          </td>
+          <td valign="top">
+            <p align="center">
+              <font face="Arial,Univers">LOG.</font>
+            </p>
+            <p align="center">
+              <font face="Arial,Univers">OCTANOL:</font>
+            </p>
+            <p align="center">
+              <font face="Arial,Univers">VAND</font>
+            </p>
+          </td>
+        </tr>
+        <tr>
+          <td align="center" width="32%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers">-</font>
+            </p>
+          </td>
+          <td width="12%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers"> </font>
+            </p>
+          </td>
+          <td width="12%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers"> </font>
+            </p>
+          </td>
+          <td width="12%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers"> </font>
+            </p>
+          </td>
+          <td width="12%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers"> </font>
+            </p>
+          </td>
+          <td width="12%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers"> </font>
+            </p>
+          </td>
+          <td width="13%" valign="top">
+            <p align="center">
+              <font face="Arial,Univers">-1,25</font>
+            </p>
+          </td>
+        </tr>
+      </table>
+      <br/>
+      </orgd>
+    <orge navn="Originaltekst E">
+        <table border="1" cellspacing="3" bordercolor="#000000" width="100%">
+          <tr>
+            <td width="50%" valign="top">
+              <font face="Arial,Univers" size="4">Særlig
+              advarsel</font>
+            </td>
+            <td>
+              <p>
+                <font face="Arial,Univers" size="4">Supplerende
+                information </font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="50%" valign="top">
+              <p>
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="50%" valign="top">
+              <p>
+                <font face="Arial,Univers">Ved indhold af 1,4-dioxan CAS nr
+                123-91-1 se brugsanvisning for dette stof.</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td valign="top" colspan="8">
+            </td>
+          </tr>
+        </table>
+        <br/>
+        <table border="1" cellspacing="3" bordercolor="#000000" cellpadding="6" width="100%">
+          <tr>
+            <td valign="top" colspan="8">
+              <p>
+                <font face="Arial,Univers" size="4">SUNDHEDSFARLIGE
+                EGENSKABER: SAMMENFATNING AF AFSNIT B.</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">LANGTIDSVIRKNINGER VED
+                UDSÆTTELSE</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">
+                  <font size="3">Nej</font>
+                </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">Mistænkt</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">Ja</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">Modstridende</font>
+              </p>
+              <p align="center">
+                <font face="Arial,Univers">oplysninger</font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">Ingen</font>
+              </p>
+              <p align="center">
+                <font face="Arial,Univers">dokumentation</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">
+                  <font face="Arial,Univers">Kræftfremkaldende</font>
+                </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">
+                  <font face="Arial,Univers"> </font>
+                </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">
+                  <font face="Arial,Univers">Skade på
+                  kønsorganer, æg, sæd, foster</font>
+                </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers">
+                  <font face="Arial,Univers"> </font>
+                </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Skade på arveanlæg
+                (mutagent)</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Hudsygdomme bl.a. allergi</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Allergisk astma</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Skade på
+                nervesystemet</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Organskade: lunger, lever,
+                nyrer</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+          <tr>
+            <td width="37%" valign="top" colspan="3">
+              <p>
+                <font face="Arial,Univers">Øvrige skader:</font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="12%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> </font>
+              </p>
+            </td>
+            <td width="13%" valign="top">
+              <p align="center">
+                <font face="Arial,Univers"> X</font>
+              </p>
+            </td>
+          </tr>
+        </table>
+      </orge>
+    <orgf navn="Originaltekst F">
+        <afsnit>
+<h2 class="sectionheading">A: Anvendelsesområde/begrænsning</h2>
+          <font size="3">
+            <br/>
+          </font>
+          <p>
+            <font size="3">
+              <b>Information om lokal praksis - skal udfyldes af
+              instituttet/afdelingen:</b>
+            </font>
+          </p>
+        </afsnit>
+      </orgf>
+    <orgg navn="Originaltekst G">
+<h2 class="sectionheading">B: Sundhedsfarlige egenskaber</h2>
+      <font size="3">
+        <br/>
+      </font>
+      <p>
+        <font size="3">Der foreligger stærkt begrænset viden om
+        dette stofs virkninger.</font>
+      </p>
+      <br/>
+      <p>Stoffet kan optages gennem hud, lunger og mavetarmkanal.</p>
+      <p>
+        <b>Indånding</b>
+      </p>
+      <p>
+      <i>Akut forgiftning:</i>
+        Evt. irritation af slimhinderne i de øvre luftveje (SAF).</p>
+      <p>
+      <b>
+        <i>Langtidsvirkninger:</i>
+      </b>
+       Der foreligger ingen information.</p>
+      <p>
+        <b>Hud</b>
+      </p>
+      <p>Evt.irritation.</p>
+      <p>
+      <b>
+        <i>Langtidsvirkninger:</i>
+      </b>
+       Der foreligger ingen information.</p>
+      <p>
+        <b>Øjne</b>
+      </p>
+      <p>Evt. irritation.</p>
+      <p>
+        <b>Indtagelse</b>
+      </p>
+      </orgg>
+    <orgh navn="Originaltekst H">
+        <afsnit>
+<h2 class="sectionheading">C: Forholdsregler ved brug</h2>
+        <font size="3">
+          <br/>
+        </font>
+        <p>
+          <font size="3">Sørg for effektiv procesventilation f.eks
+          stinkskab. Brug engangshandsker ved uundgåelig kontakt med
+          stoffet. Vær opmærksom på gennembrudstid, søg
+          oplysning hos handskeleverandør.</font>
+        </p>
+        <br/>
+        <p>Der skal være let adgang til nødbruser,
+        øjenskylleflaske og håndvask med sæbe.</p>
+        <br/>
+        <p>Der mangler viden om stoffets langtidsvirkninger,
+        tilrettelæg derfor arbejdet så kontakt med stoffet
+        undgås.</p>
+        <br/>
+        <p>Benyttede glasvarer, apparatur og lign. skylles omhyggeligt,
+        inden det stilles til opvask.</p>
+        <br/>
+        <p>
+          <b>Information om lokal praksis - skal udfyldes af
+          instituttet/afdelingen:</b>
+        </p>
+        </afsnit>
+      </orgh>
+    <orgi navn="Originaltekst I">
+        <afsnit>
+<h2 class="sectionheading">D: Beskrivelse af stoffet/produktet</h2>
+          <font size="3">
+            <br/>
+          </font>
+          <p>
+            <font size="3">Fast stof. Der foreligger ikke information om
+            opløselighed.</font>
+          </p>
+          <p>Kan indeholde op til 5% vand (Aldrich).</p>
+          <p>
+          <b>
+            <i>Uforligelighed:</i>
+          </b>
+           Der foreligger ingen information.</p>
+          <p>
+          <b>
+            <i>Miljøforhold:</i>
+          </b>
+           Der er ikke fundet nogen data om stoffets nedbrydning og det
+          må derfor anses for ikke at være let nedbrydeligt.</p>
+          <p>Anses ikke for bioakkumulerende.</p>
+          <br/>
+          <p>
+            <b>Instituttets/afdelingens supplerende oplysninger:</b>
+          </p>
+        </afsnit>
+      </orgi>
+    <orgj navn="Originaltekst J">
+<h2 class="sectionheading">E: Opvarmning og brand</h2>
+        <font size="3">
+          <br/>
+        </font>
+        <p>
+          <font size="3">
+          <b>Brand:</b>
+           Der kan dannes giftige gasser af bl.a. kulmonoxid og
+          svovloxider.</font>
+        </p>
+        <p>
+        <b>Slukning:</b>
+         Vandtåge, kuldioxid, pulverslukker (SA).</p>
+        <p>Vær dog opmærksom på, at pulver kan skade
+        apparatur.</p>
+        <br/>
+      </orgj>
+    <orgk navn="Originaltekst K">
+        <afsnit>
+<h2 class="sectionheading">F: Forholdsregler ved spild og bortskaffelse</h2>
+        <font size="3">
+          <br/>
+        </font>
+        <p>
+          <font size="3">Begræns støvudvikling. Hold uvedkommende
+          på afstand og informer ved øget risiko for
+          påvirkning.</font>
+        </p>
+        <p>Undgå kontakt med stoffet. Anvend evt handsker og
+        åndedrætsværn med kombinationsfilter (Type
+        ABEK-P).</p>
+        <p>Tør op evt. med fugtig klud. Klud og spild bortskaffes som
+        kemikalieaffald i veltillukket beholder. Rengør området
+        efter opsamling af spild.</p>
+        <p>Informér de Kommunale myndigheder og institutionens
+        miljøansvarlige ved større udslip til omgivelserne.</p>
+        <br/>
+        <div class="affaldsgruppeline">Affaldsgruppe: B Klasse,
+        klassifikationskode: - UN nr: -</div>
+        <br/>
+        </afsnit>
+      </orgk>
+    <orgl navn="Originaltekst L">
+<h2 class="sectionheading">G: Første hjælp</h2>
+        <font size="3">
+          <br/>
+        </font>
+        <p>
+          <font size="3">
+          <b>Indånding:</b>
+           Personen bringes i frisk luft, holdes i ro og under opsyn. Ved
+          risiko for bevidstløshed lejres personen i aflåst
+          sideleje og holdes varm. Ved manglende vejrtrækning gives
+          kunstigt åndedræt.</font>
+        </p>
+        <p>
+        <b>Hud:</b>
+         Skyl længe og grundigt med vand, fjern forurenet tøj og
+        evt. smykker.</p>
+        <p>
+        <b>Øjne:</b>
+         Skyl straks med vand. Spil øjet grundigt op. Fjern
+        kontaktlinser. Fortsæt skylningen indtil læge overtager
+        behandlingen.</p>
+        <p>
+        <b>Indtagelse:</b>
+         Skyl straks munden og drik vand eller mælk. Giv ikke
+        væske til bevidstløse. Fremkald ikke opkastning.</p>
+        <p>Ved vedvarende gener søg skadestue og medbring denne
+        brugsanvisning.</p>
+        <br/>
+      </orgl>
+    <orgm navn="Originaltekst M">
+        <afsnit>
+<h2 class="sectionheading">H: Sikkerhedsforskrifter ved oplagring</h2>
+        <font size="3">
+          <br/>
+        </font>
+        <p>
+          <font size="3">Stoffet skal opbevares tæt tillukket på
+          et køligt, tørt sted.</font>
+        </p>
+        <p>
+          <b>Information om lokal praksis - skal udfyldes af
+          instituttet/afdelingen:</b>
+        </p>
+        <br/>
+        </afsnit>
+      </orgm>
+    <rdcsynonyms>
+        <rdcsynonym>IPTG</rdcsynonym>
+      </rdcsynonyms>
+  </kbandoc>
+</register>
+  </basic>
+  <notes>
+    <note org="46">
+      <producer>Pharmacia</producer>
+    </note>
+  </notes>
+  <holdings>
+    <holding org="41">
+      <kvantum>0,001 kg</kvantum>
+      <building>24.5.33</building>
+      <room>Køleskab</room>
+      <place>Xn</place>
+    </holding>
+    <holding org="46">
+      <kvantum>10 g</kvantum>
+      <building>24.2.35</building>
+      <room>Kølerum</room>
+      <place>Ej oplyst</place>
+    </holding>
+    <holding org="86">
+      <kvantum>10g</kvantum>
+      <building>teilum, 6. sal</building>
+    </holding>
+    <holding org="147">
+      <kvantum>2g</kvantum>
+      <building>4.2.15</building>
+      <room>Freezer</room>
+      <place>T</place>
+    </holding>
+    <holding org="147">
+      <kvantum>5g</kvantum>
+      <building>4.2.11</building>
+      <room>-20C freezer 1</room>
+      <place>T R45</place>
+    </holding>
+  </holdings>
+</assembled>
diff --git a/test/xpath/test6.sh b/test/xpath/test6.sh
new file mode 100755 (executable)
index 0000000..49acee3
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/sh
+# $Id: test6.sh,v 1.1.2.1 2004-12-16 19:11:41 heikki Exp $
+
+pp=${srcdir:-"."}
+
+LOG="test6.log"
+TMP="test6.tmp"
+#DBG="-v 1647"
+DBG=""
+
+rm -f $LOG
+rm -f $TMP.*
+../../index/zebraidx -c $pp/zebra6.cfg -l $LOG init || exit 1
+../../index/zebraidx -c $pp/zebra6.cfg -l $LOG -t grs.xml update $pp/rec61.xml $pp/rec62.xml || exit 2
+test -f dict*.mf || exit 1
+
+../../index/zebrasrv -c $pp/zebra6.cfg -l $LOG $DBG -S unix:socket & 
+sleep 1
+test -f zebrasrv.pid || exit 2
+
+../api/testclient unix:socket \
+            '@attr 5=1 @attr 6=3  @attr 4=1 @attr 1=/assembled/basic/names/CASno "367-93-1"' >$TMP.1
+
+../api/testclient unix:socket \
+            '@attr 5=1 @attr 6=3  @attr 4=1 @attr 1=18 "367-93-1"' >$TMP.2
+
+../api/testclient unix:socket '@attr 1=/assembled/orgs/org 0' >$TMP.3
+
+../api/testclient unix:socket '@and @attr 1=/assembled/orgs/org 0 @attr 5=1 @attr 6=3 @attr 4=1 @attr 1=/assembled/basic/names/CASno "367-93-1"' >$TMP.4
+
+../api/testclient unix:socket '@and @attr 1=/assembled/orgs/org 46 @attr 5=1 @attr 6=3  @attr 4=1 @attr 1=/assembled/basic/names/CASno 367-93-1' >$TMP.5
+
+echo 'Killing server' >>$LOG
+kill `cat zebrasrv.pid` || exit 3
+sleep 1
+echo "Result counts: " >> $LOG
+cat $TMP.* >>$LOG
+echo 'Checking that result 1 count is 2' >>$LOG
+grep "^Result count: 2$" $TMP.1 >/dev/null || exit 4
+echo 'Checking that result 2 count is 2' >>$LOG
+grep "^Result count: 2$" $TMP.2 >/dev/null || exit 5
+echo 'Checking that result 3 count is 1' >>$LOG
+grep "^Result count: 1$" $TMP.3 >/dev/null || exit 6
+echo 'Checking that result 4 count is 1' >>$LOG
+grep "^Result count: 1$" $TMP.4 >/dev/null || exit 7
+echo 'Checking that result 5 count is 2' >>$LOG
+grep "^Result count: 2$" $TMP.5 >/dev/null || exit 8
+echo 'Test OK' >>$LOG
+exit 0
+
diff --git a/test/xpath/zebra6.cfg b/test/xpath/zebra6.cfg
new file mode 100644 (file)
index 0000000..6d23f89
--- /dev/null
@@ -0,0 +1,10 @@
+# $Id: zebra6.cfg,v 1.1.2.1 2004-12-16 19:11:41 heikki Exp $
+profilePath: ${srcdir:-.}:${srcdir:-.}/../../tab
+recordType: grs.sgml
+attset: bib1.att
+
+isam:b
+
+
+
+