1 /* $Id: recgrs.c,v 1.85 2003-10-07 09:18:21 adam Exp $
2 Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003
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>
36 #define GRS_MAX_WORD 512
42 struct grs_handler *next;
46 struct grs_handler *handlers;
49 static int read_grs_type (struct grs_handlers *h,
50 struct grs_read_info *p, const char *type,
53 struct grs_handler *gh = h->handlers;
54 const char *cp = strchr (type, '.');
56 if (cp == NULL || cp == type)
58 cp = strlen(type) + type;
62 strcpy (p->type, cp+1);
63 for (gh = h->handlers; gh; gh = gh->next)
65 if (!memcmp (type, gh->type->type, cp-type) &&
66 gh->type->type[cp-type] == '\0')
71 gh->clientData = (*gh->type->init)();
73 p->clientData = gh->clientData;
74 *root = (gh->type->read)(p);
75 gh->clientData = p->clientData;
82 static void grs_add_handler (struct grs_handlers *h, RecTypeGrs t)
84 struct grs_handler *gh = (struct grs_handler *) xmalloc (sizeof(*gh));
85 gh->next = h->handlers;
92 static void *grs_init(RecType recType)
94 struct grs_handlers *h = (struct grs_handlers *) xmalloc (sizeof(*h));
97 grs_add_handler (h, recTypeGrs_sgml);
98 grs_add_handler (h, recTypeGrs_regx);
100 grs_add_handler (h, recTypeGrs_tcl);
102 grs_add_handler (h, recTypeGrs_marc);
103 grs_add_handler (h, recTypeGrs_marcxml);
105 grs_add_handler (h, recTypeGrs_xml);
108 grs_add_handler (h, recTypeGrs_perl);
113 static void grs_destroy(void *clientData)
115 struct grs_handlers *h = (struct grs_handlers *) clientData;
116 struct grs_handler *gh = h->handlers, *gh_next;
121 (*gh->type->destroy)(gh->clientData);
128 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
137 if (p->which == XPATH_PREDICATE_RELATION) {
138 if (p->u.relation.name[0]) {
139 if (*p->u.relation.name != '@') {
141 " Only attributes (@) are supported in xelm xpath predicates");
142 yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
145 attname = p->u.relation.name + 1;
147 /* looking for the attribute with a specified name */
148 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
149 yaz_log(LOG_DEBUG," - attribute %s <-> %s", attname, attr->name );
151 if (!strcmp(attr->name, attname)) {
152 if (p->u.relation.op[0]) {
153 if (*p->u.relation.op != '=') {
155 "Only '=' relation is supported (%s)",p->u.relation.op);
156 yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
159 yaz_log(LOG_DEBUG," - value %s <-> %s",
160 p->u.relation.value, attr->value );
161 if (!strcmp(attr->value, p->u.relation.value)) {
166 /* attribute exists, no value specified */
171 yaz_log(LOG_DEBUG, "return %d", res);
177 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
178 if (!strcmp(p->u.boolean.op,"and")) {
179 return d1_check_xpath_predicate(n, p->u.boolean.left)
180 && d1_check_xpath_predicate(n, p->u.boolean.right);
182 else if (!strcmp(p->u.boolean.op,"or")) {
183 return (d1_check_xpath_predicate(n, p->u.boolean.left)
184 || d1_check_xpath_predicate(n, p->u.boolean.right));
186 yaz_log(LOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
197 New function, looking for xpath "element" definitions in abs, by
198 tagpath, using a kind of ugly regxp search.The DFA was built while
199 parsing abs, so here we just go trough them and try to match
200 against the given tagpath. The first matching entry is returned.
204 Added support for enhanced xelm. Now [] predicates are considered
205 as well, when selecting indexing rules... (why the hell it's called
212 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
214 data1_absyn *abs = n->root->u.root.absyn;
215 data1_xpelement *xpe = abs->xp_elements;
218 struct xpath_location_step *xp;
221 char *pexpr = xmalloc(strlen(tagpath)+2);
224 sprintf (pexpr, "%s\n", tagpath);
225 yaz_log(LOG_DEBUG,"Checking tagpath %s",tagpath);
228 struct DFA_state **dfaar = xpe->dfa->states;
229 struct DFA_state *s=dfaar[0];
236 c = *pexpr++; t = s->trans; i = s->tran_no;
237 if ((c >= t->ch[0] && c <= t->ch[1]) || (!t->ch[0])) {
240 if ((s = dfaar[t->to])->rule_no &&
241 (start_line || s->rule_nno)) {
245 for (t=s->trans, i=s->tran_no; --i >= 0; t++) {
246 if ((unsigned) *p >= t->ch[0] && (unsigned) *p <= t->ch[1])
253 yaz_log(LOG_DEBUG," xpath match %s",xpe->xpath_expr);
255 yaz_log(LOG_DEBUG," xpath no match %s",xpe->xpath_expr);
260 /* we have to check the perdicates up to the root node */
263 /* find the first tag up in the node structure */
264 nn = n; while (nn && nn->which != DATA1N_tag) {
268 /* go from inside out in the node structure, while going
269 backwards trough xpath location steps ... */
270 for (i=xpe->xpath_len - 1; i>0; i--) {
272 yaz_log(LOG_DEBUG,"Checking step %d: %s on tag %s",
273 i,xp[i].part,nn->u.tag.tag);
275 if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
276 yaz_log(LOG_DEBUG," Predicates didn't match");
281 if (nn->which == DATA1N_tag) {
296 yaz_log(LOG_DEBUG,"Got it");
297 return xpe->termlists;
304 1 start element (tag)
306 3 start attr (and attr-exact)
314 Now, if there is a matching xelm described in abs, for the
315 indexed element or the attribute, then the data is handled according
316 to those definitions...
318 modified by pop, 2002-12-13
321 /* add xpath index for an attribute */
322 static void index_xpath_attr (char *tag_path, char *name, char *value,
323 char *structure, struct recExtractCtrl *p,
326 wrd->attrSet = VAL_IDXPATH;
329 wrd->string = tag_path;
330 wrd->length = strlen(tag_path);
337 wrd->length = strlen(value);
343 wrd->string = tag_path;
344 wrd->length = strlen(tag_path);
349 static void index_xpath (data1_node *n, struct recExtractCtrl *p,
350 int level, RecWord *wrd, int use)
353 char tag_path_full[1024];
356 int termlist_only = 1;
358 yaz_log(LOG_DEBUG, "index_xpath level=%d use=%d", level, use);
359 if ((!n->root->u.root.absyn) ||
360 (n->root->u.root.absyn->enable_xpath_indexing)) {
367 wrd->string = n->u.data.data;
368 wrd->length = n->u.data.len;
369 if (p->flagShowRecords)
371 printf("%*s XData:\"", (level + 1) * 4, "");
372 for (i = 0; i<wrd->length && i < 8; i++)
373 fputc (wrd->string[i], stdout);
381 /* we have to fetch the whole path to the data tag */
382 for (nn = n; nn; nn = nn->parent) {
383 if (nn->which == DATA1N_tag) {
384 size_t tlen = strlen(nn->u.tag.tag);
385 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
386 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
388 tag_path_full[flen++] = '/';
390 else if (nn->which == DATA1N_root) break;
393 tag_path_full[flen] = 0;
395 /* If we have a matching termlist... */
396 if (n->root->u.root.absyn && (tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
397 for (; tl; tl = tl->next) {
398 wrd->reg_type = *tl->structure;
399 /* this is the ! case, so structure is for the xpath index */
401 wrd->attrSet = VAL_IDXPATH;
406 /* this is just the old fashioned attribute based index */
407 wrd->attrSet = (int) (tl->att->parent->reference);
408 wrd->attrUse = tl->att->locals->local;
413 /* xpath indexing is done, if there was no termlist given,
414 or no ! in the termlist, and default indexing is enabled... */
415 if ((!xpdone) && (!termlist_only)) {
416 wrd->attrSet = VAL_IDXPATH;
425 for (nn = n; nn; nn = nn->parent)
427 if (nn->which == DATA1N_tag)
429 size_t tlen = strlen(nn->u.tag.tag);
430 if (tlen + flen > (sizeof(tag_path_full)-2))
432 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
434 tag_path_full[flen++] = '/';
436 else if (nn->which == DATA1N_root)
442 wrd->string = tag_path_full;
444 wrd->attrSet = VAL_IDXPATH;
446 if (p->flagShowRecords)
448 printf("%*s tag=", (level + 1) * 4, "");
449 for (i = 0; i<wrd->length && i < 40; i++)
450 fputc (wrd->string[i], stdout);
461 tag_path_full[flen] = 0;
463 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
464 directive, or default xpath indexing is enabled */
465 if (!(do_xpindex = 1 - termlist_only)) {
466 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
467 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
471 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
474 if (use == 1) /* only for the starting tag... */
476 #define MAX_ATTR_COUNT 50
477 data1_termlist *tll[MAX_ATTR_COUNT];
481 /* get termlists for attributes, and find out, if we have to do xpath indexing */
482 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
487 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
489 int do_xpindex = 1 - termlist_only;
491 char attr_tag_path_full[1024];
494 /* this could be cached as well */
495 sprintf (attr_tag_path_full, "@%s/%.*s",
496 xp->name, int_len, tag_path_full);
498 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
500 /* if there is a ! in the xelm termlist, or default indexing is on,
501 proceed with xpath idx */
504 for (; tl; tl = tl->next)
513 /* attribute (no value) */
516 wrd->string = xp->name;
517 wrd->length = strlen(xp->name);
523 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
525 /* attribute value exact */
526 strcpy (comb, xp->name);
528 strcat (comb, xp->value);
533 wrd->length = strlen(comb);
543 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
545 char attr_tag_path_full[1024];
549 sprintf (attr_tag_path_full, "@%s/%.*s",
550 xp->name, int_len, tag_path_full);
554 /* If there is a termlist given (=xelm directive) */
555 for (; tl; tl = tl->next)
558 /* add xpath index for the attribute */
559 index_xpath_attr (attr_tag_path_full, xp->name,
560 xp->value, tl->structure,
564 /* add attribute based index for the attribute */
567 (tl->att->parent->reference);
568 wrd->attrUse = tl->att->locals->local;
569 wrd->reg_type = *tl->structure;
570 wrd->string = xp->value;
571 wrd->length = strlen(xp->value);
577 /* if there was no termlist for the given path,
578 or the termlist didn't have a ! element, index
579 the attribute as "w" */
580 if ((!xpdone) && (!termlist_only))
582 index_xpath_attr (attr_tag_path_full, xp->name,
583 xp->value, "w", p, wrd);
592 static void index_termlist (data1_node *par, data1_node *n,
593 struct recExtractCtrl *p, int level, RecWord *wrd)
595 data1_termlist *tlist = 0;
596 data1_datatype dtype = DATA1K_string;
599 * cycle up towards the root until we find a tag with an att..
600 * this has the effect of indexing locally defined tags with
601 * the attribute of their ancestor in the record.
604 while (!par->u.tag.element)
605 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
607 if (!par || !(tlist = par->u.tag.element->termlists))
609 if (par->u.tag.element->tag)
610 dtype = par->u.tag.element->tag->kind;
612 for (; tlist; tlist = tlist->next)
616 /* consider source */
619 if (!strcmp (tlist->source, "data") && n->which == DATA1N_data)
621 wrd->string = n->u.data.data;
622 wrd->length = n->u.data.len;
624 else if (!strcmp (tlist->source, "tag") && n->which == DATA1N_tag)
626 wrd->string = n->u.tag.tag;
627 wrd->length = strlen(n->u.tag.tag);
629 else if (sscanf (tlist->source, "attr(%511[^)])", xattr) == 1 &&
630 n->which == DATA1N_tag)
632 data1_xattr *p = n->u.tag.attributes;
633 while (p && strcmp (p->name, xattr))
637 wrd->string = p->value;
638 wrd->length = strlen(p->value);
643 if (p->flagShowRecords)
646 printf("%*sIdx: [%s]", (level + 1) * 4, "",
648 printf("%s:%s [%d] %s",
649 tlist->att->parent->name,
650 tlist->att->name, tlist->att->value,
652 printf (" XData:\"");
653 for (i = 0; i<wrd->length && i < 40; i++)
654 fputc (wrd->string[i], stdout);
656 if (wrd->length > 40)
658 fputc ('\n', stdout);
662 wrd->reg_type = *tlist->structure;
663 wrd->attrSet = (int) (tlist->att->parent->reference);
664 wrd->attrUse = tlist->att->locals->local;
671 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
674 for (; n; n = n->next)
676 if (p->flagShowRecords) /* display element description to user */
678 if (n->which == DATA1N_root)
680 printf("%*s", level * 4, "");
681 printf("Record type: '%s'\n", n->u.root.type);
683 else if (n->which == DATA1N_tag)
687 printf("%*s", level * 4, "");
688 if (!(e = n->u.tag.element))
689 printf("Local tag: '%s'\n", n->u.tag.tag);
692 printf("Elm: '%s' ", e->name);
695 data1_tag *t = e->tag;
697 printf("TagNam: '%s' ", t->names->name);
700 printf("%s[%d],", t->tagset->name, t->tagset->type);
703 if (t->which == DATA1T_numeric)
704 printf("%d)", t->value.numeric);
706 printf("'%s')", t->value.string);
713 if (n->which == DATA1N_tag)
715 index_termlist (n, n, p, level, wrd);
716 /* index start tag */
717 if (n->root->u.root.absyn)
718 index_xpath (n, p, level, wrd, 1);
722 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
726 if (n->which == DATA1N_data)
728 data1_node *par = get_parent_tag(p->dh, n);
730 if (p->flagShowRecords)
732 printf("%*s", level * 4, "");
734 if (n->u.data.len > 256)
735 printf("'%.170s ... %.70s'\n", n->u.data.data,
736 n->u.data.data + n->u.data.len-70);
737 else if (n->u.data.len > 0)
738 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
744 index_termlist (par, n, p, level, wrd);
746 index_xpath (n, p, level, wrd, 1016);
749 if (n->which == DATA1N_tag)
752 index_xpath (n, p, level, wrd, 2);
755 if (p->flagShowRecords && n->which == DATA1N_root)
757 printf("%*s-------------\n\n", level * 4, "");
763 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
766 int oidtmp[OID_SIZE];
769 oe.proto = PROTO_Z3950;
770 oe.oclass = CLASS_SCHEMA;
773 oe.value = n->u.root.absyn->reference;
775 if ((oid_ent_to_oid (&oe, oidtmp)))
776 (*p->schemaAdd)(p, oidtmp);
780 return dumpkeys(n, p, 0, &wrd);
783 static int grs_extract_sub(struct grs_handlers *h, struct recExtractCtrl *p,
787 struct grs_read_info gri;
789 int oidtmp[OID_SIZE];
792 gri.readf = p->readf;
793 gri.seekf = p->seekf;
794 gri.tellf = p->tellf;
797 gri.offset = p->offset;
801 if (read_grs_type (h, &gri, p->subType, &n))
802 return RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER;
804 return RECCTRL_EXTRACT_EOF;
805 oe.proto = PROTO_Z3950;
806 oe.oclass = CLASS_SCHEMA;
808 if (!n->u.root.absyn)
809 return RECCTRL_EXTRACT_ERROR;
813 oe.value = n->u.root.absyn->reference;
814 if ((oid_ent_to_oid (&oe, oidtmp)))
815 (*p->schemaAdd)(p, oidtmp);
817 data1_concat_text(p->dh, mem, n);
819 /* ensure our data1 tree is UTF-8 */
820 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
823 data1_pr_tree (p->dh, n, stdout);
827 if (dumpkeys(n, p, 0, &wrd) < 0)
829 data1_free_tree(p->dh, n);
830 return RECCTRL_EXTRACT_ERROR_GENERIC;
832 data1_free_tree(p->dh, n);
833 return RECCTRL_EXTRACT_OK;
836 static int grs_extract(void *clientData, struct recExtractCtrl *p)
839 NMEM mem = nmem_create ();
840 struct grs_handlers *h = (struct grs_handlers *) clientData;
842 ret = grs_extract_sub(h, p, mem);
848 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
850 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c)
852 data1_esetname *eset;
858 case Z_RecordComp_simple:
859 if (c->u.simple->which != Z_ElementSetNames_generic)
860 return 26; /* only generic form supported. Fix this later */
861 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
862 c->u.simple->u.generic)))
864 yaz_log(LOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
865 return 25; /* invalid esetname */
867 yaz_log(LOG_DEBUG, "Esetname '%s' in simple compspec",
868 c->u.simple->u.generic);
871 case Z_RecordComp_complex:
872 if (c->u.complex->generic)
874 /* insert check for schema */
875 if ((p = c->u.complex->generic->elementSpec))
879 case Z_ElementSpec_elementSetName:
881 data1_getesetbyname(dh, n->u.root.absyn,
882 p->u.elementSetName)))
884 yaz_log(LOG_LOG, "Unknown esetname '%s'",
885 p->u.elementSetName);
886 return 25; /* invalid esetname */
888 yaz_log(LOG_DEBUG, "Esetname '%s' in complex compspec",
889 p->u.elementSetName);
892 case Z_ElementSpec_externalSpec:
893 if (p->u.externalSpec->which == Z_External_espec1)
895 yaz_log(LOG_DEBUG, "Got Espec-1");
896 espec = p->u.externalSpec-> u.espec1;
900 yaz_log(LOG_LOG, "Unknown external espec.");
901 return 25; /* bad. what is proper diagnostic? */
912 yaz_log(LOG_DEBUG, "Element: Espec-1 match");
913 return data1_doespec1(dh, n, espec);
917 yaz_log(LOG_DEBUG, "Element: all match");
922 /* Add Zebra info in separate namespace ...
925 <metadata xmlns="http://www.indexdata.dk/zebra/">
927 <localnumber>447</localnumber>
928 <filename>records/genera.xml</filename>
933 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
936 const char *idzebra_ns[3];
937 const char *i2 = "\n ";
938 const char *i4 = "\n ";
941 idzebra_ns[0] = "xmlns";
942 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
945 data1_mk_text (p->dh, mem, i2, top);
947 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
949 data1_mk_text (p->dh, mem, "\n", top);
951 data1_mk_text (p->dh, mem, i4, n);
953 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
957 data1_mk_text (p->dh, mem, i4, n);
958 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
960 data1_mk_text (p->dh, mem, i4, n);
961 data1_mk_tag_data_int (p->dh, n, "localnumber", p->localno, mem);
964 data1_mk_text (p->dh, mem, i4, n);
965 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
967 data1_mk_text (p->dh, mem, i2, n);
970 static int grs_retrieve(void *clientData, struct recRetrieveCtrl *p)
972 data1_node *node = 0, *onode = 0, *top;
975 int res, selected = 0;
977 struct grs_read_info gri;
979 struct grs_handlers *h = (struct grs_handlers *) clientData;
980 int requested_schema = VAL_NONE;
981 data1_marctab *marctab;
985 gri.readf = p->readf;
986 gri.seekf = p->seekf;
987 gri.tellf = p->tellf;
994 yaz_log(LOG_DEBUG, "grs_retrieve");
995 if (read_grs_type (h, &gri, p->subType, &node))
1007 data1_concat_text(p->dh, mem, node);
1009 /* ensure our data1 tree is UTF-8 */
1010 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1013 data1_pr_tree (p->dh, node, stdout);
1015 top = data1_get_root_tag (p->dh, node);
1017 yaz_log(LOG_DEBUG, "grs_retrieve: size");
1018 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1020 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1022 dnew->u.data.what = DATA1I_text;
1023 dnew->u.data.data = dnew->lbuf;
1024 sprintf(dnew->u.data.data, "%d", p->recordSize);
1025 dnew->u.data.len = strlen(dnew->u.data.data);
1028 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1029 if (tagname && p->score >= 0 &&
1030 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1032 yaz_log(LOG_DEBUG, "grs_retrieve: %s", tagname);
1033 dnew->u.data.what = DATA1I_num;
1034 dnew->u.data.data = dnew->lbuf;
1035 sprintf(dnew->u.data.data, "%d", p->score);
1036 dnew->u.data.len = strlen(dnew->u.data.data);
1039 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1040 "localControlNumber");
1041 if (tagname && p->localno > 0 &&
1042 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1044 yaz_log(LOG_DEBUG, "grs_retrieve: %s", tagname);
1045 dnew->u.data.what = DATA1I_text;
1046 dnew->u.data.data = dnew->lbuf;
1048 sprintf(dnew->u.data.data, "%d", p->localno);
1049 dnew->u.data.len = strlen(dnew->u.data.data);
1052 data1_pr_tree (p->dh, node, stdout);
1054 #if YAZ_VERSIONL >= 0x010903L
1055 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1056 p->comp->u.complex->generic &&
1057 p->comp->u.complex->generic->which == Z_Schema_oid &&
1058 p->comp->u.complex->generic->schema.oid)
1060 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1062 requested_schema = oe->value;
1065 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1066 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1068 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1070 requested_schema = oe->value;
1074 /* If schema has been specified, map if possible, then check that
1075 * we got the right one
1077 if (requested_schema != VAL_NONE)
1079 yaz_log(LOG_DEBUG, "grs_retrieve: schema mapping");
1080 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1082 if (map->target_absyn_ref == requested_schema)
1085 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1094 if (node->u.root.absyn &&
1095 requested_schema != node->u.root.absyn->reference)
1097 p->diagnostic = 238;
1103 * Does the requested format match a known syntax-mapping? (this reflects
1104 * the overlap of schema and formatting which is inherent in the MARC
1107 yaz_log(LOG_DEBUG, "grs_retrieve: syntax mapping");
1108 if (node->u.root.absyn)
1109 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1111 if (map->target_absyn_ref == p->input_format)
1114 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1123 yaz_log(LOG_DEBUG, "grs_retrieve: schemaIdentifier");
1124 if (node->u.root.absyn &&
1125 node->u.root.absyn->reference != VAL_NONE &&
1126 p->input_format == VAL_GRS1)
1130 int oidtmp[OID_SIZE];
1132 oe.proto = PROTO_Z3950;
1133 oe.oclass = CLASS_SCHEMA;
1134 oe.value = node->u.root.absyn->reference;
1136 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1139 data1_handle dh = p->dh;
1143 for (ii = oid; *ii >= 0; ii++)
1147 sprintf(p, "%d", *ii);
1150 if ((dnew = data1_mk_tag_data_wd(dh, top,
1151 "schemaIdentifier", mem)))
1153 dnew->u.data.what = DATA1I_oid;
1154 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1155 memcpy(dnew->u.data.data, tmp, p - tmp);
1156 dnew->u.data.len = p - tmp;
1161 yaz_log(LOG_DEBUG, "grs_retrieve: element spec");
1162 if (p->comp && (res = process_comp(p->dh, node, p->comp)) > 0)
1164 p->diagnostic = res;
1166 data1_free_tree(p->dh, onode);
1167 data1_free_tree(p->dh, node);
1171 else if (p->comp && !res)
1175 data1_pr_tree (p->dh, node, stdout);
1177 yaz_log(LOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1178 switch (p->output_format = (p->input_format != VAL_NONE ?
1179 p->input_format : VAL_SUTRS))
1182 zebra_xml_metadata (p, top, mem);
1185 data1_pr_tree (p->dh, node, stdout);
1189 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1191 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1193 p->diagnostic = 238;
1196 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1197 memcpy (new_buf, p->rec_buf, p->rec_len);
1198 p->rec_buf = new_buf;
1203 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1205 p->diagnostic = 238; /* not available in requested syntax */
1207 p->rec_len = (size_t) (-1);
1210 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1212 p->diagnostic = 238;
1214 p->rec_len = (size_t) (-1);
1217 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1219 p->diagnostic = 238;
1221 p->rec_len = (size_t) (-1);
1225 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1226 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1228 p->diagnostic = 238;
1231 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1232 memcpy (new_buf, p->rec_buf, p->rec_len);
1233 p->rec_buf = new_buf;
1237 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1239 p->diagnostic = 238;
1242 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1243 memcpy (new_buf, p->rec_buf, p->rec_len);
1244 p->rec_buf = new_buf;
1248 if (!node->u.root.absyn)
1250 p->diagnostic = 238;
1253 for (marctab = node->u.root.absyn->marc; marctab;
1254 marctab = marctab->next)
1255 if (marctab->reference == p->input_format)
1259 p->diagnostic = 238;
1263 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1264 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1265 selected, &p->rec_len)))
1266 p->diagnostic = 238;
1269 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1270 memcpy (new_buf, p->rec_buf, p->rec_len);
1271 p->rec_buf = new_buf;
1275 data1_free_tree(p->dh, node);
1277 data1_free_tree(p->dh, onode);
1282 static struct recType grs_type =
1291 RecType recTypeGrs = &grs_type;