1 /* $Id: recgrs.c,v 1.83 2003-09-16 12:18:24 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 logf(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 logf(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 logf(LOG_WARN, "predicate %s ignored", p->u.relation.name);
159 logf(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 */
176 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
177 if (!strcmp(p->u.boolean.op,"and")) {
178 return d1_check_xpath_predicate(n, p->u.boolean.left)
179 && d1_check_xpath_predicate(n, p->u.boolean.right);
181 else if (!strcmp(p->u.boolean.op,"or")) {
182 return (d1_check_xpath_predicate(n, p->u.boolean.left)
183 || d1_check_xpath_predicate(n, p->u.boolean.right));
185 logf(LOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
196 New function, looking for xpath "element" definitions in abs, by
197 tagpath, using a kind of ugly regxp search.The DFA was built while
198 parsing abs, so here we just go trough them and try to match
199 against the given tagpath. The first matching entry is returned.
203 Added support for enhanced xelm. Now [] predicates are considered
204 as well, when selecting indexing rules... (why the hell it's called
211 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
213 data1_absyn *abs = n->root->u.root.absyn;
214 data1_xpelement *xpe = abs->xp_elements;
217 struct xpath_location_step *xp;
220 char *pexpr = xmalloc(strlen(tagpath)+2);
223 sprintf (pexpr, "%s\n", tagpath);
224 logf(LOG_DEBUG,"Checking tagpath %s",tagpath);
227 struct DFA_state **dfaar = xpe->dfa->states;
228 struct DFA_state *s=dfaar[0];
235 logf(LOG_DEBUG," - xpath %s",xpe->xpath_expr);
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])
256 /* we have to check the perdicates up to the root node */
259 /* find the first tag up in the node structure */
260 nn = n; while (nn && nn->which != DATA1N_tag) {
264 /* go from inside out in the node structure, while going
265 backwards trough xpath location steps ... */
266 for (i=xpe->xpath_len - 1; i>0; i--) {
268 logf(LOG_DEBUG,"Checking step %d: %s on tag %s",
269 i,xp[i].part,nn->u.tag.tag);
271 if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
272 logf(LOG_DEBUG," Predicates didn't match");
277 if (nn->which == DATA1N_tag) {
292 logf(LOG_DEBUG,"Got it");
293 return xpe->termlists;
300 1 start element (tag)
302 3 start attr (and attr-exact)
310 Now, if there is a matching xelm described in abs, for the
311 indexed element or the attribute, then the data is handled according
312 to those definitions...
314 modified by pop, 2002-12-13
317 /* add xpath index for an attribute */
318 static void index_xpath_attr (char *tag_path, char *name, char *value,
319 char *structure, struct recExtractCtrl *p,
322 wrd->attrSet = VAL_IDXPATH;
325 wrd->string = tag_path;
326 wrd->length = strlen(tag_path);
333 wrd->length = strlen(value);
339 wrd->string = tag_path;
340 wrd->length = strlen(tag_path);
345 static void index_xpath (data1_node *n, struct recExtractCtrl *p,
346 int level, RecWord *wrd, int use)
349 char tag_path_full[1024];
352 int termlist_only = 1;
354 if ((!n->root->u.root.absyn) ||
355 (n->root->u.root.absyn->enable_xpath_indexing)) {
362 wrd->string = n->u.data.data;
363 wrd->length = n->u.data.len;
364 if (p->flagShowRecords)
366 printf("%*s XData:\"", (level + 1) * 4, "");
367 for (i = 0; i<wrd->length && i < 8; i++)
368 fputc (wrd->string[i], stdout);
376 // logf (LOG_LOG,"Index value, %s",wrd->string);
378 /* we have to fetch the whole path to the data tag */
379 for (nn = n; nn; nn = nn->parent) {
380 if (nn->which == DATA1N_tag) {
381 size_t tlen = strlen(nn->u.tag.tag);
382 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
383 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
385 tag_path_full[flen++] = '/';
387 else if (nn->which == DATA1N_root) break;
390 tag_path_full[flen] = 0;
392 /* If we have a matching termlist... */
393 if (n->root->u.root.absyn && (tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
394 for (; tl; tl = tl->next) {
395 wrd->reg_type = *tl->structure;
396 /* this is the ! case, so structure is for the xpath index */
398 wrd->attrSet = VAL_IDXPATH;
402 /* this is just the old fashioned attribute based index */
404 wrd->attrSet = (int) (tl->att->parent->reference);
405 wrd->attrUse = tl->att->locals->local;
410 /* xpath indexing is done, if there was no termlist given,
411 or no ! in the termlist, and default indexing is enabled... */
412 if ((!xpdone) && (!termlist_only)) {
413 wrd->attrSet = VAL_IDXPATH;
422 for (nn = n; nn; nn = nn->parent)
424 if (nn->which == DATA1N_tag)
426 size_t tlen = strlen(nn->u.tag.tag);
427 if (tlen + flen > (sizeof(tag_path_full)-2))
429 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
431 tag_path_full[flen++] = '/';
433 else if (nn->which == DATA1N_root)
439 wrd->string = tag_path_full;
441 wrd->attrSet = VAL_IDXPATH;
443 if (p->flagShowRecords)
445 printf("%*s tag=", (level + 1) * 4, "");
446 for (i = 0; i<wrd->length && i < 40; i++)
447 fputc (wrd->string[i], stdout);
458 tag_path_full[flen] = 0;
460 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
461 directive, or default xpath indexing is enabled */
462 if (!(do_xpindex = 1 - termlist_only)) {
463 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
464 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
468 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
471 if (use == 1) /* only for the starting tag... */
474 #define MAX_ATTR_COUNT 50
476 data1_termlist *tll[MAX_ATTR_COUNT];
480 /* get termlists for attributes, and find out, if we have to do xpath indexing */
481 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
486 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
488 int do_xpindex = 1 - termlist_only;
490 char attr_tag_path_full[1024];
493 /* this could be cached as well */
494 sprintf (attr_tag_path_full, "@%s/%.*s",
495 xp->name, int_len, tag_path_full);
497 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
499 /* if there is a ! in the xelm termlist, or default indexing is on,
500 proceed with xpath idx */
503 for (; tl; tl = tl->next)
512 /* attribute (no value) */
515 wrd->string = xp->name;
516 wrd->length = strlen(xp->name);
522 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
524 /* attribute value exact */
525 strcpy (comb, xp->name);
527 strcat (comb, xp->value);
532 wrd->length = strlen(comb);
542 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
544 char attr_tag_path_full[1024];
548 sprintf (attr_tag_path_full, "@%s/%.*s",
549 xp->name, int_len, tag_path_full);
553 /* If there is a termlist given (=xelm directive) */
554 for (; tl; tl = tl->next)
557 /* add xpath index for the attribute */
558 index_xpath_attr (attr_tag_path_full, xp->name,
559 xp->value, tl->structure,
563 /* add attribute based index for the attribute */
566 (tl->att->parent->reference);
567 wrd->attrUse = tl->att->locals->local;
568 wrd->reg_type = *tl->structure;
569 wrd->string = xp->value;
570 wrd->length = strlen(xp->value);
576 /* if there was no termlist for the given path,
577 or the termlist didn't have a ! element, index
578 the attribute as "w" */
579 if ((!xpdone) && (!termlist_only))
581 index_xpath_attr (attr_tag_path_full, xp->name,
582 xp->value, "w", p, wrd);
591 static void index_termlist (data1_node *par, data1_node *n,
592 struct recExtractCtrl *p, int level, RecWord *wrd)
594 data1_termlist *tlist = 0;
595 data1_datatype dtype = DATA1K_string;
598 * cycle up towards the root until we find a tag with an att..
599 * this has the effect of indexing locally defined tags with
600 * the attribute of their ancestor in the record.
603 while (!par->u.tag.element)
604 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
606 if (!par || !(tlist = par->u.tag.element->termlists))
608 if (par->u.tag.element->tag)
609 dtype = par->u.tag.element->tag->kind;
611 for (; tlist; tlist = tlist->next)
615 /* consider source */
618 if (!strcmp (tlist->source, "data") && n->which == DATA1N_data)
620 wrd->string = n->u.data.data;
621 wrd->length = n->u.data.len;
623 else if (!strcmp (tlist->source, "tag") && n->which == DATA1N_tag)
625 wrd->string = n->u.tag.tag;
626 wrd->length = strlen(n->u.tag.tag);
628 else if (sscanf (tlist->source, "attr(%511[^)])", xattr) == 1 &&
629 n->which == DATA1N_tag)
631 data1_xattr *p = n->u.tag.attributes;
632 while (p && strcmp (p->name, xattr))
636 wrd->string = p->value;
637 wrd->length = strlen(p->value);
642 if (p->flagShowRecords)
645 printf("%*sIdx: [%s]", (level + 1) * 4, "",
647 printf("%s:%s [%d] %s",
648 tlist->att->parent->name,
649 tlist->att->name, tlist->att->value,
651 printf (" XData:\"");
652 for (i = 0; i<wrd->length && i < 40; i++)
653 fputc (wrd->string[i], stdout);
655 if (wrd->length > 40)
657 fputc ('\n', stdout);
661 wrd->reg_type = *tlist->structure;
662 wrd->attrSet = (int) (tlist->att->parent->reference);
663 wrd->attrUse = tlist->att->locals->local;
670 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
673 for (; n; n = n->next)
675 if (p->flagShowRecords) /* display element description to user */
677 if (n->which == DATA1N_root)
679 printf("%*s", level * 4, "");
680 printf("Record type: '%s'\n", n->u.root.type);
682 else if (n->which == DATA1N_tag)
686 printf("%*s", level * 4, "");
687 if (!(e = n->u.tag.element))
688 printf("Local tag: '%s'\n", n->u.tag.tag);
691 printf("Elm: '%s' ", e->name);
694 data1_tag *t = e->tag;
696 printf("TagNam: '%s' ", t->names->name);
699 printf("%s[%d],", t->tagset->name, t->tagset->type);
702 if (t->which == DATA1T_numeric)
703 printf("%d)", t->value.numeric);
705 printf("'%s')", t->value.string);
712 if (n->which == DATA1N_tag)
714 index_termlist (n, n, p, level, wrd);
715 /* index start tag */
716 if (n->root->u.root.absyn)
717 index_xpath (n, p, level, wrd, 1);
721 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
725 if (n->which == DATA1N_data)
727 data1_node *par = get_parent_tag(p->dh, n);
729 if (p->flagShowRecords)
731 printf("%*s", level * 4, "");
733 if (n->u.data.len > 256)
734 printf("'%.170s ... %.70s'\n", n->u.data.data,
735 n->u.data.data + n->u.data.len-70);
736 else if (n->u.data.len > 0)
737 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
743 index_termlist (par, n, p, level, wrd);
745 index_xpath (n, p, level, wrd, 1016);
748 if (n->which == DATA1N_tag)
751 index_xpath (n, p, level, wrd, 2);
754 if (p->flagShowRecords && n->which == DATA1N_root)
756 printf("%*s-------------\n\n", level * 4, "");
762 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
765 int oidtmp[OID_SIZE];
768 oe.proto = PROTO_Z3950;
769 oe.oclass = CLASS_SCHEMA;
772 oe.value = n->u.root.absyn->reference;
774 if ((oid_ent_to_oid (&oe, oidtmp)))
775 (*p->schemaAdd)(p, oidtmp);
779 return dumpkeys(n, p, 0, &wrd);
782 static int grs_extract_sub(struct grs_handlers *h, struct recExtractCtrl *p,
786 struct grs_read_info gri;
788 int oidtmp[OID_SIZE];
791 gri.readf = p->readf;
792 gri.seekf = p->seekf;
793 gri.tellf = p->tellf;
796 gri.offset = p->offset;
800 if (read_grs_type (h, &gri, p->subType, &n))
801 return RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER;
803 return RECCTRL_EXTRACT_EOF;
804 oe.proto = PROTO_Z3950;
805 oe.oclass = CLASS_SCHEMA;
807 if (!n->u.root.absyn)
808 return RECCTRL_EXTRACT_ERROR;
812 oe.value = n->u.root.absyn->reference;
813 if ((oid_ent_to_oid (&oe, oidtmp)))
814 (*p->schemaAdd)(p, oidtmp);
816 data1_concat_text(p->dh, mem, n);
818 /* ensure our data1 tree is UTF-8 */
819 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
822 data1_pr_tree (p->dh, n, stdout);
826 if (dumpkeys(n, p, 0, &wrd) < 0)
828 data1_free_tree(p->dh, n);
829 return RECCTRL_EXTRACT_ERROR_GENERIC;
831 data1_free_tree(p->dh, n);
832 return RECCTRL_EXTRACT_OK;
835 static int grs_extract(void *clientData, struct recExtractCtrl *p)
838 NMEM mem = nmem_create ();
839 struct grs_handlers *h = (struct grs_handlers *) clientData;
841 ret = grs_extract_sub(h, p, mem);
847 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
849 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c)
851 data1_esetname *eset;
857 case Z_RecordComp_simple:
858 if (c->u.simple->which != Z_ElementSetNames_generic)
859 return 26; /* only generic form supported. Fix this later */
860 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
861 c->u.simple->u.generic)))
863 logf(LOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
864 return 25; /* invalid esetname */
866 logf(LOG_DEBUG, "Esetname '%s' in simple compspec",
867 c->u.simple->u.generic);
870 case Z_RecordComp_complex:
871 if (c->u.complex->generic)
873 /* insert check for schema */
874 if ((p = c->u.complex->generic->elementSpec))
878 case Z_ElementSpec_elementSetName:
880 data1_getesetbyname(dh, n->u.root.absyn,
881 p->u.elementSetName)))
883 logf(LOG_LOG, "Unknown esetname '%s'",
884 p->u.elementSetName);
885 return 25; /* invalid esetname */
887 logf(LOG_DEBUG, "Esetname '%s' in complex compspec",
888 p->u.elementSetName);
891 case Z_ElementSpec_externalSpec:
892 if (p->u.externalSpec->which == Z_External_espec1)
894 logf(LOG_DEBUG, "Got Espec-1");
895 espec = p->u.externalSpec-> u.espec1;
899 logf(LOG_LOG, "Unknown external espec.");
900 return 25; /* bad. what is proper diagnostic? */
911 logf (LOG_DEBUG, "Element: Espec-1 match");
912 return data1_doespec1(dh, n, espec);
916 logf (LOG_DEBUG, "Element: all match");
921 /* Add Zebra info in separate namespace ...
924 <metadata xmlns="http://www.indexdata.dk/zebra/">
926 <localnumber>447</localnumber>
927 <filename>records/genera.xml</filename>
932 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
935 const char *idzebra_ns[3];
936 const char *i2 = "\n ";
937 const char *i4 = "\n ";
940 idzebra_ns[0] = "xmlns";
941 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
944 data1_mk_text (p->dh, mem, i2, top);
946 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
948 data1_mk_text (p->dh, mem, "\n", top);
950 data1_mk_text (p->dh, mem, i4, n);
952 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
956 data1_mk_text (p->dh, mem, i4, n);
957 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
959 data1_mk_text (p->dh, mem, i4, n);
960 data1_mk_tag_data_int (p->dh, n, "localnumber", p->localno, mem);
963 data1_mk_text (p->dh, mem, i4, n);
964 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
966 data1_mk_text (p->dh, mem, i2, n);
969 static int grs_retrieve(void *clientData, struct recRetrieveCtrl *p)
971 data1_node *node = 0, *onode = 0, *top;
974 int res, selected = 0;
976 struct grs_read_info gri;
978 struct grs_handlers *h = (struct grs_handlers *) clientData;
979 int requested_schema = VAL_NONE;
980 data1_marctab *marctab;
984 gri.readf = p->readf;
985 gri.seekf = p->seekf;
986 gri.tellf = p->tellf;
993 logf (LOG_DEBUG, "grs_retrieve");
994 if (read_grs_type (h, &gri, p->subType, &node))
1006 data1_concat_text(p->dh, mem, node);
1008 /* ensure our data1 tree is UTF-8 */
1009 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1012 data1_pr_tree (p->dh, node, stdout);
1014 top = data1_get_root_tag (p->dh, node);
1016 logf (LOG_DEBUG, "grs_retrieve: size");
1017 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1019 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1021 dnew->u.data.what = DATA1I_text;
1022 dnew->u.data.data = dnew->lbuf;
1023 sprintf(dnew->u.data.data, "%d", p->recordSize);
1024 dnew->u.data.len = strlen(dnew->u.data.data);
1027 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1028 if (tagname && p->score >= 0 &&
1029 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1031 logf (LOG_DEBUG, "grs_retrieve: %s", tagname);
1032 dnew->u.data.what = DATA1I_num;
1033 dnew->u.data.data = dnew->lbuf;
1034 sprintf(dnew->u.data.data, "%d", p->score);
1035 dnew->u.data.len = strlen(dnew->u.data.data);
1038 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1039 "localControlNumber");
1040 if (tagname && p->localno > 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_text;
1045 dnew->u.data.data = dnew->lbuf;
1047 sprintf(dnew->u.data.data, "%d", p->localno);
1048 dnew->u.data.len = strlen(dnew->u.data.data);
1051 data1_pr_tree (p->dh, node, stdout);
1053 #if YAZ_VERSIONL >= 0x010903L
1054 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1055 p->comp->u.complex->generic &&
1056 p->comp->u.complex->generic->which == Z_Schema_oid &&
1057 p->comp->u.complex->generic->schema.oid)
1059 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1061 requested_schema = oe->value;
1064 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1065 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1067 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1069 requested_schema = oe->value;
1073 /* If schema has been specified, map if possible, then check that
1074 * we got the right one
1076 if (requested_schema != VAL_NONE)
1078 logf (LOG_DEBUG, "grs_retrieve: schema mapping");
1079 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1081 if (map->target_absyn_ref == requested_schema)
1084 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1093 if (node->u.root.absyn &&
1094 requested_schema != node->u.root.absyn->reference)
1096 p->diagnostic = 238;
1102 * Does the requested format match a known syntax-mapping? (this reflects
1103 * the overlap of schema and formatting which is inherent in the MARC
1106 yaz_log (LOG_DEBUG, "grs_retrieve: syntax mapping");
1107 if (node->u.root.absyn)
1108 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1110 if (map->target_absyn_ref == p->input_format)
1113 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1122 yaz_log (LOG_DEBUG, "grs_retrieve: schemaIdentifier");
1123 if (node->u.root.absyn &&
1124 node->u.root.absyn->reference != VAL_NONE &&
1125 p->input_format == VAL_GRS1)
1129 int oidtmp[OID_SIZE];
1131 oe.proto = PROTO_Z3950;
1132 oe.oclass = CLASS_SCHEMA;
1133 oe.value = node->u.root.absyn->reference;
1135 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1138 data1_handle dh = p->dh;
1142 for (ii = oid; *ii >= 0; ii++)
1146 sprintf(p, "%d", *ii);
1149 if ((dnew = data1_mk_tag_data_wd(dh, top,
1150 "schemaIdentifier", mem)))
1152 dnew->u.data.what = DATA1I_oid;
1153 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1154 memcpy(dnew->u.data.data, tmp, p - tmp);
1155 dnew->u.data.len = p - tmp;
1160 logf (LOG_DEBUG, "grs_retrieve: element spec");
1161 if (p->comp && (res = process_comp(p->dh, node, p->comp)) > 0)
1163 p->diagnostic = res;
1165 data1_free_tree(p->dh, onode);
1166 data1_free_tree(p->dh, node);
1170 else if (p->comp && !res)
1174 data1_pr_tree (p->dh, node, stdout);
1176 logf (LOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1177 switch (p->output_format = (p->input_format != VAL_NONE ?
1178 p->input_format : VAL_SUTRS))
1181 zebra_xml_metadata (p, top, mem);
1184 data1_pr_tree (p->dh, node, stdout);
1188 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1190 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1192 p->diagnostic = 238;
1195 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1196 memcpy (new_buf, p->rec_buf, p->rec_len);
1197 p->rec_buf = new_buf;
1202 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1204 p->diagnostic = 238; /* not available in requested syntax */
1206 p->rec_len = (size_t) (-1);
1209 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1211 p->diagnostic = 238;
1213 p->rec_len = (size_t) (-1);
1216 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1218 p->diagnostic = 238;
1220 p->rec_len = (size_t) (-1);
1224 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1225 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1227 p->diagnostic = 238;
1230 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1231 memcpy (new_buf, p->rec_buf, p->rec_len);
1232 p->rec_buf = new_buf;
1236 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1238 p->diagnostic = 238;
1241 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1242 memcpy (new_buf, p->rec_buf, p->rec_len);
1243 p->rec_buf = new_buf;
1247 if (!node->u.root.absyn)
1249 p->diagnostic = 238;
1252 for (marctab = node->u.root.absyn->marc; marctab;
1253 marctab = marctab->next)
1254 if (marctab->reference == p->input_format)
1258 p->diagnostic = 238;
1262 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1263 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1264 selected, &p->rec_len)))
1265 p->diagnostic = 238;
1268 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1269 memcpy (new_buf, p->rec_buf, p->rec_len);
1270 p->rec_buf = new_buf;
1274 data1_free_tree(p->dh, node);
1276 data1_free_tree(p->dh, onode);
1281 static struct recType grs_type =
1290 RecType recTypeGrs = &grs_type;