1 /* $Id: recgrs.c,v 1.77 2003-04-24 22:29:52 pop 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))
70 gh->clientData = (*gh->type->init)();
72 p->clientData = gh->clientData;
73 *root = (gh->type->read)(p);
74 gh->clientData = p->clientData;
81 static void grs_add_handler (struct grs_handlers *h, RecTypeGrs t)
83 struct grs_handler *gh = (struct grs_handler *) xmalloc (sizeof(*gh));
84 gh->next = h->handlers;
91 static void *grs_init(RecType recType)
93 struct grs_handlers *h = (struct grs_handlers *) xmalloc (sizeof(*h));
96 grs_add_handler (h, recTypeGrs_sgml);
97 grs_add_handler (h, recTypeGrs_regx);
99 grs_add_handler (h, recTypeGrs_tcl);
101 grs_add_handler (h, recTypeGrs_marc);
103 grs_add_handler (h, recTypeGrs_xml);
106 grs_add_handler (h, recTypeGrs_perl);
111 static void grs_destroy(void *clientData)
113 struct grs_handlers *h = (struct grs_handlers *) clientData;
114 struct grs_handler *gh = h->handlers, *gh_next;
119 (*gh->type->destroy)(gh->clientData);
126 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p) {
134 if (p->which == XPATH_PREDICATE_RELATION) {
135 if (p->u.relation.name[0]) {
136 if (*p->u.relation.name != '@') {
138 " Only attributes (@) are supported in xelm xpath predicates");
139 logf(LOG_WARN, "predicate %s ignored", p->u.relation.name);
142 attname = p->u.relation.name + 1;
144 /* looking for the attribute with a specified name */
145 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
146 logf(LOG_DEBUG," - attribute %s <-> %s", attname, attr->name );
148 if (!strcmp(attr->name, attname)) {
149 if (p->u.relation.op[0]) {
150 if (*p->u.relation.op != '=') {
152 "Only '=' relation is supported (%s)",p->u.relation.op);
153 logf(LOG_WARN, "predicate %s ignored", p->u.relation.name);
156 logf(LOG_DEBUG," - value %s <-> %s",
157 p->u.relation.value, attr->value );
158 if (!strcmp(attr->value, p->u.relation.value)) {
163 /* attribute exists, no value specified */
173 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
174 if (!strcmp(p->u.boolean.op,"and")) {
175 return (d1_check_xpath_predicate(n, p->u.boolean.left)
176 && d1_check_xpath_predicate(n, p->u.boolean.right));
178 else if (!strcmp(p->u.boolean.op,"or")) {
179 return (d1_check_xpath_predicate(n, p->u.boolean.left)
180 || d1_check_xpath_predicate(n, p->u.boolean.right));
182 logf(LOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
193 New function, looking for xpath "element" definitions in abs, by
194 tagpath, using a kind of ugly regxp search.The DFA was built while
195 parsing abs, so here we just go trough them and try to match
196 against the given tagpath. The first matching entry is returned.
200 Added support for enhanced xelm. Now [] predicates are considered
201 as well, when selecting indexing rules... (why the hell it's called
208 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
210 data1_absyn *abs = n->root->u.root.absyn;
211 data1_xpelement *xpe = abs->xp_elements;
214 struct xpath_location_step *xp;
217 char *pexpr = xmalloc(strlen(tagpath)+2);
220 sprintf (pexpr, "%s\n", tagpath);
221 logf(LOG_DEBUG,"Checking tagpath %s",tagpath);
224 struct DFA_state **dfaar = xpe->dfa->states;
225 struct DFA_state *s=dfaar[0];
232 logf(LOG_DEBUG," - xpath %s",xpe->xpath_expr);
234 c = *pexpr++; t = s->trans; i = s->tran_no;
235 if ((c >= t->ch[0] && c <= t->ch[1]) || (!t->ch[0])) {
238 if ((s = dfaar[t->to])->rule_no &&
239 (start_line || s->rule_nno)) {
243 for (t=s->trans, i=s->tran_no; --i >= 0; t++) {
244 if ((unsigned) *p >= t->ch[0] && (unsigned) *p <= t->ch[1])
253 /* we have to check the perdicates up to the root node */
256 /* find the first tag up in the node structure */
257 nn = n; while (nn && nn->which != DATA1N_tag) {
261 /* go from inside out in the node structure, while going
262 backwards trough xpath location steps ... */
263 for (i=xpe->xpath_len - 1; i>0; i--) {
265 logf(LOG_DEBUG,"Checking step %d: %s on tag %s",
266 i,xp[i].part,nn->u.tag.tag);
268 if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
269 logf(LOG_DEBUG," Predicates didn't match");
274 if (nn->which == DATA1N_tag) {
289 logf(LOG_DEBUG,"Got it");
290 return xpe->termlists;
297 1 start element (tag)
299 3 start attr (and attr-exact)
307 Now, if there is a matching xelm described in abs, for the
308 indexed element or the attribute, then the data is handled according
309 to those definitions...
311 modified by pop, 2002-12-13
314 /* add xpath index for an attribute */
315 static void index_xpath_attr (char *tag_path, char *name, char *value,
316 char *structure, struct recExtractCtrl *p,
322 wrd->attrSet = VAL_IDXPATH;
326 wrd->length = strlen(name);
332 strlen(name) + strlen(value) < sizeof(comb)-2) {
335 strcat (comb, value);
340 wrd->length = strlen(comb);
347 wrd->attrSet = VAL_IDXPATH;
350 wrd->string = tag_path;
351 wrd->length = strlen(tag_path);
358 wrd->length = strlen(value);
364 wrd->string = tag_path;
365 wrd->length = strlen(tag_path);
370 static void index_xpath (data1_node *n, struct recExtractCtrl *p,
371 int level, RecWord *wrd, int use)
374 char tag_path_full[1024];
377 int termlist_only = 1;
379 if ((!n->root->u.root.absyn) ||
380 (n->root->u.root.absyn->enable_xpath_indexing)) {
387 wrd->string = n->u.data.data;
388 wrd->length = n->u.data.len;
389 if (p->flagShowRecords)
391 printf("%*s data=", (level + 1) * 4, "");
392 for (i = 0; i<wrd->length && i < 8; i++)
393 fputc (wrd->string[i], stdout);
401 // logf (LOG_LOG,"Index value, %s",wrd->string);
403 /* we have to fetch the whole path to the data tag */
404 for (nn = n; nn; nn = nn->parent) {
405 if (nn->which == DATA1N_tag) {
406 size_t tlen = strlen(nn->u.tag.tag);
407 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
408 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
410 tag_path_full[flen++] = '/';
412 else if (nn->which == DATA1N_root) break;
415 tag_path_full[flen] = 0;
417 /* If we have a matching termlist... */
418 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
419 for (; tl; tl = tl->next) {
420 wrd->reg_type = *tl->structure;
421 /* this is the ! case, so structure is for the xpath index */
423 wrd->attrSet = VAL_IDXPATH;
427 /* this is just the old fashioned attribute based index */
429 wrd->attrSet = (int) (tl->att->parent->reference);
430 wrd->attrUse = tl->att->locals->local;
435 /* xpath indexing is done, if there was no termlist given,
436 or no ! in the termlist, and default indexing is enabled... */
437 if ((!xpdone) && (!termlist_only)) {
438 wrd->attrSet = VAL_IDXPATH;
447 for (nn = n; nn; nn = nn->parent)
449 if (nn->which == DATA1N_tag)
451 size_t tlen = strlen(nn->u.tag.tag);
452 if (tlen + flen > (sizeof(tag_path_full)-2))
454 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
456 tag_path_full[flen++] = '/';
458 else if (nn->which == DATA1N_root)
464 wrd->string = tag_path_full;
466 wrd->attrSet = VAL_IDXPATH;
468 if (p->flagShowRecords)
470 printf("%*s tag=", (level + 1) * 4, "");
471 for (i = 0; i<wrd->length && i < 40; i++)
472 fputc (wrd->string[i], stdout);
483 tag_path_full[flen] = 0;
485 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
486 directive, or default xpath indexing is enabled */
487 if (!(do_xpindex = 1 - termlist_only)) {
488 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
489 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
493 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
496 if (use == 1) /* only for the starting tag... */
499 #define MAX_ATTR_COUNT 50
501 data1_termlist *tll[MAX_ATTR_COUNT];
505 /* get termlists for attributes, and find out, if we have to do xpath indexing */
506 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
511 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
513 int do_xpindex = 1 - termlist_only;
515 char attr_tag_path_full[1024];
518 /* this could be cached as well */
519 sprintf (attr_tag_path_full, "@%s/%.*s",
520 xp->name, int_len, tag_path_full);
522 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
524 /* if there is a ! in the xelm termlist, or default indexing is on,
525 proceed with xpath idx */
527 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
532 /* attribute (no value) */
535 wrd->string = xp->name;
536 wrd->length = strlen(xp->name);
542 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
544 /* attribute value exact */
545 strcpy (comb, xp->name);
547 strcat (comb, xp->value);
552 wrd->length = strlen(comb);
562 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
564 char attr_tag_path_full[1024];
568 sprintf (attr_tag_path_full, "@%s/%.*s",
569 xp->name, int_len, tag_path_full);
572 /* If there is a termlist given (=xelm directive) */
573 for (; tl; tl = tl->next) {
575 /* add xpath index for the attribute */
576 index_xpath_attr (attr_tag_path_full, xp->name,
577 xp->value, tl->structure, p, wrd);
580 /* add attribute based index for the attribute */
582 wrd->attrSet = (int) (tl->att->parent->reference);
583 wrd->attrUse = tl->att->locals->local;
584 wrd->reg_type = *tl->structure;
585 wrd->string = xp->value;
586 wrd->length = strlen(xp->value);
592 /* if there was no termlist for the given path,
593 or the termlist didn't have a ! element, index
594 the attribute as "w" */
595 if ((!xpdone) && (!termlist_only)) {
596 index_xpath_attr (attr_tag_path_full, xp->name, xp->value,
606 static void index_termlist (data1_node *par, data1_node *n,
607 struct recExtractCtrl *p, int level, RecWord *wrd)
609 data1_termlist *tlist = 0;
610 data1_datatype dtype = DATA1K_string;
613 * cycle up towards the root until we find a tag with an att..
614 * this has the effect of indexing locally defined tags with
615 * the attribute of their ancestor in the record.
618 while (!par->u.tag.element)
619 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
621 if (!par || !(tlist = par->u.tag.element->termlists))
623 if (par->u.tag.element->tag)
624 dtype = par->u.tag.element->tag->kind;
626 for (; tlist; tlist = tlist->next)
630 /* consider source */
633 if (!strcmp (tlist->source, "data") && n->which == DATA1N_data)
635 wrd->string = n->u.data.data;
636 wrd->length = n->u.data.len;
638 else if (!strcmp (tlist->source, "tag") && n->which == DATA1N_tag)
640 wrd->string = n->u.tag.tag;
641 wrd->length = strlen(n->u.tag.tag);
643 else if (sscanf (tlist->source, "attr(%511[^)])", xattr) == 1 &&
644 n->which == DATA1N_tag)
646 data1_xattr *p = n->u.tag.attributes;
647 while (p && strcmp (p->name, xattr))
651 wrd->string = p->value;
652 wrd->length = strlen(p->value);
657 if (p->flagShowRecords)
660 printf("%*sIdx: [%s]", (level + 1) * 4, "",
662 printf("%s:%s [%d] %s",
663 tlist->att->parent->name,
664 tlist->att->name, tlist->att->value,
667 for (i = 0; i<wrd->length && i < 40; i++)
668 fputc (wrd->string[i], stdout);
670 if (wrd->length > 40)
672 fputc ('\n', stdout);
676 wrd->reg_type = *tlist->structure;
677 wrd->attrSet = (int) (tlist->att->parent->reference);
678 wrd->attrUse = tlist->att->locals->local;
685 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
688 for (; n; n = n->next)
690 if (p->flagShowRecords) /* display element description to user */
692 if (n->which == DATA1N_root)
694 printf("%*s", level * 4, "");
695 printf("Record type: '%s'\n", n->u.root.type);
697 else if (n->which == DATA1N_tag)
701 printf("%*s", level * 4, "");
702 if (!(e = n->u.tag.element))
703 printf("Local tag: '%s'\n", n->u.tag.tag);
706 printf("Elm: '%s' ", e->name);
709 data1_tag *t = e->tag;
711 printf("TagNam: '%s' ", t->names->name);
714 printf("%s[%d],", t->tagset->name, t->tagset->type);
717 if (t->which == DATA1T_numeric)
718 printf("%d)", t->value.numeric);
720 printf("'%s')", t->value.string);
727 if (n->which == DATA1N_tag)
729 index_termlist (n, n, p, level, wrd);
730 /* index start tag */
731 assert (n->root->u.root.absyn);
732 index_xpath (n, p, level, wrd, 1);
736 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
740 if (n->which == DATA1N_data)
742 data1_node *par = get_parent_tag(p->dh, n);
744 if (p->flagShowRecords)
746 printf("%*s", level * 4, "");
748 if (n->u.data.len > 256)
749 printf("'%.240s ... %.6s'\n", n->u.data.data,
750 n->u.data.data + n->u.data.len-6);
751 else if (n->u.data.len > 0)
752 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
758 index_termlist (par, n, p, level, wrd);
760 index_xpath (n, p, level, wrd, 1016);
763 if (n->which == DATA1N_tag)
766 index_xpath (n, p, level, wrd, 2);
769 if (p->flagShowRecords && n->which == DATA1N_root)
771 printf("%*s-------------\n\n", level * 4, "");
777 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
780 int oidtmp[OID_SIZE];
783 oe.proto = PROTO_Z3950;
784 oe.oclass = CLASS_SCHEMA;
787 oe.value = n->u.root.absyn->reference;
789 if ((oid_ent_to_oid (&oe, oidtmp)))
790 (*p->schemaAdd)(p, oidtmp);
794 return dumpkeys(n, p, 0, &wrd);
797 static int grs_extract_sub(struct grs_handlers *h, struct recExtractCtrl *p,
801 struct grs_read_info gri;
803 int oidtmp[OID_SIZE];
806 gri.readf = p->readf;
807 gri.seekf = p->seekf;
808 gri.tellf = p->tellf;
811 gri.offset = p->offset;
815 if (read_grs_type (h, &gri, p->subType, &n))
816 return RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER;
818 return RECCTRL_EXTRACT_EOF;
819 oe.proto = PROTO_Z3950;
820 oe.oclass = CLASS_SCHEMA;
822 if (!n->u.root.absyn)
823 return RECCTRL_EXTRACT_ERROR;
827 oe.value = n->u.root.absyn->reference;
828 if ((oid_ent_to_oid (&oe, oidtmp)))
829 (*p->schemaAdd)(p, oidtmp);
832 /* ensure our data1 tree is UTF-8 */
833 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
836 data1_pr_tree (p->dh, n, stdout);
840 if (dumpkeys(n, p, 0, &wrd) < 0)
842 data1_free_tree(p->dh, n);
843 return RECCTRL_EXTRACT_ERROR_GENERIC;
845 data1_free_tree(p->dh, n);
846 return RECCTRL_EXTRACT_OK;
849 static int grs_extract(void *clientData, struct recExtractCtrl *p)
852 NMEM mem = nmem_create ();
853 struct grs_handlers *h = (struct grs_handlers *) clientData;
855 ret = grs_extract_sub(h, p, mem);
861 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
863 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c)
865 data1_esetname *eset;
871 case Z_RecordComp_simple:
872 if (c->u.simple->which != Z_ElementSetNames_generic)
873 return 26; /* only generic form supported. Fix this later */
874 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
875 c->u.simple->u.generic)))
877 logf(LOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
878 return 25; /* invalid esetname */
880 logf(LOG_DEBUG, "Esetname '%s' in simple compspec",
881 c->u.simple->u.generic);
884 case Z_RecordComp_complex:
885 if (c->u.complex->generic)
887 /* insert check for schema */
888 if ((p = c->u.complex->generic->elementSpec))
892 case Z_ElementSpec_elementSetName:
894 data1_getesetbyname(dh, n->u.root.absyn,
895 p->u.elementSetName)))
897 logf(LOG_LOG, "Unknown esetname '%s'",
898 p->u.elementSetName);
899 return 25; /* invalid esetname */
901 logf(LOG_DEBUG, "Esetname '%s' in complex compspec",
902 p->u.elementSetName);
905 case Z_ElementSpec_externalSpec:
906 if (p->u.externalSpec->which == Z_External_espec1)
908 logf(LOG_DEBUG, "Got Espec-1");
909 espec = p->u.externalSpec-> u.espec1;
913 logf(LOG_LOG, "Unknown external espec.");
914 return 25; /* bad. what is proper diagnostic? */
925 logf (LOG_DEBUG, "Element: Espec-1 match");
926 return data1_doespec1(dh, n, espec);
930 logf (LOG_DEBUG, "Element: all match");
935 /* Add Zebra info in separate namespace ...
938 <metadata xmlns="http://www.indexdata.dk/zebra/">
940 <localnumber>447</localnumber>
941 <filename>records/genera.xml</filename>
946 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
949 const char *idzebra_ns[3];
950 const char *i2 = "\n ";
951 const char *i4 = "\n ";
954 idzebra_ns[0] = "xmlns";
955 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
958 data1_mk_text (p->dh, mem, i2, top);
960 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
962 data1_mk_text (p->dh, mem, "\n", top);
964 data1_mk_text (p->dh, mem, i4, n);
966 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
970 data1_mk_text (p->dh, mem, i4, n);
971 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
973 data1_mk_text (p->dh, mem, i4, n);
974 data1_mk_tag_data_int (p->dh, n, "localnumber", p->localno, mem);
977 data1_mk_text (p->dh, mem, i4, n);
978 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
980 data1_mk_text (p->dh, mem, i2, n);
983 static int grs_retrieve(void *clientData, struct recRetrieveCtrl *p)
985 data1_node *node = 0, *onode = 0, *top;
988 int res, selected = 0;
990 struct grs_read_info gri;
992 struct grs_handlers *h = (struct grs_handlers *) clientData;
993 int requested_schema = VAL_NONE;
994 data1_marctab *marctab;
998 gri.readf = p->readf;
999 gri.seekf = p->seekf;
1000 gri.tellf = p->tellf;
1007 logf (LOG_DEBUG, "grs_retrieve");
1008 if (read_grs_type (h, &gri, p->subType, &node))
1020 /* ensure our data1 tree is UTF-8 */
1021 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1024 data1_pr_tree (p->dh, node, stdout);
1026 top = data1_get_root_tag (p->dh, node);
1028 logf (LOG_DEBUG, "grs_retrieve: size");
1029 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1031 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1033 dnew->u.data.what = DATA1I_text;
1034 dnew->u.data.data = dnew->lbuf;
1035 sprintf(dnew->u.data.data, "%d", p->recordSize);
1036 dnew->u.data.len = strlen(dnew->u.data.data);
1039 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1040 if (tagname && p->score >= 0 &&
1041 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1043 logf (LOG_DEBUG, "grs_retrieve: %s", tagname);
1044 dnew->u.data.what = DATA1I_num;
1045 dnew->u.data.data = dnew->lbuf;
1046 sprintf(dnew->u.data.data, "%d", p->score);
1047 dnew->u.data.len = strlen(dnew->u.data.data);
1050 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1051 "localControlNumber");
1052 if (tagname && p->localno > 0 &&
1053 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1055 logf (LOG_DEBUG, "grs_retrieve: %s", tagname);
1056 dnew->u.data.what = DATA1I_text;
1057 dnew->u.data.data = dnew->lbuf;
1059 sprintf(dnew->u.data.data, "%d", p->localno);
1060 dnew->u.data.len = strlen(dnew->u.data.data);
1063 data1_pr_tree (p->dh, node, stdout);
1065 #if YAZ_VERSIONL >= 0x010903L
1066 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1067 p->comp->u.complex->generic &&
1068 p->comp->u.complex->generic->which == Z_Schema_oid &&
1069 p->comp->u.complex->generic->schema.oid)
1071 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1073 requested_schema = oe->value;
1076 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1077 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1079 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1081 requested_schema = oe->value;
1085 /* If schema has been specified, map if possible, then check that
1086 * we got the right one
1088 if (requested_schema != VAL_NONE)
1090 logf (LOG_DEBUG, "grs_retrieve: schema mapping");
1091 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1093 if (map->target_absyn_ref == requested_schema)
1096 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1105 if (node->u.root.absyn &&
1106 requested_schema != node->u.root.absyn->reference)
1108 p->diagnostic = 238;
1114 * Does the requested format match a known syntax-mapping? (this reflects
1115 * the overlap of schema and formatting which is inherent in the MARC
1118 yaz_log (LOG_DEBUG, "grs_retrieve: syntax mapping");
1119 if (node->u.root.absyn)
1120 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1122 if (map->target_absyn_ref == p->input_format)
1125 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1134 yaz_log (LOG_DEBUG, "grs_retrieve: schemaIdentifier");
1135 if (node->u.root.absyn &&
1136 node->u.root.absyn->reference != VAL_NONE &&
1137 p->input_format == VAL_GRS1)
1141 int oidtmp[OID_SIZE];
1143 oe.proto = PROTO_Z3950;
1144 oe.oclass = CLASS_SCHEMA;
1145 oe.value = node->u.root.absyn->reference;
1147 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1150 data1_handle dh = p->dh;
1154 for (ii = oid; *ii >= 0; ii++)
1158 sprintf(p, "%d", *ii);
1161 if ((dnew = data1_mk_tag_data_wd(dh, top,
1162 "schemaIdentifier", mem)))
1164 dnew->u.data.what = DATA1I_oid;
1165 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1166 memcpy(dnew->u.data.data, tmp, p - tmp);
1167 dnew->u.data.len = p - tmp;
1172 logf (LOG_DEBUG, "grs_retrieve: element spec");
1173 if (p->comp && (res = process_comp(p->dh, node, p->comp)) > 0)
1175 p->diagnostic = res;
1177 data1_free_tree(p->dh, onode);
1178 data1_free_tree(p->dh, node);
1182 else if (p->comp && !res)
1186 data1_pr_tree (p->dh, node, stdout);
1188 logf (LOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1189 switch (p->output_format = (p->input_format != VAL_NONE ?
1190 p->input_format : VAL_SUTRS))
1193 zebra_xml_metadata (p, top, mem);
1196 data1_pr_tree (p->dh, node, stdout);
1200 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1202 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1204 p->diagnostic = 238;
1207 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1208 memcpy (new_buf, p->rec_buf, p->rec_len);
1209 p->rec_buf = new_buf;
1214 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1216 p->diagnostic = 238; /* not available in requested syntax */
1218 p->rec_len = (size_t) (-1);
1221 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1223 p->diagnostic = 238;
1225 p->rec_len = (size_t) (-1);
1228 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1230 p->diagnostic = 238;
1232 p->rec_len = (size_t) (-1);
1236 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1237 if (!(p->rec_buf = data1_nodetobuf(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 (!(p->rec_buf = data1_nodetosoif(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;
1259 if (!node->u.root.absyn)
1261 p->diagnostic = 238;
1264 for (marctab = node->u.root.absyn->marc; marctab;
1265 marctab = marctab->next)
1266 if (marctab->reference == p->input_format)
1270 p->diagnostic = 238;
1274 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1275 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1276 selected, &p->rec_len)))
1277 p->diagnostic = 238;
1280 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1281 memcpy (new_buf, p->rec_buf, p->rec_len);
1282 p->rec_buf = new_buf;
1286 data1_free_tree(p->dh, node);
1288 data1_free_tree(p->dh, onode);
1293 static struct recType grs_type =
1302 RecType recTypeGrs = &grs_type;