1 /* $Id: recgrs.c,v 1.94 2004-11-29 21:45:12 adam Exp $
2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004
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 Zebra; see the file LICENSE.zebra. If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 #include <sys/types.h>
35 #include <idzebra/recgrs.h>
37 #define GRS_MAX_WORD 512
39 struct source_parser {
46 static int sp_lex(struct source_parser *sp)
48 while (*sp->src == ' ')
52 while (*sp->src && !strchr("<>();,-: ", *sp->src))
61 sp->lookahead = *sp->src;
69 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd)
71 if (sp->lookahead != 't')
73 if (sp->len == 4 && !memcmp(sp->tok, "data", sp->len))
75 if (n->which == DATA1N_data)
77 wrd->string = n->u.data.data;
78 wrd->length = n->u.data.len;
82 else if (sp->len == 3 && !memcmp(sp->tok, "tag", sp->len))
84 if (n->which == DATA1N_tag)
86 wrd->string = n->u.tag.tag;
87 wrd->length = strlen(n->u.tag.tag);
91 else if (sp->len == 4 && !memcmp(sp->tok, "attr", sp->len))
94 if (sp->lookahead != '(')
97 if (sp->lookahead != 't')
100 if (n->which == DATA1N_tag)
102 data1_xattr *p = n->u.tag.attributes;
103 while (p && strlen(p->name) != sp->len &&
104 memcmp (p->name, sp->tok, sp->len))
108 wrd->string = p->value;
109 wrd->length = strlen(p->value);
113 if (sp->lookahead != ')')
117 else if (sp->len == 5 && !memcmp(sp->tok, "range", sp->len))
121 if (sp->lookahead != '(')
126 if (sp->lookahead != ',')
130 if (sp->lookahead != 't')
132 start = atoi_n(sp->tok, sp->len);
135 if (sp->lookahead != ',')
139 if (sp->lookahead != 't')
141 len = atoi_n(sp->tok, sp->len);
144 if (sp->lookahead != ')')
148 if (wrd->string && wrd->length)
150 wrd->string += start;
151 wrd->length -= start;
152 if (wrd->length > len)
159 static int sp_parse(data1_node *n, RecWord *wrd, const char *src)
161 struct source_parser sp;
168 return sp_expr(&sp, n, wrd);
171 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
180 if (p->which == XPATH_PREDICATE_RELATION) {
181 if (p->u.relation.name[0]) {
182 if (*p->u.relation.name != '@') {
184 " Only attributes (@) are supported in xelm xpath predicates");
185 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
188 attname = p->u.relation.name + 1;
190 /* looking for the attribute with a specified name */
191 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
192 yaz_log(YLOG_DEBUG," - attribute %s <-> %s", attname, attr->name );
194 if (!strcmp(attr->name, attname)) {
195 if (p->u.relation.op[0]) {
196 if (*p->u.relation.op != '=') {
198 "Only '=' relation is supported (%s)",p->u.relation.op);
199 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
202 yaz_log(YLOG_DEBUG," - value %s <-> %s",
203 p->u.relation.value, attr->value );
204 if (!strcmp(attr->value, p->u.relation.value)) {
209 /* attribute exists, no value specified */
214 yaz_log(YLOG_DEBUG, "return %d", res);
220 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
221 if (!strcmp(p->u.boolean.op,"and")) {
222 return d1_check_xpath_predicate(n, p->u.boolean.left)
223 && d1_check_xpath_predicate(n, p->u.boolean.right);
225 else if (!strcmp(p->u.boolean.op,"or")) {
226 return (d1_check_xpath_predicate(n, p->u.boolean.left)
227 || d1_check_xpath_predicate(n, p->u.boolean.right));
229 yaz_log(YLOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
240 New function, looking for xpath "element" definitions in abs, by
241 tagpath, using a kind of ugly regxp search.The DFA was built while
242 parsing abs, so here we just go trough them and try to match
243 against the given tagpath. The first matching entry is returned.
247 Added support for enhanced xelm. Now [] predicates are considered
248 as well, when selecting indexing rules... (why the hell it's called
255 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
257 data1_absyn *abs = n->root->u.root.absyn;
258 data1_xpelement *xpe = abs->xp_elements;
261 struct xpath_location_step *xp;
264 char *pexpr = xmalloc(strlen(tagpath)+2);
267 sprintf (pexpr, "%s\n", tagpath);
268 yaz_log(YLOG_DEBUG,"Checking tagpath %s",tagpath);
271 struct DFA_state **dfaar = xpe->dfa->states;
272 struct DFA_state *s=dfaar[0];
279 c = *pexpr++; t = s->trans; i = s->tran_no;
280 if ((c >= t->ch[0] && c <= t->ch[1]) || (!t->ch[0])) {
283 if ((s = dfaar[t->to])->rule_no &&
284 (start_line || s->rule_nno)) {
288 for (t=s->trans, i=s->tran_no; --i >= 0; t++) {
289 if ((unsigned) *p >= t->ch[0] && (unsigned) *p <= t->ch[1])
296 yaz_log(YLOG_DEBUG," xpath match %s",xpe->xpath_expr);
298 yaz_log(YLOG_DEBUG," xpath no match %s",xpe->xpath_expr);
303 /* we have to check the perdicates up to the root node */
306 /* find the first tag up in the node structure */
307 nn = n; while (nn && nn->which != DATA1N_tag) {
311 /* go from inside out in the node structure, while going
312 backwards trough xpath location steps ... */
313 for (i=xpe->xpath_len - 1; i>0; i--) {
315 yaz_log(YLOG_DEBUG,"Checking step %d: %s on tag %s",
316 i,xp[i].part,nn->u.tag.tag);
318 if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
319 yaz_log(YLOG_DEBUG," Predicates didn't match");
324 if (nn->which == DATA1N_tag) {
339 yaz_log(YLOG_DEBUG,"Got it");
340 return xpe->termlists;
347 1 start element (tag)
349 3 start attr (and attr-exact)
357 Now, if there is a matching xelm described in abs, for the
358 indexed element or the attribute, then the data is handled according
359 to those definitions...
361 modified by pop, 2002-12-13
364 /* add xpath index for an attribute */
365 static void index_xpath_attr (char *tag_path, char *name, char *value,
366 char *structure, struct recExtractCtrl *p,
369 wrd->attrSet = VAL_IDXPATH;
372 wrd->string = tag_path;
373 wrd->length = strlen(tag_path);
380 wrd->length = strlen(value);
386 wrd->string = tag_path;
387 wrd->length = strlen(tag_path);
392 static void index_xpath (data1_node *n, struct recExtractCtrl *p,
393 int level, RecWord *wrd, int use)
396 char tag_path_full[1024];
399 int termlist_only = 1;
403 yaz_log(YLOG_DEBUG, "index_xpath level=%d use=%d", level, use);
404 if ((!n->root->u.root.absyn) ||
405 (n->root->u.root.absyn->enable_xpath_indexing)) {
412 wrd->string = n->u.data.data;
413 wrd->length = n->u.data.len;
417 /* we have to fetch the whole path to the data tag */
418 for (nn = n; nn; nn = nn->parent) {
419 if (nn->which == DATA1N_tag) {
420 size_t tlen = strlen(nn->u.tag.tag);
421 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
422 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
424 tag_path_full[flen++] = '/';
426 else if (nn->which == DATA1N_root) break;
429 tag_path_full[flen] = 0;
431 /* If we have a matching termlist... */
432 if (n->root->u.root.absyn &&
433 (tl = xpath_termlist_by_tagpath(tag_path_full, n)))
435 for (; tl; tl = tl->next)
437 /* need to copy recword because it may be changed */
439 wrd->reg_type = *tl->structure;
440 /* this is the ! case, so structure is for the xpath index */
441 memcpy (&wrd_tl, wrd, sizeof(*wrd));
443 sp_parse(n, &wrd_tl, tl->source);
445 wrd_tl.attrSet = VAL_IDXPATH;
446 wrd_tl.attrUse = use;
447 if (p->flagShowRecords)
450 printf("%*sXPath index", (level + 1) * 4, "");
451 printf (" XData:\"");
452 for (i = 0; i<wrd_tl.length && i < 40; i++)
453 fputc (wrd_tl.string[i], stdout);
455 if (wrd_tl.length > 40)
457 fputc ('\n', stdout);
460 (*p->tokenAdd)(&wrd_tl);
463 /* this is just the old fashioned attribute based index */
464 wrd_tl.attrSet = (int) (tl->att->parent->reference);
465 wrd_tl.attrUse = tl->att->locals->local;
466 if (p->flagShowRecords)
469 printf("%*sIdx: [%s]", (level + 1) * 4, "",
471 printf("%s:%s [%d] %s",
472 tl->att->parent->name,
473 tl->att->name, tl->att->value,
475 printf (" XData:\"");
476 for (i = 0; i<wrd_tl.length && i < 40; i++)
477 fputc (wrd_tl.string[i], stdout);
479 if (wrd_tl.length > 40)
481 fputc ('\n', stdout);
484 (*p->tokenAdd)(&wrd_tl);
488 /* xpath indexing is done, if there was no termlist given,
489 or no ! in the termlist, and default indexing is enabled... */
490 if (!p->flagShowRecords && !xpdone && !termlist_only)
492 wrd->attrSet = VAL_IDXPATH;
500 for (nn = n; nn; nn = nn->parent)
502 if (nn->which == DATA1N_tag)
504 size_t tlen = strlen(nn->u.tag.tag);
505 if (tlen + flen > (sizeof(tag_path_full)-2))
507 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
509 tag_path_full[flen++] = '/';
511 else if (nn->which == DATA1N_root)
517 wrd->string = tag_path_full;
519 wrd->attrSet = VAL_IDXPATH;
521 if (p->flagShowRecords)
523 printf("%*s tag=", (level + 1) * 4, "");
524 for (i = 0; i<wrd->length && i < 40; i++)
525 fputc (wrd->string[i], stdout);
536 tag_path_full[flen] = 0;
538 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
539 directive, or default xpath indexing is enabled */
540 if (!(do_xpindex = 1 - termlist_only)) {
541 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
542 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
546 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
549 if (use == 1) /* only for the starting tag... */
551 #define MAX_ATTR_COUNT 50
552 data1_termlist *tll[MAX_ATTR_COUNT];
556 /* get termlists for attributes, and find out, if we have to do xpath indexing */
557 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
562 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
564 int do_xpindex = 1 - termlist_only;
566 char attr_tag_path_full[1024];
569 /* this could be cached as well */
570 sprintf (attr_tag_path_full, "@%s/%.*s",
571 xp->name, int_len, tag_path_full);
573 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
575 /* if there is a ! in the xelm termlist, or default indexing is on,
576 proceed with xpath idx */
579 for (; tl; tl = tl->next)
588 /* attribute (no value) */
591 wrd->string = xp->name;
592 wrd->length = strlen(xp->name);
598 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
600 /* attribute value exact */
601 strcpy (comb, xp->name);
603 strcat (comb, xp->value);
608 wrd->length = strlen(comb);
618 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
620 char attr_tag_path_full[1024];
624 sprintf (attr_tag_path_full, "@%s/%.*s",
625 xp->name, int_len, tag_path_full);
629 /* If there is a termlist given (=xelm directive) */
630 for (; tl; tl = tl->next)
633 /* add xpath index for the attribute */
634 index_xpath_attr (attr_tag_path_full, xp->name,
635 xp->value, tl->structure,
639 /* add attribute based index for the attribute */
642 (tl->att->parent->reference);
643 wrd->attrUse = tl->att->locals->local;
644 wrd->reg_type = *tl->structure;
645 wrd->string = xp->value;
646 wrd->length = strlen(xp->value);
652 /* if there was no termlist for the given path,
653 or the termlist didn't have a ! element, index
654 the attribute as "w" */
655 if ((!xpdone) && (!termlist_only))
657 index_xpath_attr (attr_tag_path_full, xp->name,
658 xp->value, "w", p, wrd);
667 static void index_termlist (data1_node *par, data1_node *n,
668 struct recExtractCtrl *p, int level, RecWord *wrd)
670 data1_termlist *tlist = 0;
671 data1_datatype dtype = DATA1K_string;
674 * cycle up towards the root until we find a tag with an att..
675 * this has the effect of indexing locally defined tags with
676 * the attribute of their ancestor in the record.
679 while (!par->u.tag.element)
680 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
682 if (!par || !(tlist = par->u.tag.element->termlists))
684 if (par->u.tag.element->tag)
685 dtype = par->u.tag.element->tag->kind;
687 for (; tlist; tlist = tlist->next)
689 /* consider source */
691 assert(tlist->source);
692 sp_parse(n, wrd, tlist->source);
696 if (p->flagShowRecords)
699 printf("%*sIdx: [%s]", (level + 1) * 4, "",
701 printf("%s:%s [%d] %s",
702 tlist->att->parent->name,
703 tlist->att->name, tlist->att->value,
705 printf (" XData:\"");
706 for (i = 0; i<wrd->length && i < 40; i++)
707 fputc (wrd->string[i], stdout);
709 if (wrd->length > 40)
711 fputc ('\n', stdout);
715 wrd->reg_type = *tlist->structure;
716 wrd->attrSet = (int) (tlist->att->parent->reference);
717 wrd->attrUse = tlist->att->locals->local;
724 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
727 for (; n; n = n->next)
729 if (p->flagShowRecords) /* display element description to user */
731 if (n->which == DATA1N_root)
733 printf("%*s", level * 4, "");
734 printf("Record type: '%s'\n", n->u.root.type);
736 else if (n->which == DATA1N_tag)
740 printf("%*s", level * 4, "");
741 if (!(e = n->u.tag.element))
742 printf("Local tag: '%s'\n", n->u.tag.tag);
745 printf("Elm: '%s' ", e->name);
748 data1_tag *t = e->tag;
750 printf("TagNam: '%s' ", t->names->name);
753 printf("%s[%d],", t->tagset->name, t->tagset->type);
756 if (t->which == DATA1T_numeric)
757 printf("%d)", t->value.numeric);
759 printf("'%s')", t->value.string);
766 if (n->which == DATA1N_tag)
768 index_termlist (n, n, p, level, wrd);
769 /* index start tag */
770 if (n->root->u.root.absyn)
771 index_xpath (n, p, level, wrd, 1);
775 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
779 if (n->which == DATA1N_data)
781 data1_node *par = get_parent_tag(p->dh, n);
783 if (p->flagShowRecords)
785 printf("%*s", level * 4, "");
787 if (n->u.data.len > 256)
788 printf("'%.170s ... %.70s'\n", n->u.data.data,
789 n->u.data.data + n->u.data.len-70);
790 else if (n->u.data.len > 0)
791 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
797 index_termlist (par, n, p, level, wrd);
799 index_xpath (n, p, level, wrd, 1016);
802 if (n->which == DATA1N_tag)
805 index_xpath (n, p, level, wrd, 2);
808 if (p->flagShowRecords && n->which == DATA1N_root)
810 printf("%*s-------------\n\n", level * 4, "");
816 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
819 int oidtmp[OID_SIZE];
822 oe.proto = PROTO_Z3950;
823 oe.oclass = CLASS_SCHEMA;
826 oe.value = n->u.root.absyn->reference;
828 if ((oid_ent_to_oid (&oe, oidtmp)))
829 (*p->schemaAdd)(p, oidtmp);
833 return dumpkeys(n, p, 0, &wrd);
836 static int grs_extract_sub(void *clientData, struct recExtractCtrl *p,
838 data1_node *(*grs_read)(struct grs_read_info *))
841 struct grs_read_info gri;
843 int oidtmp[OID_SIZE];
846 gri.readf = p->readf;
847 gri.seekf = p->seekf;
848 gri.tellf = p->tellf;
851 gri.offset = p->offset;
854 gri.clientData = clientData;
856 n = (*grs_read)(&gri);
858 return RECCTRL_EXTRACT_EOF;
859 oe.proto = PROTO_Z3950;
860 oe.oclass = CLASS_SCHEMA;
862 if (!n->u.root.absyn)
863 return RECCTRL_EXTRACT_ERROR;
867 oe.value = n->u.root.absyn->reference;
868 if ((oid_ent_to_oid (&oe, oidtmp)))
869 (*p->schemaAdd)(p, oidtmp);
871 data1_concat_text(p->dh, mem, n);
873 /* ensure our data1 tree is UTF-8 */
874 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
877 data1_pr_tree (p->dh, n, stdout);
881 if (dumpkeys(n, p, 0, &wrd) < 0)
883 data1_free_tree(p->dh, n);
884 return RECCTRL_EXTRACT_ERROR_GENERIC;
886 data1_free_tree(p->dh, n);
887 return RECCTRL_EXTRACT_OK;
890 int zebra_grs_extract(void *clientData, struct recExtractCtrl *p,
891 data1_node *(*grs_read)(struct grs_read_info *))
894 NMEM mem = nmem_create ();
895 ret = grs_extract_sub(clientData, p, mem, grs_read);
901 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
903 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c,
904 char **addinfo, ODR o)
906 data1_esetname *eset;
912 case Z_RecordComp_simple:
913 if (c->u.simple->which != Z_ElementSetNames_generic)
914 return 26; /* only generic form supported. Fix this later */
915 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
916 c->u.simple->u.generic)))
918 yaz_log(YLOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
919 *addinfo = odr_strdup(o, c->u.simple->u.generic);
920 return 25; /* invalid esetname */
922 yaz_log(YLOG_DEBUG, "Esetname '%s' in simple compspec",
923 c->u.simple->u.generic);
926 case Z_RecordComp_complex:
927 if (c->u.complex->generic)
929 /* insert check for schema */
930 if ((p = c->u.complex->generic->elementSpec))
934 case Z_ElementSpec_elementSetName:
936 data1_getesetbyname(dh, n->u.root.absyn,
937 p->u.elementSetName)))
939 yaz_log(YLOG_DEBUG, "Unknown esetname '%s'",
940 p->u.elementSetName);
941 *addinfo = odr_strdup(o, p->u.elementSetName);
942 return 25; /* invalid esetname */
944 yaz_log(YLOG_DEBUG, "Esetname '%s' in complex compspec",
945 p->u.elementSetName);
948 case Z_ElementSpec_externalSpec:
949 if (p->u.externalSpec->which == Z_External_espec1)
951 yaz_log(YLOG_DEBUG, "Got Espec-1");
952 espec = p->u.externalSpec-> u.espec1;
956 yaz_log(YLOG_LOG, "Unknown external espec.");
957 return 25; /* bad. what is proper diagnostic? */
968 yaz_log(YLOG_DEBUG, "Element: Espec-1 match");
969 return data1_doespec1(dh, n, espec);
973 yaz_log(YLOG_DEBUG, "Element: all match");
978 /* Add Zebra info in separate namespace ...
981 <metadata xmlns="http://www.indexdata.dk/zebra/">
983 <localnumber>447</localnumber>
984 <filename>records/genera.xml</filename>
989 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
992 const char *idzebra_ns[3];
993 const char *i2 = "\n ";
994 const char *i4 = "\n ";
997 idzebra_ns[0] = "xmlns";
998 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
1001 data1_mk_text (p->dh, mem, i2, top);
1003 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
1005 data1_mk_text (p->dh, mem, "\n", top);
1007 data1_mk_text (p->dh, mem, i4, n);
1009 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
1013 data1_mk_text (p->dh, mem, i4, n);
1014 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
1016 data1_mk_text (p->dh, mem, i4, n);
1017 data1_mk_tag_data_zint (p->dh, n, "localnumber", p->localno, mem);
1020 data1_mk_text (p->dh, mem, i4, n);
1021 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
1023 data1_mk_text (p->dh, mem, i2, n);
1026 int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p,
1027 data1_node *(*grs_read)(struct grs_read_info *))
1029 data1_node *node = 0, *onode = 0, *top;
1032 int res, selected = 0;
1034 struct grs_read_info gri;
1035 const char *tagname;
1037 int requested_schema = VAL_NONE;
1038 data1_marctab *marctab;
1041 mem = nmem_create();
1042 gri.readf = p->readf;
1043 gri.seekf = p->seekf;
1044 gri.tellf = p->tellf;
1050 gri.clientData = clientData;
1052 yaz_log(YLOG_DEBUG, "grs_retrieve");
1053 node = (*grs_read)(&gri);
1060 data1_concat_text(p->dh, mem, node);
1062 /* ensure our data1 tree is UTF-8 */
1063 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1066 data1_pr_tree (p->dh, node, stdout);
1068 top = data1_get_root_tag (p->dh, node);
1070 yaz_log(YLOG_DEBUG, "grs_retrieve: size");
1071 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1073 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1075 dnew->u.data.what = DATA1I_text;
1076 dnew->u.data.data = dnew->lbuf;
1077 sprintf(dnew->u.data.data, "%d", p->recordSize);
1078 dnew->u.data.len = strlen(dnew->u.data.data);
1081 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1082 if (tagname && p->score >= 0 &&
1083 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1085 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1086 dnew->u.data.what = DATA1I_num;
1087 dnew->u.data.data = dnew->lbuf;
1088 sprintf(dnew->u.data.data, "%d", p->score);
1089 dnew->u.data.len = strlen(dnew->u.data.data);
1092 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1093 "localControlNumber");
1094 if (tagname && p->localno > 0 &&
1095 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1097 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1098 dnew->u.data.what = DATA1I_text;
1099 dnew->u.data.data = dnew->lbuf;
1101 sprintf(dnew->u.data.data, ZINT_FORMAT, p->localno);
1102 dnew->u.data.len = strlen(dnew->u.data.data);
1105 if (p->input_format == VAL_TEXT_XML)
1106 zebra_xml_metadata (p, top, mem);
1109 data1_pr_tree (p->dh, node, stdout);
1111 #if YAZ_VERSIONL >= 0x010903L
1112 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1113 p->comp->u.complex->generic &&
1114 p->comp->u.complex->generic->which == Z_Schema_oid &&
1115 p->comp->u.complex->generic->schema.oid)
1117 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1119 requested_schema = oe->value;
1122 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1123 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1125 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1127 requested_schema = oe->value;
1131 /* If schema has been specified, map if possible, then check that
1132 * we got the right one
1134 if (requested_schema != VAL_NONE)
1136 yaz_log(YLOG_DEBUG, "grs_retrieve: schema mapping");
1137 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1139 if (map->target_absyn_ref == requested_schema)
1142 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1151 if (node->u.root.absyn &&
1152 requested_schema != node->u.root.absyn->reference)
1154 p->diagnostic = 238;
1160 * Does the requested format match a known syntax-mapping? (this reflects
1161 * the overlap of schema and formatting which is inherent in the MARC
1164 yaz_log(YLOG_DEBUG, "grs_retrieve: syntax mapping");
1165 if (node->u.root.absyn)
1166 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1168 if (map->target_absyn_ref == p->input_format)
1171 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1180 yaz_log(YLOG_DEBUG, "grs_retrieve: schemaIdentifier");
1181 if (node->u.root.absyn &&
1182 node->u.root.absyn->reference != VAL_NONE &&
1183 p->input_format == VAL_GRS1)
1187 int oidtmp[OID_SIZE];
1189 oe.proto = PROTO_Z3950;
1190 oe.oclass = CLASS_SCHEMA;
1191 oe.value = node->u.root.absyn->reference;
1193 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1196 data1_handle dh = p->dh;
1200 for (ii = oid; *ii >= 0; ii++)
1204 sprintf(p, "%d", *ii);
1207 if ((dnew = data1_mk_tag_data_wd(dh, top,
1208 "schemaIdentifier", mem)))
1210 dnew->u.data.what = DATA1I_oid;
1211 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1212 memcpy(dnew->u.data.data, tmp, p - tmp);
1213 dnew->u.data.len = p - tmp;
1218 yaz_log(YLOG_DEBUG, "grs_retrieve: element spec");
1219 if (p->comp && (res = process_comp(p->dh, node, p->comp, &p->addinfo,
1222 p->diagnostic = res;
1224 data1_free_tree(p->dh, onode);
1225 data1_free_tree(p->dh, node);
1229 else if (p->comp && !res)
1233 data1_pr_tree (p->dh, node, stdout);
1235 yaz_log(YLOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1236 switch (p->output_format = (p->input_format != VAL_NONE ?
1237 p->input_format : VAL_SUTRS))
1242 data1_pr_tree (p->dh, node, stdout);
1246 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1248 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1250 p->diagnostic = 238;
1253 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1254 memcpy (new_buf, p->rec_buf, p->rec_len);
1255 p->rec_buf = new_buf;
1260 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1262 p->diagnostic = 238; /* not available in requested syntax */
1264 p->rec_len = (size_t) (-1);
1267 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1269 p->diagnostic = 238;
1271 p->rec_len = (size_t) (-1);
1274 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1276 p->diagnostic = 238;
1278 p->rec_len = (size_t) (-1);
1282 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1283 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1285 p->diagnostic = 238;
1288 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1289 memcpy (new_buf, p->rec_buf, p->rec_len);
1290 p->rec_buf = new_buf;
1294 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1296 p->diagnostic = 238;
1299 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1300 memcpy (new_buf, p->rec_buf, p->rec_len);
1301 p->rec_buf = new_buf;
1305 if (!node->u.root.absyn)
1307 p->diagnostic = 238;
1310 for (marctab = node->u.root.absyn->marc; marctab;
1311 marctab = marctab->next)
1312 if (marctab->reference == p->input_format)
1316 p->diagnostic = 238;
1320 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1321 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1322 selected, &p->rec_len)))
1323 p->diagnostic = 238;
1326 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1327 memcpy (new_buf, p->rec_buf, p->rec_len);
1328 p->rec_buf = new_buf;
1332 data1_free_tree(p->dh, node);
1334 data1_free_tree(p->dh, onode);