1 /* $Id: recgrs.c,v 1.13 2007-01-15 15:10:17 adam Exp $
2 Copyright (C) 1995-2007
5 This file is part of the Zebra server.
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <sys/types.h>
32 #include <idzebra/recgrs.h>
34 #define GRS_MAX_WORD 512
36 struct source_parser {
44 static int sp_lex(struct source_parser *sp)
46 while (*sp->src == ' ')
50 while (*sp->src && !strchr("<>();,-: ", *sp->src))
59 sp->lookahead = *sp->src;
66 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd);
68 static int sp_range(struct source_parser *sp, data1_node *n, RecWord *wrd)
75 if (sp->lookahead != '(')
77 sp_lex(sp); /* skip ( */
80 if (!sp_expr(sp, n, wrd))
83 if (sp->lookahead != ',')
85 sp_lex(sp); /* skip , */
88 if (!sp_expr(sp, n, &tmp_w))
90 start = atoi_n(tmp_w.term_buf, tmp_w.term_len);
92 if (sp->lookahead == ',')
94 sp_lex(sp); /* skip , */
97 if (!sp_expr(sp, n, &tmp_w))
99 len = atoi_n(tmp_w.term_buf, tmp_w.term_len);
105 if (sp->lookahead != ')')
109 if (wrd->term_buf && wrd->term_len)
111 wrd->term_buf += start;
112 wrd->term_len -= start;
113 if (wrd->term_len > len)
119 static int sp_first(struct source_parser *sp, data1_node *n, RecWord *wrd)
124 if (sp->lookahead != '(')
126 sp_lex(sp); /* skip ( */
127 if (!sp_expr(sp, n, wrd))
129 while (sp->lookahead == ',')
133 sp_lex(sp); /* skip , */
135 if (!sp_expr(sp, n, &search_w))
137 for (i = 0; i<wrd->term_len; i++)
140 for (j = 0; j<search_w.term_len && i+j < wrd->term_len; j++)
141 if (wrd->term_buf[i+j] != search_w.term_buf[j])
143 if (j == search_w.term_len) /* match ? */
145 if (min_pos == -1 || i < min_pos)
151 if (sp->lookahead != ')')
155 min_pos = 0; /* the default if not found */
156 sprintf(num_str, "%d", min_pos);
157 wrd->term_buf = nmem_strdup(sp->nmem, num_str);
158 wrd->term_len = strlen(wrd->term_buf);
162 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd)
164 if (sp->lookahead != 't')
166 if (sp->len == 4 && !memcmp(sp->tok, "data", sp->len))
168 if (n->which == DATA1N_data)
170 wrd->term_buf = n->u.data.data;
171 wrd->term_len = n->u.data.len;
175 else if (sp->len == 3 && !memcmp(sp->tok, "tag", sp->len))
177 if (n->which == DATA1N_tag)
179 wrd->term_buf = n->u.tag.tag;
180 wrd->term_len = strlen(n->u.tag.tag);
184 else if (sp->len == 4 && !memcmp(sp->tok, "attr", sp->len))
188 if (sp->lookahead != '(')
192 if (!sp_expr(sp, n, &tmp_w))
197 if (n->which == DATA1N_tag)
199 data1_xattr *p = n->u.tag.attributes;
200 while (p && strlen(p->name) != tmp_w.term_len &&
201 memcmp (p->name, tmp_w.term_buf, tmp_w.term_len))
205 wrd->term_buf = p->value;
206 wrd->term_len = strlen(p->value);
209 if (sp->lookahead != ')')
213 else if (sp->len == 5 && !memcmp(sp->tok, "first", sp->len))
215 return sp_first(sp, n, wrd);
217 else if (sp->len == 5 && !memcmp(sp->tok, "range", sp->len))
219 return sp_range(sp, n, wrd);
221 else if (sp->len > 0 && isdigit(*(unsigned char *)sp->tok))
224 wrd->term_len = sp->len;
225 b = nmem_malloc(sp->nmem, sp->len);
226 memcpy(b, sp->tok, sp->len);
230 else if (sp->len > 2 && sp->tok[0] == '\'' && sp->tok[sp->len-1] == '\'')
233 wrd->term_len = sp->len - 2;
234 b = nmem_malloc(sp->nmem, wrd->term_len);
235 memcpy(b, sp->tok+1, wrd->term_len);
248 static struct source_parser *source_parser_create(void)
250 struct source_parser *sp = xmalloc(sizeof(*sp));
252 sp->nmem = nmem_create();
256 static void source_parser_destroy(struct source_parser *sp)
260 nmem_destroy(sp->nmem);
264 static int sp_parse(struct source_parser *sp,
265 data1_node *n, RecWord *wrd, const char *src)
271 nmem_reset(sp->nmem);
274 return sp_expr(sp, n, wrd);
277 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
286 if (p->which == XPATH_PREDICATE_RELATION) {
287 if (p->u.relation.name[0]) {
288 if (*p->u.relation.name != '@') {
290 " Only attributes (@) are supported in xelm xpath predicates");
291 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
294 attname = p->u.relation.name + 1;
296 /* looking for the attribute with a specified name */
297 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
298 if (!strcmp(attr->name, attname)) {
299 if (p->u.relation.op[0]) {
300 if (*p->u.relation.op != '=') {
302 "Only '=' relation is supported (%s)",p->u.relation.op);
303 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
306 if (!strcmp(attr->value, p->u.relation.value)) {
311 /* attribute exists, no value specified */
321 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
322 if (!strcmp(p->u.boolean.op,"and")) {
323 return d1_check_xpath_predicate(n, p->u.boolean.left)
324 && d1_check_xpath_predicate(n, p->u.boolean.right);
326 else if (!strcmp(p->u.boolean.op,"or")) {
327 return (d1_check_xpath_predicate(n, p->u.boolean.left)
328 || d1_check_xpath_predicate(n, p->u.boolean.right));
330 yaz_log(YLOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
339 static int dfa_match_first(struct DFA_state **dfaar, const char *text)
341 struct DFA_state *s = dfaar[0]; /* start state */
344 const char *p = text;
347 for (c = *p++, t = s->trans, i = s->tran_no; --i >= 0; t++)
349 if (c >= t->ch[0] && c <= t->ch[1])
353 /* move to next state and return if we get a match */
361 for (t = s->trans, i = s->tran_no; --i >= 0; t++)
362 if (c >= t->ch[0] && c <= t->ch[1])
372 New function, looking for xpath "element" definitions in abs, by
373 tagpath, using a kind of ugly regxp search.The DFA was built while
374 parsing abs, so here we just go trough them and try to match
375 against the given tagpath. The first matching entry is returned.
379 Added support for enhanced xelm. Now [] predicates are considered
380 as well, when selecting indexing rules... (why the hell it's called
387 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
389 data1_absyn *abs = n->root->u.root.absyn;
391 data1_xpelement *xpe = 0;
394 struct xpath_location_step *xp;
396 char *pexpr = xmalloc(strlen(tagpath)+5);
398 sprintf (pexpr, "/%s\n", tagpath);
400 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
401 xpe->match_state = -1; /* don't know if it matches yet */
403 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
406 int ok = xpe->match_state;
408 { /* don't know whether there is a match yet */
409 data1_xpelement *xpe1;
412 ok = dfa_match_first(xpe->dfa->states, pexpr);
415 /* mark this and following ones with same regexp */
416 for (xpe1 = xpe; xpe1; xpe1 = xpe1->match_next)
417 xpe1->match_state = ok;
420 assert (ok == 0 || ok == 1);
423 /* we have to check the perdicates up to the root node */
426 /* find the first tag up in the node structure */
427 for (nn = n; nn && nn->which != DATA1N_tag; nn = nn->parent)
430 /* go from inside out in the node structure, while going
431 backwards trough xpath location steps ... */
432 for (i = xpe->xpath_len - 1; i>0; i--)
434 if (!d1_check_xpath_predicate(nn, xp[i].predicate))
440 if (nn->which == DATA1N_tag)
452 yaz_log(YLOG_DEBUG, "Got it");
453 return xpe->termlists;
460 1 start element (tag)
462 3 start attr (and attr-exact)
470 Now, if there is a matching xelm described in abs, for the
471 indexed element or the attribute, then the data is handled according
472 to those definitions...
474 modified by pop, 2002-12-13
477 /* add xpath index for an attribute */
478 static void index_xpath_attr (char *tag_path, char *name, char *value,
479 char *structure, struct recExtractCtrl *p,
482 wrd->index_name = ZEBRA_XPATH_ELM_BEGIN;
483 wrd->index_type = '0';
484 wrd->term_buf = tag_path;
485 wrd->term_len = strlen(tag_path);
489 wrd->index_name = ZEBRA_XPATH_ATTR_CDATA;
490 wrd->index_type = 'w';
491 wrd->term_buf = value;
492 wrd->term_len = strlen(value);
495 wrd->index_name = ZEBRA_XPATH_ELM_END;
496 wrd->index_type = '0';
497 wrd->term_buf = tag_path;
498 wrd->term_len = strlen(tag_path);
503 static void mk_tag_path_full(char *tag_path_full, size_t max, data1_node *n)
508 /* we have to fetch the whole path to the data tag */
509 for (nn = n; nn; nn = nn->parent)
511 if (nn->which == DATA1N_tag)
513 size_t tlen = strlen(nn->u.tag.tag);
514 if (tlen + flen > (max - 2))
516 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
518 tag_path_full[flen++] = '/';
521 if (nn->which == DATA1N_root)
524 tag_path_full[flen] = 0;
528 static void index_staticrank(struct recExtractCtrl *p,
532 const char *staticrank_index = data1_absyn_get_staticrank(absyn);
534 if (staticrank_index && !strcmp(wrd->index_name, staticrank_index))
537 size_t len = wrd->term_len;
539 if (len > sizeof(valz)-1)
540 len = sizeof(valz)-1;
541 memcpy(valz, wrd->term_buf, len);
543 p->staticrank = atozint(valz);
547 static void index_xpath(struct source_parser *sp, data1_node *n,
548 struct recExtractCtrl *p,
549 int level, RecWord *wrd,
555 char tag_path_full[1024];
556 int termlist_only = 1;
560 if (!n->root->u.root.absyn
562 n->root->u.root.absyn->xpath_indexing == DATA1_XPATH_INDEXING_ENABLE)
571 wrd->term_buf = n->u.data.data;
572 wrd->term_len = n->u.data.len;
575 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
577 /* If we have a matching termlist... */
578 if (n->root->u.root.absyn &&
579 (tl = xpath_termlist_by_tagpath(tag_path_full, n)))
582 for (; tl; tl = tl->next)
584 /* need to copy recword because it may be changed */
586 wrd->index_type = *tl->structure;
587 memcpy (&wrd_tl, wrd, sizeof(*wrd));
589 sp_parse(sp, n, &wrd_tl, tl->source);
591 /* this is just the old fashioned attribute based index */
592 wrd_tl.index_name = tl->index_name;
593 if (p->flagShowRecords)
596 printf("%*sIdx: [%s]", (level + 1) * 4, "",
598 printf("%s %s", tl->index_name, tl->source);
599 printf (" XData:\"");
600 for (i = 0; i<wrd_tl.term_len && i < 40; i++)
601 fputc (wrd_tl.term_buf[i], stdout);
603 if (wrd_tl.term_len > 40)
605 fputc ('\n', stdout);
609 (*p->tokenAdd)(&wrd_tl);
610 index_staticrank(p, &wrd_tl, n->root->u.root.absyn);
612 if (wrd_tl.seqno > max_seqno)
613 max_seqno = wrd_tl.seqno;
616 wrd->seqno = max_seqno;
619 /* xpath indexing is done, if there was no termlist given,
620 or no ! in the termlist, and default indexing is enabled... */
621 if (!p->flagShowRecords && !xpdone && !termlist_only)
623 wrd->index_name = xpath_index;
624 wrd->index_type = 'w';
631 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
633 wrd->index_type = '0';
634 wrd->term_buf = tag_path_full;
635 wrd->term_len = strlen(tag_path_full);
636 wrd->index_name = xpath_index;
637 if (p->flagShowRecords)
639 printf("%*s tag=", (level + 1) * 4, "");
640 for (i = 0; i<wrd->term_len && i < 40; i++)
641 fputc (wrd->term_buf[i], stdout);
650 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
652 if (xpath_is_start == 1) /* only for the starting tag... */
654 #define MAX_ATTR_COUNT 50
655 data1_termlist *tll[MAX_ATTR_COUNT];
658 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
660 char attr_tag_path_full[1024];
662 /* this could be cached as well */
663 sprintf (attr_tag_path_full, "@%s/%s",
664 xp->name, tag_path_full);
666 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
668 /* attribute (no value) */
669 wrd->index_type = '0';
670 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
671 wrd->term_buf = xp->name;
672 wrd->term_len = strlen(xp->name);
679 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2)
681 /* attribute value exact */
682 strcpy (comb, xp->name);
684 strcat (comb, xp->value);
686 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
687 wrd->index_type = '0';
688 wrd->term_buf = comb;
689 wrd->term_len = strlen(comb);
698 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
700 char attr_tag_path_full[1024];
703 sprintf (attr_tag_path_full, "@%s/%s",
704 xp->name, tag_path_full);
708 /* If there is a termlist given (=xelm directive) */
709 for (; tl; tl = tl->next)
713 /* add xpath index for the attribute */
714 index_xpath_attr (attr_tag_path_full, xp->name,
715 xp->value, tl->structure,
719 /* index attribute value (only path/@attr) */
722 wrd->index_name = tl->index_name;
723 wrd->index_type = *tl->structure;
724 wrd->term_buf = xp->value;
725 wrd->term_len = strlen(xp->value);
727 index_staticrank(p, wrd,
728 n->root->u.root.absyn);
733 /* if there was no termlist for the given path,
734 or the termlist didn't have a ! element, index
735 the attribute as "w" */
736 if ((!xpdone) && (!termlist_only))
738 index_xpath_attr (attr_tag_path_full, xp->name,
739 xp->value, "w", p, wrd);
748 static void index_termlist (struct source_parser *sp, data1_node *par,
750 struct recExtractCtrl *p, int level, RecWord *wrd)
752 data1_termlist *tlist = 0;
753 data1_datatype dtype = DATA1K_string;
756 * cycle up towards the root until we find a tag with an att..
757 * this has the effect of indexing locally defined tags with
758 * the attribute of their ancestor in the record.
761 while (!par->u.tag.element)
762 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
764 if (!par || !(tlist = par->u.tag.element->termlists))
766 if (par->u.tag.element->tag)
767 dtype = par->u.tag.element->tag->kind;
769 for (; tlist; tlist = tlist->next)
771 /* consider source */
773 assert(tlist->source);
774 sp_parse(sp, n, wrd, tlist->source);
776 if (wrd->term_buf && wrd->term_len)
778 if (p->flagShowRecords)
781 printf("%*sIdx: [%s]", (level + 1) * 4, "",
783 printf("%s %s", tlist->index_name, tlist->source);
784 printf (" XData:\"");
785 for (i = 0; i<wrd->term_len && i < 40; i++)
786 fputc (wrd->term_buf[i], stdout);
788 if (wrd->term_len > 40)
790 fputc ('\n', stdout);
794 wrd->index_type = *tlist->structure;
795 wrd->index_name = tlist->index_name;
796 index_staticrank(p, wrd, n->root->u.root.absyn);
803 static int dumpkeys_r(struct source_parser *sp,
804 data1_node *n, struct recExtractCtrl *p, int level,
807 for (; n; n = n->next)
809 if (p->flagShowRecords) /* display element description to user */
811 if (n->which == DATA1N_root)
813 printf("%*s", level * 4, "");
814 printf("Record type: '%s'\n", n->u.root.type);
816 else if (n->which == DATA1N_tag)
820 printf("%*s", level * 4, "");
821 if (!(e = n->u.tag.element))
822 printf("Local tag: '%s'\n", n->u.tag.tag);
825 printf("Elm: '%s' ", e->name);
828 data1_tag *t = e->tag;
830 printf("TagNam: '%s' ", t->names->name);
833 printf("%s[%d],", t->tagset->name, t->tagset->type);
836 if (t->which == DATA1T_numeric)
837 printf("%d)", t->value.numeric);
839 printf("'%s')", t->value.string);
846 if (n->which == DATA1N_tag)
848 index_termlist(sp, n, n, p, level, wrd);
849 /* index start tag */
850 if (n->root->u.root.absyn)
851 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_BEGIN,
856 if (dumpkeys_r(sp, n->child, p, level + 1, wrd) < 0)
860 if (n->which == DATA1N_data)
862 data1_node *par = get_parent_tag(p->dh, n);
864 if (p->flagShowRecords)
866 printf("%*s", level * 4, "");
868 if (n->u.data.len > 256)
869 printf("'%.170s ... %.70s'\n", n->u.data.data,
870 n->u.data.data + n->u.data.len-70);
871 else if (n->u.data.len > 0)
872 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
878 index_termlist(sp, par, n, p, level, wrd);
880 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_CDATA,
884 if (n->which == DATA1N_tag)
887 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_END,
891 if (p->flagShowRecords && n->which == DATA1N_root)
893 printf("%*s-------------\n\n", level * 4, "");
899 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, RecWord *wrd)
901 struct source_parser *sp = source_parser_create();
902 int r = dumpkeys_r(sp, n, p, 0, wrd);
903 source_parser_destroy(sp);
907 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
910 int oidtmp[OID_SIZE];
913 oe.proto = PROTO_Z3950;
914 oe.oclass = CLASS_SCHEMA;
917 oe.value = n->u.root.absyn->reference;
919 if ((oid_ent_to_oid (&oe, oidtmp)))
920 (*p->schemaAdd)(p, oidtmp);
924 /* data1_pr_tree(p->dh, n, stdout); */
926 return dumpkeys(n, p, &wrd);
929 static int grs_extract_sub(void *clientData, struct recExtractCtrl *p,
931 data1_node *(*grs_read)(struct grs_read_info *))
934 struct grs_read_info gri;
936 int oidtmp[OID_SIZE];
939 gri.stream = p->stream;
942 gri.clientData = clientData;
944 n = (*grs_read)(&gri);
946 return RECCTRL_EXTRACT_EOF;
947 oe.proto = PROTO_Z3950;
948 oe.oclass = CLASS_SCHEMA;
950 if (!n->u.root.absyn)
951 return RECCTRL_EXTRACT_ERROR;
955 oe.value = n->u.root.absyn->reference;
956 if ((oid_ent_to_oid (&oe, oidtmp)))
957 (*p->schemaAdd)(p, oidtmp);
959 data1_concat_text(p->dh, mem, n);
961 /* ensure our data1 tree is UTF-8 */
962 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
965 data1_remove_idzebra_subtree (p->dh, n);
968 data1_pr_tree (p->dh, n, stdout);
972 if (dumpkeys(n, p, &wrd) < 0)
974 return RECCTRL_EXTRACT_ERROR_GENERIC;
976 return RECCTRL_EXTRACT_OK;
979 int zebra_grs_extract(void *clientData, struct recExtractCtrl *p,
980 data1_node *(*grs_read)(struct grs_read_info *))
983 NMEM mem = nmem_create ();
984 ret = grs_extract_sub(clientData, p, mem, grs_read);
990 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
992 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c,
993 char **addinfo, ODR o)
995 data1_esetname *eset;
1001 case Z_RecordComp_simple:
1002 if (c->u.simple->which != Z_ElementSetNames_generic)
1003 return 26; /* only generic form supported. Fix this later */
1004 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
1005 c->u.simple->u.generic)))
1007 yaz_log(YLOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
1008 *addinfo = odr_strdup(o, c->u.simple->u.generic);
1009 return 25; /* invalid esetname */
1011 yaz_log(YLOG_DEBUG, "Esetname '%s' in simple compspec",
1012 c->u.simple->u.generic);
1015 case Z_RecordComp_complex:
1016 if (c->u.complex->generic)
1018 /* insert check for schema */
1019 if ((p = c->u.complex->generic->elementSpec))
1023 case Z_ElementSpec_elementSetName:
1025 data1_getesetbyname(dh, n->u.root.absyn,
1026 p->u.elementSetName)))
1028 yaz_log(YLOG_DEBUG, "Unknown esetname '%s'",
1029 p->u.elementSetName);
1030 *addinfo = odr_strdup(o, p->u.elementSetName);
1031 return 25; /* invalid esetname */
1033 yaz_log(YLOG_DEBUG, "Esetname '%s' in complex compspec",
1034 p->u.elementSetName);
1037 case Z_ElementSpec_externalSpec:
1038 if (p->u.externalSpec->which == Z_External_espec1)
1040 yaz_log(YLOG_DEBUG, "Got Espec-1");
1041 espec = p->u.externalSpec-> u.espec1;
1045 yaz_log(YLOG_LOG, "Unknown external espec.");
1046 return 25; /* bad. what is proper diagnostic? */
1053 return 26; /* fix */
1057 yaz_log(YLOG_DEBUG, "Element: Espec-1 match");
1058 return data1_doespec1(dh, n, espec);
1062 yaz_log(YLOG_DEBUG, "Element: all match");
1067 /* Add Zebra info in separate namespace ...
1070 <metadata xmlns="http://www.indexdata.dk/zebra/">
1072 <localnumber>447</localnumber>
1073 <filename>records/genera.xml</filename>
1078 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
1081 const char *idzebra_ns[3];
1082 const char *i2 = "\n ";
1083 const char *i4 = "\n ";
1086 idzebra_ns[0] = "xmlns";
1087 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
1090 data1_mk_text (p->dh, mem, i2, top);
1092 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
1094 data1_mk_text (p->dh, mem, "\n", top);
1096 data1_mk_text (p->dh, mem, i4, n);
1098 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
1102 data1_mk_text (p->dh, mem, i4, n);
1103 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
1105 data1_mk_text (p->dh, mem, i4, n);
1106 data1_mk_tag_data_zint (p->dh, n, "localnumber", p->localno, mem);
1109 data1_mk_text (p->dh, mem, i4, n);
1110 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
1112 data1_mk_text (p->dh, mem, i2, n);
1115 int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p,
1116 data1_node *(*grs_read)(struct grs_read_info *))
1118 data1_node *node = 0, *onode = 0, *top;
1121 int res, selected = 0;
1123 struct grs_read_info gri;
1124 const char *tagname;
1126 int requested_schema = VAL_NONE;
1127 data1_marctab *marctab;
1130 mem = nmem_create();
1131 gri.stream = p->stream;
1134 gri.clientData = clientData;
1136 yaz_log(YLOG_DEBUG, "grs_retrieve");
1137 node = (*grs_read)(&gri);
1144 data1_concat_text(p->dh, mem, node);
1146 data1_remove_idzebra_subtree (p->dh, node);
1149 data1_pr_tree (p->dh, node, stdout);
1151 top = data1_get_root_tag (p->dh, node);
1153 yaz_log(YLOG_DEBUG, "grs_retrieve: size");
1154 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1156 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1158 dnew->u.data.what = DATA1I_text;
1159 dnew->u.data.data = dnew->lbuf;
1160 sprintf(dnew->u.data.data, "%d", p->recordSize);
1161 dnew->u.data.len = strlen(dnew->u.data.data);
1164 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1165 if (tagname && p->score >= 0 &&
1166 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1168 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1169 dnew->u.data.what = DATA1I_num;
1170 dnew->u.data.data = dnew->lbuf;
1171 sprintf(dnew->u.data.data, "%d", p->score);
1172 dnew->u.data.len = strlen(dnew->u.data.data);
1175 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1176 "localControlNumber");
1177 if (tagname && p->localno > 0 &&
1178 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1180 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1181 dnew->u.data.what = DATA1I_text;
1182 dnew->u.data.data = dnew->lbuf;
1184 sprintf(dnew->u.data.data, ZINT_FORMAT, p->localno);
1185 dnew->u.data.len = strlen(dnew->u.data.data);
1188 if (p->input_format == VAL_TEXT_XML)
1189 zebra_xml_metadata (p, top, mem);
1192 data1_pr_tree (p->dh, node, stdout);
1194 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1195 p->comp->u.complex->generic &&
1196 p->comp->u.complex->generic->which == Z_Schema_oid &&
1197 p->comp->u.complex->generic->schema.oid)
1199 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1201 requested_schema = oe->value;
1203 /* If schema has been specified, map if possible, then check that
1204 * we got the right one
1206 if (requested_schema != VAL_NONE)
1208 yaz_log(YLOG_DEBUG, "grs_retrieve: schema mapping");
1209 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1211 if (map->target_absyn_ref == requested_schema)
1214 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1223 if (node->u.root.absyn &&
1224 requested_schema != node->u.root.absyn->reference)
1226 p->diagnostic = 238;
1232 * Does the requested format match a known syntax-mapping? (this reflects
1233 * the overlap of schema and formatting which is inherent in the MARC
1236 yaz_log(YLOG_DEBUG, "grs_retrieve: syntax mapping");
1237 if (node->u.root.absyn)
1238 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1240 if (map->target_absyn_ref == p->input_format)
1243 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1252 yaz_log(YLOG_DEBUG, "grs_retrieve: schemaIdentifier");
1253 if (node->u.root.absyn &&
1254 node->u.root.absyn->reference != VAL_NONE &&
1255 p->input_format == VAL_GRS1)
1259 int oidtmp[OID_SIZE];
1261 oe.proto = PROTO_Z3950;
1262 oe.oclass = CLASS_SCHEMA;
1263 oe.value = node->u.root.absyn->reference;
1265 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1268 data1_handle dh = p->dh;
1272 for (ii = oid; *ii >= 0; ii++)
1276 sprintf(p, "%d", *ii);
1279 if ((dnew = data1_mk_tag_data_wd(dh, top,
1280 "schemaIdentifier", mem)))
1282 dnew->u.data.what = DATA1I_oid;
1283 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1284 memcpy(dnew->u.data.data, tmp, p - tmp);
1285 dnew->u.data.len = p - tmp;
1290 yaz_log(YLOG_DEBUG, "grs_retrieve: element spec");
1291 if (p->comp && (res = process_comp(p->dh, node, p->comp, &p->addinfo,
1294 p->diagnostic = res;
1298 else if (p->comp && !res)
1302 data1_pr_tree (p->dh, node, stdout);
1304 yaz_log(YLOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1305 switch (p->output_format = (p->input_format != VAL_NONE ?
1306 p->input_format : VAL_SUTRS))
1310 data1_pr_tree (p->dh, node, stdout);
1312 /* default output encoding for XML is UTF-8 */
1313 data1_iconv (p->dh, mem, node,
1314 p->encoding ? p->encoding : "UTF-8",
1315 data1_get_encoding(p->dh, node));
1317 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1319 p->diagnostic = 238;
1322 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1323 memcpy (new_buf, p->rec_buf, p->rec_len);
1324 p->rec_buf = new_buf;
1328 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1330 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1332 p->diagnostic = 238; /* not available in requested syntax */
1337 /* ensure our data1 tree is UTF-8 */
1338 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1340 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1342 p->diagnostic = 238;
1347 /* ensure our data1 tree is UTF-8 */
1348 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1349 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1351 p->diagnostic = 238;
1357 data1_iconv (p->dh, mem, node, p->encoding,
1358 data1_get_encoding(p->dh, node));
1359 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1361 p->diagnostic = 238;
1364 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1365 memcpy (new_buf, p->rec_buf, p->rec_len);
1366 p->rec_buf = new_buf;
1371 data1_iconv (p->dh, mem, node, p->encoding,
1372 data1_get_encoding(p->dh, node));
1373 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1375 p->diagnostic = 238;
1378 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1379 memcpy (new_buf, p->rec_buf, p->rec_len);
1380 p->rec_buf = new_buf;
1384 if (!node->u.root.absyn)
1386 p->diagnostic = 238;
1389 for (marctab = node->u.root.absyn->marc; marctab;
1390 marctab = marctab->next)
1391 if (marctab->reference == p->input_format)
1395 p->diagnostic = 238;
1399 data1_iconv (p->dh, mem, node, p->encoding,
1400 data1_get_encoding(p->dh, node));
1401 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1402 selected, &p->rec_len)))
1403 p->diagnostic = 238;
1406 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1407 memcpy (new_buf, p->rec_buf, p->rec_len);
1408 p->rec_buf = new_buf;
1418 * indent-tabs-mode: nil
1420 * vim: shiftwidth=4 tabstop=8 expandtab