1 /* $Id: recgrs.c,v 1.88 2004-08-06 13:36:23 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);
110 grs_add_handler (h, recTypeGrs_danbib);
114 static void grs_destroy(void *clientData)
116 struct grs_handlers *h = (struct grs_handlers *) clientData;
117 struct grs_handler *gh = h->handlers, *gh_next;
122 (*gh->type->destroy)(gh->clientData);
129 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
138 if (p->which == XPATH_PREDICATE_RELATION) {
139 if (p->u.relation.name[0]) {
140 if (*p->u.relation.name != '@') {
142 " Only attributes (@) are supported in xelm xpath predicates");
143 yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
146 attname = p->u.relation.name + 1;
148 /* looking for the attribute with a specified name */
149 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
150 yaz_log(LOG_DEBUG," - attribute %s <-> %s", attname, attr->name );
152 if (!strcmp(attr->name, attname)) {
153 if (p->u.relation.op[0]) {
154 if (*p->u.relation.op != '=') {
156 "Only '=' relation is supported (%s)",p->u.relation.op);
157 yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
160 yaz_log(LOG_DEBUG," - value %s <-> %s",
161 p->u.relation.value, attr->value );
162 if (!strcmp(attr->value, p->u.relation.value)) {
167 /* attribute exists, no value specified */
172 yaz_log(LOG_DEBUG, "return %d", res);
178 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
179 if (!strcmp(p->u.boolean.op,"and")) {
180 return d1_check_xpath_predicate(n, p->u.boolean.left)
181 && d1_check_xpath_predicate(n, p->u.boolean.right);
183 else if (!strcmp(p->u.boolean.op,"or")) {
184 return (d1_check_xpath_predicate(n, p->u.boolean.left)
185 || d1_check_xpath_predicate(n, p->u.boolean.right));
187 yaz_log(LOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
198 New function, looking for xpath "element" definitions in abs, by
199 tagpath, using a kind of ugly regxp search.The DFA was built while
200 parsing abs, so here we just go trough them and try to match
201 against the given tagpath. The first matching entry is returned.
205 Added support for enhanced xelm. Now [] predicates are considered
206 as well, when selecting indexing rules... (why the hell it's called
213 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
215 data1_absyn *abs = n->root->u.root.absyn;
216 data1_xpelement *xpe = abs->xp_elements;
219 struct xpath_location_step *xp;
222 char *pexpr = xmalloc(strlen(tagpath)+2);
225 sprintf (pexpr, "%s\n", tagpath);
226 yaz_log(LOG_DEBUG,"Checking tagpath %s",tagpath);
229 struct DFA_state **dfaar = xpe->dfa->states;
230 struct DFA_state *s=dfaar[0];
237 c = *pexpr++; t = s->trans; i = s->tran_no;
238 if ((c >= t->ch[0] && c <= t->ch[1]) || (!t->ch[0])) {
241 if ((s = dfaar[t->to])->rule_no &&
242 (start_line || s->rule_nno)) {
246 for (t=s->trans, i=s->tran_no; --i >= 0; t++) {
247 if ((unsigned) *p >= t->ch[0] && (unsigned) *p <= t->ch[1])
254 yaz_log(LOG_DEBUG," xpath match %s",xpe->xpath_expr);
256 yaz_log(LOG_DEBUG," xpath no match %s",xpe->xpath_expr);
261 /* we have to check the perdicates up to the root node */
264 /* find the first tag up in the node structure */
265 nn = n; while (nn && nn->which != DATA1N_tag) {
269 /* go from inside out in the node structure, while going
270 backwards trough xpath location steps ... */
271 for (i=xpe->xpath_len - 1; i>0; i--) {
273 yaz_log(LOG_DEBUG,"Checking step %d: %s on tag %s",
274 i,xp[i].part,nn->u.tag.tag);
276 if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
277 yaz_log(LOG_DEBUG," Predicates didn't match");
282 if (nn->which == DATA1N_tag) {
297 yaz_log(LOG_DEBUG,"Got it");
298 return xpe->termlists;
305 1 start element (tag)
307 3 start attr (and attr-exact)
315 Now, if there is a matching xelm described in abs, for the
316 indexed element or the attribute, then the data is handled according
317 to those definitions...
319 modified by pop, 2002-12-13
322 /* add xpath index for an attribute */
323 static void index_xpath_attr (char *tag_path, char *name, char *value,
324 char *structure, struct recExtractCtrl *p,
327 wrd->attrSet = VAL_IDXPATH;
330 wrd->string = tag_path;
331 wrd->length = strlen(tag_path);
338 wrd->length = strlen(value);
344 wrd->string = tag_path;
345 wrd->length = strlen(tag_path);
350 static void index_xpath (data1_node *n, struct recExtractCtrl *p,
351 int level, RecWord *wrd, int use)
354 char tag_path_full[1024];
357 int termlist_only = 1;
359 yaz_log(LOG_DEBUG, "index_xpath level=%d use=%d", level, use);
360 if ((!n->root->u.root.absyn) ||
361 (n->root->u.root.absyn->enable_xpath_indexing)) {
368 wrd->string = n->u.data.data;
369 wrd->length = n->u.data.len;
370 if (p->flagShowRecords)
372 printf("%*s XData:\"", (level + 1) * 4, "");
373 for (i = 0; i<wrd->length && i < 8; i++)
374 fputc (wrd->string[i], stdout);
382 /* we have to fetch the whole path to the data tag */
383 for (nn = n; nn; nn = nn->parent) {
384 if (nn->which == DATA1N_tag) {
385 size_t tlen = strlen(nn->u.tag.tag);
386 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
387 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
389 tag_path_full[flen++] = '/';
391 else if (nn->which == DATA1N_root) break;
394 tag_path_full[flen] = 0;
396 /* If we have a matching termlist... */
397 if (n->root->u.root.absyn && (tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
398 for (; tl; tl = tl->next) {
399 wrd->reg_type = *tl->structure;
400 /* this is the ! case, so structure is for the xpath index */
402 wrd->attrSet = VAL_IDXPATH;
407 /* this is just the old fashioned attribute based index */
408 wrd->attrSet = (int) (tl->att->parent->reference);
409 wrd->attrUse = tl->att->locals->local;
414 /* xpath indexing is done, if there was no termlist given,
415 or no ! in the termlist, and default indexing is enabled... */
416 if ((!xpdone) && (!termlist_only)) {
417 wrd->attrSet = VAL_IDXPATH;
426 for (nn = n; nn; nn = nn->parent)
428 if (nn->which == DATA1N_tag)
430 size_t tlen = strlen(nn->u.tag.tag);
431 if (tlen + flen > (sizeof(tag_path_full)-2))
433 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
435 tag_path_full[flen++] = '/';
437 else if (nn->which == DATA1N_root)
443 wrd->string = tag_path_full;
445 wrd->attrSet = VAL_IDXPATH;
447 if (p->flagShowRecords)
449 printf("%*s tag=", (level + 1) * 4, "");
450 for (i = 0; i<wrd->length && i < 40; i++)
451 fputc (wrd->string[i], stdout);
462 tag_path_full[flen] = 0;
464 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
465 directive, or default xpath indexing is enabled */
466 if (!(do_xpindex = 1 - termlist_only)) {
467 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
468 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
472 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
475 if (use == 1) /* only for the starting tag... */
477 #define MAX_ATTR_COUNT 50
478 data1_termlist *tll[MAX_ATTR_COUNT];
482 /* get termlists for attributes, and find out, if we have to do xpath indexing */
483 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
488 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
490 int do_xpindex = 1 - termlist_only;
492 char attr_tag_path_full[1024];
495 /* this could be cached as well */
496 sprintf (attr_tag_path_full, "@%s/%.*s",
497 xp->name, int_len, tag_path_full);
499 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
501 /* if there is a ! in the xelm termlist, or default indexing is on,
502 proceed with xpath idx */
505 for (; tl; tl = tl->next)
514 /* attribute (no value) */
517 wrd->string = xp->name;
518 wrd->length = strlen(xp->name);
524 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
526 /* attribute value exact */
527 strcpy (comb, xp->name);
529 strcat (comb, xp->value);
534 wrd->length = strlen(comb);
544 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
546 char attr_tag_path_full[1024];
550 sprintf (attr_tag_path_full, "@%s/%.*s",
551 xp->name, int_len, tag_path_full);
555 /* If there is a termlist given (=xelm directive) */
556 for (; tl; tl = tl->next)
559 /* add xpath index for the attribute */
560 index_xpath_attr (attr_tag_path_full, xp->name,
561 xp->value, tl->structure,
565 /* add attribute based index for the attribute */
568 (tl->att->parent->reference);
569 wrd->attrUse = tl->att->locals->local;
570 wrd->reg_type = *tl->structure;
571 wrd->string = xp->value;
572 wrd->length = strlen(xp->value);
578 /* if there was no termlist for the given path,
579 or the termlist didn't have a ! element, index
580 the attribute as "w" */
581 if ((!xpdone) && (!termlist_only))
583 index_xpath_attr (attr_tag_path_full, xp->name,
584 xp->value, "w", p, wrd);
593 static void index_termlist (data1_node *par, data1_node *n,
594 struct recExtractCtrl *p, int level, RecWord *wrd)
596 data1_termlist *tlist = 0;
597 data1_datatype dtype = DATA1K_string;
600 * cycle up towards the root until we find a tag with an att..
601 * this has the effect of indexing locally defined tags with
602 * the attribute of their ancestor in the record.
605 while (!par->u.tag.element)
606 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
608 if (!par || !(tlist = par->u.tag.element->termlists))
610 if (par->u.tag.element->tag)
611 dtype = par->u.tag.element->tag->kind;
613 for (; tlist; tlist = tlist->next)
617 /* consider source */
620 if (!strcmp (tlist->source, "data") && n->which == DATA1N_data)
622 wrd->string = n->u.data.data;
623 wrd->length = n->u.data.len;
625 else if (!strcmp (tlist->source, "tag") && n->which == DATA1N_tag)
627 wrd->string = n->u.tag.tag;
628 wrd->length = strlen(n->u.tag.tag);
630 else if (sscanf (tlist->source, "attr(%511[^)])", xattr) == 1 &&
631 n->which == DATA1N_tag)
633 data1_xattr *p = n->u.tag.attributes;
634 while (p && strcmp (p->name, xattr))
638 wrd->string = p->value;
639 wrd->length = strlen(p->value);
644 if (p->flagShowRecords)
647 printf("%*sIdx: [%s]", (level + 1) * 4, "",
649 printf("%s:%s [%d] %s",
650 tlist->att->parent->name,
651 tlist->att->name, tlist->att->value,
653 printf (" XData:\"");
654 for (i = 0; i<wrd->length && i < 40; i++)
655 fputc (wrd->string[i], stdout);
657 if (wrd->length > 40)
659 fputc ('\n', stdout);
663 wrd->reg_type = *tlist->structure;
664 wrd->attrSet = (int) (tlist->att->parent->reference);
665 wrd->attrUse = tlist->att->locals->local;
672 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
675 for (; n; n = n->next)
677 if (p->flagShowRecords) /* display element description to user */
679 if (n->which == DATA1N_root)
681 printf("%*s", level * 4, "");
682 printf("Record type: '%s'\n", n->u.root.type);
684 else if (n->which == DATA1N_tag)
688 printf("%*s", level * 4, "");
689 if (!(e = n->u.tag.element))
690 printf("Local tag: '%s'\n", n->u.tag.tag);
693 printf("Elm: '%s' ", e->name);
696 data1_tag *t = e->tag;
698 printf("TagNam: '%s' ", t->names->name);
701 printf("%s[%d],", t->tagset->name, t->tagset->type);
704 if (t->which == DATA1T_numeric)
705 printf("%d)", t->value.numeric);
707 printf("'%s')", t->value.string);
714 if (n->which == DATA1N_tag)
716 index_termlist (n, n, p, level, wrd);
717 /* index start tag */
718 if (n->root->u.root.absyn)
719 index_xpath (n, p, level, wrd, 1);
723 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
727 if (n->which == DATA1N_data)
729 data1_node *par = get_parent_tag(p->dh, n);
731 if (p->flagShowRecords)
733 printf("%*s", level * 4, "");
735 if (n->u.data.len > 256)
736 printf("'%.170s ... %.70s'\n", n->u.data.data,
737 n->u.data.data + n->u.data.len-70);
738 else if (n->u.data.len > 0)
739 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
745 index_termlist (par, n, p, level, wrd);
747 index_xpath (n, p, level, wrd, 1016);
750 if (n->which == DATA1N_tag)
753 index_xpath (n, p, level, wrd, 2);
756 if (p->flagShowRecords && n->which == DATA1N_root)
758 printf("%*s-------------\n\n", level * 4, "");
764 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
767 int oidtmp[OID_SIZE];
770 oe.proto = PROTO_Z3950;
771 oe.oclass = CLASS_SCHEMA;
774 oe.value = n->u.root.absyn->reference;
776 if ((oid_ent_to_oid (&oe, oidtmp)))
777 (*p->schemaAdd)(p, oidtmp);
781 return dumpkeys(n, p, 0, &wrd);
784 static int grs_extract_sub(struct grs_handlers *h, struct recExtractCtrl *p,
788 struct grs_read_info gri;
790 int oidtmp[OID_SIZE];
793 gri.readf = p->readf;
794 gri.seekf = p->seekf;
795 gri.tellf = p->tellf;
798 gri.offset = p->offset;
802 if (read_grs_type (h, &gri, p->subType, &n))
803 return RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER;
805 return RECCTRL_EXTRACT_EOF;
806 oe.proto = PROTO_Z3950;
807 oe.oclass = CLASS_SCHEMA;
809 if (!n->u.root.absyn)
810 return RECCTRL_EXTRACT_ERROR;
814 oe.value = n->u.root.absyn->reference;
815 if ((oid_ent_to_oid (&oe, oidtmp)))
816 (*p->schemaAdd)(p, oidtmp);
818 data1_concat_text(p->dh, mem, n);
820 /* ensure our data1 tree is UTF-8 */
821 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
824 data1_pr_tree (p->dh, n, stdout);
828 if (dumpkeys(n, p, 0, &wrd) < 0)
830 data1_free_tree(p->dh, n);
831 return RECCTRL_EXTRACT_ERROR_GENERIC;
833 data1_free_tree(p->dh, n);
834 return RECCTRL_EXTRACT_OK;
837 static int grs_extract(void *clientData, struct recExtractCtrl *p)
840 NMEM mem = nmem_create ();
841 struct grs_handlers *h = (struct grs_handlers *) clientData;
843 ret = grs_extract_sub(h, p, mem);
849 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
851 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c)
853 data1_esetname *eset;
859 case Z_RecordComp_simple:
860 if (c->u.simple->which != Z_ElementSetNames_generic)
861 return 26; /* only generic form supported. Fix this later */
862 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
863 c->u.simple->u.generic)))
865 yaz_log(LOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
866 return 25; /* invalid esetname */
868 yaz_log(LOG_DEBUG, "Esetname '%s' in simple compspec",
869 c->u.simple->u.generic);
872 case Z_RecordComp_complex:
873 if (c->u.complex->generic)
875 /* insert check for schema */
876 if ((p = c->u.complex->generic->elementSpec))
880 case Z_ElementSpec_elementSetName:
882 data1_getesetbyname(dh, n->u.root.absyn,
883 p->u.elementSetName)))
885 yaz_log(LOG_LOG, "Unknown esetname '%s'",
886 p->u.elementSetName);
887 return 25; /* invalid esetname */
889 yaz_log(LOG_DEBUG, "Esetname '%s' in complex compspec",
890 p->u.elementSetName);
893 case Z_ElementSpec_externalSpec:
894 if (p->u.externalSpec->which == Z_External_espec1)
896 yaz_log(LOG_DEBUG, "Got Espec-1");
897 espec = p->u.externalSpec-> u.espec1;
901 yaz_log(LOG_LOG, "Unknown external espec.");
902 return 25; /* bad. what is proper diagnostic? */
913 yaz_log(LOG_DEBUG, "Element: Espec-1 match");
914 return data1_doespec1(dh, n, espec);
918 yaz_log(LOG_DEBUG, "Element: all match");
923 /* Add Zebra info in separate namespace ...
926 <metadata xmlns="http://www.indexdata.dk/zebra/">
928 <localnumber>447</localnumber>
929 <filename>records/genera.xml</filename>
934 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
937 const char *idzebra_ns[3];
938 const char *i2 = "\n ";
939 const char *i4 = "\n ";
942 idzebra_ns[0] = "xmlns";
943 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
946 data1_mk_text (p->dh, mem, i2, top);
948 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
950 data1_mk_text (p->dh, mem, "\n", top);
952 data1_mk_text (p->dh, mem, i4, n);
954 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
958 data1_mk_text (p->dh, mem, i4, n);
959 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
961 data1_mk_text (p->dh, mem, i4, n);
962 data1_mk_tag_data_zint (p->dh, n, "localnumber", p->localno, mem);
965 data1_mk_text (p->dh, mem, i4, n);
966 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
968 data1_mk_text (p->dh, mem, i2, n);
971 static int grs_retrieve(void *clientData, struct recRetrieveCtrl *p)
973 data1_node *node = 0, *onode = 0, *top;
976 int res, selected = 0;
978 struct grs_read_info gri;
980 struct grs_handlers *h = (struct grs_handlers *) clientData;
981 int requested_schema = VAL_NONE;
982 data1_marctab *marctab;
986 gri.readf = p->readf;
987 gri.seekf = p->seekf;
988 gri.tellf = p->tellf;
995 yaz_log(LOG_DEBUG, "grs_retrieve");
996 if (read_grs_type (h, &gri, p->subType, &node))
1008 data1_concat_text(p->dh, mem, node);
1010 /* ensure our data1 tree is UTF-8 */
1011 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1014 data1_pr_tree (p->dh, node, stdout);
1016 top = data1_get_root_tag (p->dh, node);
1018 yaz_log(LOG_DEBUG, "grs_retrieve: size");
1019 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1021 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1023 dnew->u.data.what = DATA1I_text;
1024 dnew->u.data.data = dnew->lbuf;
1025 sprintf(dnew->u.data.data, "%d", p->recordSize);
1026 dnew->u.data.len = strlen(dnew->u.data.data);
1029 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1030 if (tagname && p->score >= 0 &&
1031 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1033 yaz_log(LOG_DEBUG, "grs_retrieve: %s", tagname);
1034 dnew->u.data.what = DATA1I_num;
1035 dnew->u.data.data = dnew->lbuf;
1036 sprintf(dnew->u.data.data, "%d", p->score);
1037 dnew->u.data.len = strlen(dnew->u.data.data);
1040 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1041 "localControlNumber");
1042 if (tagname && p->localno > 0 &&
1043 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1045 yaz_log(LOG_DEBUG, "grs_retrieve: %s", tagname);
1046 dnew->u.data.what = DATA1I_text;
1047 dnew->u.data.data = dnew->lbuf;
1049 sprintf(dnew->u.data.data, ZINT_FORMAT, p->localno);
1050 dnew->u.data.len = strlen(dnew->u.data.data);
1053 data1_pr_tree (p->dh, node, stdout);
1055 #if YAZ_VERSIONL >= 0x010903L
1056 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1057 p->comp->u.complex->generic &&
1058 p->comp->u.complex->generic->which == Z_Schema_oid &&
1059 p->comp->u.complex->generic->schema.oid)
1061 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1063 requested_schema = oe->value;
1066 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1067 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1069 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1071 requested_schema = oe->value;
1075 /* If schema has been specified, map if possible, then check that
1076 * we got the right one
1078 if (requested_schema != VAL_NONE)
1080 yaz_log(LOG_DEBUG, "grs_retrieve: schema mapping");
1081 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1083 if (map->target_absyn_ref == requested_schema)
1086 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1095 if (node->u.root.absyn &&
1096 requested_schema != node->u.root.absyn->reference)
1098 p->diagnostic = 238;
1104 * Does the requested format match a known syntax-mapping? (this reflects
1105 * the overlap of schema and formatting which is inherent in the MARC
1108 yaz_log(LOG_DEBUG, "grs_retrieve: syntax mapping");
1109 if (node->u.root.absyn)
1110 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1112 if (map->target_absyn_ref == p->input_format)
1115 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1124 yaz_log(LOG_DEBUG, "grs_retrieve: schemaIdentifier");
1125 if (node->u.root.absyn &&
1126 node->u.root.absyn->reference != VAL_NONE &&
1127 p->input_format == VAL_GRS1)
1131 int oidtmp[OID_SIZE];
1133 oe.proto = PROTO_Z3950;
1134 oe.oclass = CLASS_SCHEMA;
1135 oe.value = node->u.root.absyn->reference;
1137 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1140 data1_handle dh = p->dh;
1144 for (ii = oid; *ii >= 0; ii++)
1148 sprintf(p, "%d", *ii);
1151 if ((dnew = data1_mk_tag_data_wd(dh, top,
1152 "schemaIdentifier", mem)))
1154 dnew->u.data.what = DATA1I_oid;
1155 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1156 memcpy(dnew->u.data.data, tmp, p - tmp);
1157 dnew->u.data.len = p - tmp;
1162 yaz_log(LOG_DEBUG, "grs_retrieve: element spec");
1163 if (p->comp && (res = process_comp(p->dh, node, p->comp)) > 0)
1165 p->diagnostic = res;
1167 data1_free_tree(p->dh, onode);
1168 data1_free_tree(p->dh, node);
1172 else if (p->comp && !res)
1176 data1_pr_tree (p->dh, node, stdout);
1178 yaz_log(LOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1179 switch (p->output_format = (p->input_format != VAL_NONE ?
1180 p->input_format : VAL_SUTRS))
1183 zebra_xml_metadata (p, top, mem);
1186 data1_pr_tree (p->dh, node, stdout);
1190 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1192 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1194 p->diagnostic = 238;
1197 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1198 memcpy (new_buf, p->rec_buf, p->rec_len);
1199 p->rec_buf = new_buf;
1204 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1206 p->diagnostic = 238; /* not available in requested syntax */
1208 p->rec_len = (size_t) (-1);
1211 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1213 p->diagnostic = 238;
1215 p->rec_len = (size_t) (-1);
1218 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1220 p->diagnostic = 238;
1222 p->rec_len = (size_t) (-1);
1226 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1227 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1229 p->diagnostic = 238;
1232 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1233 memcpy (new_buf, p->rec_buf, p->rec_len);
1234 p->rec_buf = new_buf;
1238 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1240 p->diagnostic = 238;
1243 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1244 memcpy (new_buf, p->rec_buf, p->rec_len);
1245 p->rec_buf = new_buf;
1249 if (!node->u.root.absyn)
1251 p->diagnostic = 238;
1254 for (marctab = node->u.root.absyn->marc; marctab;
1255 marctab = marctab->next)
1256 if (marctab->reference == p->input_format)
1260 p->diagnostic = 238;
1264 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1265 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1266 selected, &p->rec_len)))
1267 p->diagnostic = 238;
1270 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1271 memcpy (new_buf, p->rec_buf, p->rec_len);
1272 p->rec_buf = new_buf;
1276 data1_free_tree(p->dh, node);
1278 data1_free_tree(p->dh, onode);
1283 static struct recType grs_type =
1292 RecType recTypeGrs = &grs_type;