1 /* $Id: recgrs.c,v 1.84 2003-09-16 19:35:19 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 /* we have to fetch the whole path to the data tag */
377 for (nn = n; nn; nn = nn->parent) {
378 if (nn->which == DATA1N_tag) {
379 size_t tlen = strlen(nn->u.tag.tag);
380 if (tlen + flen > (sizeof(tag_path_full)-2)) return;
381 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
383 tag_path_full[flen++] = '/';
385 else if (nn->which == DATA1N_root) break;
388 tag_path_full[flen] = 0;
390 /* If we have a matching termlist... */
391 if (n->root->u.root.absyn && (tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
392 for (; tl; tl = tl->next) {
393 wrd->reg_type = *tl->structure;
394 /* this is the ! case, so structure is for the xpath index */
396 wrd->attrSet = VAL_IDXPATH;
400 /* this is just the old fashioned attribute based index */
402 wrd->attrSet = (int) (tl->att->parent->reference);
403 wrd->attrUse = tl->att->locals->local;
408 /* xpath indexing is done, if there was no termlist given,
409 or no ! in the termlist, and default indexing is enabled... */
410 if ((!xpdone) && (!termlist_only)) {
411 wrd->attrSet = VAL_IDXPATH;
420 for (nn = n; nn; nn = nn->parent)
422 if (nn->which == DATA1N_tag)
424 size_t tlen = strlen(nn->u.tag.tag);
425 if (tlen + flen > (sizeof(tag_path_full)-2))
427 memcpy (tag_path_full + flen, nn->u.tag.tag, tlen);
429 tag_path_full[flen++] = '/';
431 else if (nn->which == DATA1N_root)
437 wrd->string = tag_path_full;
439 wrd->attrSet = VAL_IDXPATH;
441 if (p->flagShowRecords)
443 printf("%*s tag=", (level + 1) * 4, "");
444 for (i = 0; i<wrd->length && i < 40; i++)
445 fputc (wrd->string[i], stdout);
456 tag_path_full[flen] = 0;
458 /* Add tag start/end xpath index, only when there is a ! in the apropriate xelm
459 directive, or default xpath indexing is enabled */
460 if (!(do_xpindex = 1 - termlist_only)) {
461 if ((tl = xpath_termlist_by_tagpath(tag_path_full, n))) {
462 for (; tl; tl = tl->next) { if (!tl->att) {do_xpindex = 1;} }
466 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
469 if (use == 1) /* only for the starting tag... */
472 #define MAX_ATTR_COUNT 50
474 data1_termlist *tll[MAX_ATTR_COUNT];
478 /* get termlists for attributes, and find out, if we have to do xpath indexing */
479 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
484 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
486 int do_xpindex = 1 - termlist_only;
488 char attr_tag_path_full[1024];
491 /* this could be cached as well */
492 sprintf (attr_tag_path_full, "@%s/%.*s",
493 xp->name, int_len, tag_path_full);
495 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
497 /* if there is a ! in the xelm termlist, or default indexing is on,
498 proceed with xpath idx */
501 for (; tl; tl = tl->next)
510 /* attribute (no value) */
513 wrd->string = xp->name;
514 wrd->length = strlen(xp->name);
520 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2) {
522 /* attribute value exact */
523 strcpy (comb, xp->name);
525 strcat (comb, xp->value);
530 wrd->length = strlen(comb);
540 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
542 char attr_tag_path_full[1024];
546 sprintf (attr_tag_path_full, "@%s/%.*s",
547 xp->name, int_len, tag_path_full);
551 /* If there is a termlist given (=xelm directive) */
552 for (; tl; tl = tl->next)
555 /* add xpath index for the attribute */
556 index_xpath_attr (attr_tag_path_full, xp->name,
557 xp->value, tl->structure,
561 /* add attribute based index for the attribute */
564 (tl->att->parent->reference);
565 wrd->attrUse = tl->att->locals->local;
566 wrd->reg_type = *tl->structure;
567 wrd->string = xp->value;
568 wrd->length = strlen(xp->value);
574 /* if there was no termlist for the given path,
575 or the termlist didn't have a ! element, index
576 the attribute as "w" */
577 if ((!xpdone) && (!termlist_only))
579 index_xpath_attr (attr_tag_path_full, xp->name,
580 xp->value, "w", p, wrd);
589 static void index_termlist (data1_node *par, data1_node *n,
590 struct recExtractCtrl *p, int level, RecWord *wrd)
592 data1_termlist *tlist = 0;
593 data1_datatype dtype = DATA1K_string;
596 * cycle up towards the root until we find a tag with an att..
597 * this has the effect of indexing locally defined tags with
598 * the attribute of their ancestor in the record.
601 while (!par->u.tag.element)
602 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
604 if (!par || !(tlist = par->u.tag.element->termlists))
606 if (par->u.tag.element->tag)
607 dtype = par->u.tag.element->tag->kind;
609 for (; tlist; tlist = tlist->next)
613 /* consider source */
616 if (!strcmp (tlist->source, "data") && n->which == DATA1N_data)
618 wrd->string = n->u.data.data;
619 wrd->length = n->u.data.len;
621 else if (!strcmp (tlist->source, "tag") && n->which == DATA1N_tag)
623 wrd->string = n->u.tag.tag;
624 wrd->length = strlen(n->u.tag.tag);
626 else if (sscanf (tlist->source, "attr(%511[^)])", xattr) == 1 &&
627 n->which == DATA1N_tag)
629 data1_xattr *p = n->u.tag.attributes;
630 while (p && strcmp (p->name, xattr))
634 wrd->string = p->value;
635 wrd->length = strlen(p->value);
640 if (p->flagShowRecords)
643 printf("%*sIdx: [%s]", (level + 1) * 4, "",
645 printf("%s:%s [%d] %s",
646 tlist->att->parent->name,
647 tlist->att->name, tlist->att->value,
649 printf (" XData:\"");
650 for (i = 0; i<wrd->length && i < 40; i++)
651 fputc (wrd->string[i], stdout);
653 if (wrd->length > 40)
655 fputc ('\n', stdout);
659 wrd->reg_type = *tlist->structure;
660 wrd->attrSet = (int) (tlist->att->parent->reference);
661 wrd->attrUse = tlist->att->locals->local;
668 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, int level,
671 for (; n; n = n->next)
673 if (p->flagShowRecords) /* display element description to user */
675 if (n->which == DATA1N_root)
677 printf("%*s", level * 4, "");
678 printf("Record type: '%s'\n", n->u.root.type);
680 else if (n->which == DATA1N_tag)
684 printf("%*s", level * 4, "");
685 if (!(e = n->u.tag.element))
686 printf("Local tag: '%s'\n", n->u.tag.tag);
689 printf("Elm: '%s' ", e->name);
692 data1_tag *t = e->tag;
694 printf("TagNam: '%s' ", t->names->name);
697 printf("%s[%d],", t->tagset->name, t->tagset->type);
700 if (t->which == DATA1T_numeric)
701 printf("%d)", t->value.numeric);
703 printf("'%s')", t->value.string);
710 if (n->which == DATA1N_tag)
712 index_termlist (n, n, p, level, wrd);
713 /* index start tag */
714 if (n->root->u.root.absyn)
715 index_xpath (n, p, level, wrd, 1);
719 if (dumpkeys(n->child, p, level + 1, wrd) < 0)
723 if (n->which == DATA1N_data)
725 data1_node *par = get_parent_tag(p->dh, n);
727 if (p->flagShowRecords)
729 printf("%*s", level * 4, "");
731 if (n->u.data.len > 256)
732 printf("'%.170s ... %.70s'\n", n->u.data.data,
733 n->u.data.data + n->u.data.len-70);
734 else if (n->u.data.len > 0)
735 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
741 index_termlist (par, n, p, level, wrd);
743 index_xpath (n, p, level, wrd, 1016);
746 if (n->which == DATA1N_tag)
749 index_xpath (n, p, level, wrd, 2);
752 if (p->flagShowRecords && n->which == DATA1N_root)
754 printf("%*s-------------\n\n", level * 4, "");
760 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
763 int oidtmp[OID_SIZE];
766 oe.proto = PROTO_Z3950;
767 oe.oclass = CLASS_SCHEMA;
770 oe.value = n->u.root.absyn->reference;
772 if ((oid_ent_to_oid (&oe, oidtmp)))
773 (*p->schemaAdd)(p, oidtmp);
777 return dumpkeys(n, p, 0, &wrd);
780 static int grs_extract_sub(struct grs_handlers *h, struct recExtractCtrl *p,
784 struct grs_read_info gri;
786 int oidtmp[OID_SIZE];
789 gri.readf = p->readf;
790 gri.seekf = p->seekf;
791 gri.tellf = p->tellf;
794 gri.offset = p->offset;
798 if (read_grs_type (h, &gri, p->subType, &n))
799 return RECCTRL_EXTRACT_ERROR_NO_SUCH_FILTER;
801 return RECCTRL_EXTRACT_EOF;
802 oe.proto = PROTO_Z3950;
803 oe.oclass = CLASS_SCHEMA;
805 if (!n->u.root.absyn)
806 return RECCTRL_EXTRACT_ERROR;
810 oe.value = n->u.root.absyn->reference;
811 if ((oid_ent_to_oid (&oe, oidtmp)))
812 (*p->schemaAdd)(p, oidtmp);
814 data1_concat_text(p->dh, mem, n);
816 /* ensure our data1 tree is UTF-8 */
817 data1_iconv (p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
820 data1_pr_tree (p->dh, n, stdout);
824 if (dumpkeys(n, p, 0, &wrd) < 0)
826 data1_free_tree(p->dh, n);
827 return RECCTRL_EXTRACT_ERROR_GENERIC;
829 data1_free_tree(p->dh, n);
830 return RECCTRL_EXTRACT_OK;
833 static int grs_extract(void *clientData, struct recExtractCtrl *p)
836 NMEM mem = nmem_create ();
837 struct grs_handlers *h = (struct grs_handlers *) clientData;
839 ret = grs_extract_sub(h, p, mem);
845 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
847 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c)
849 data1_esetname *eset;
855 case Z_RecordComp_simple:
856 if (c->u.simple->which != Z_ElementSetNames_generic)
857 return 26; /* only generic form supported. Fix this later */
858 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
859 c->u.simple->u.generic)))
861 logf(LOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
862 return 25; /* invalid esetname */
864 logf(LOG_DEBUG, "Esetname '%s' in simple compspec",
865 c->u.simple->u.generic);
868 case Z_RecordComp_complex:
869 if (c->u.complex->generic)
871 /* insert check for schema */
872 if ((p = c->u.complex->generic->elementSpec))
876 case Z_ElementSpec_elementSetName:
878 data1_getesetbyname(dh, n->u.root.absyn,
879 p->u.elementSetName)))
881 logf(LOG_LOG, "Unknown esetname '%s'",
882 p->u.elementSetName);
883 return 25; /* invalid esetname */
885 logf(LOG_DEBUG, "Esetname '%s' in complex compspec",
886 p->u.elementSetName);
889 case Z_ElementSpec_externalSpec:
890 if (p->u.externalSpec->which == Z_External_espec1)
892 logf(LOG_DEBUG, "Got Espec-1");
893 espec = p->u.externalSpec-> u.espec1;
897 logf(LOG_LOG, "Unknown external espec.");
898 return 25; /* bad. what is proper diagnostic? */
909 logf (LOG_DEBUG, "Element: Espec-1 match");
910 return data1_doespec1(dh, n, espec);
914 logf (LOG_DEBUG, "Element: all match");
919 /* Add Zebra info in separate namespace ...
922 <metadata xmlns="http://www.indexdata.dk/zebra/">
924 <localnumber>447</localnumber>
925 <filename>records/genera.xml</filename>
930 static void zebra_xml_metadata (struct recRetrieveCtrl *p, data1_node *top,
933 const char *idzebra_ns[3];
934 const char *i2 = "\n ";
935 const char *i4 = "\n ";
938 idzebra_ns[0] = "xmlns";
939 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
942 data1_mk_text (p->dh, mem, i2, top);
944 n = data1_mk_tag (p->dh, mem, "idzebra", idzebra_ns, top);
946 data1_mk_text (p->dh, mem, "\n", top);
948 data1_mk_text (p->dh, mem, i4, n);
950 data1_mk_tag_data_int (p->dh, n, "size", p->recordSize, mem);
954 data1_mk_text (p->dh, mem, i4, n);
955 data1_mk_tag_data_int (p->dh, n, "score", p->score, mem);
957 data1_mk_text (p->dh, mem, i4, n);
958 data1_mk_tag_data_int (p->dh, n, "localnumber", p->localno, mem);
961 data1_mk_text (p->dh, mem, i4, n);
962 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
964 data1_mk_text (p->dh, mem, i2, n);
967 static int grs_retrieve(void *clientData, struct recRetrieveCtrl *p)
969 data1_node *node = 0, *onode = 0, *top;
972 int res, selected = 0;
974 struct grs_read_info gri;
976 struct grs_handlers *h = (struct grs_handlers *) clientData;
977 int requested_schema = VAL_NONE;
978 data1_marctab *marctab;
982 gri.readf = p->readf;
983 gri.seekf = p->seekf;
984 gri.tellf = p->tellf;
991 logf (LOG_DEBUG, "grs_retrieve");
992 if (read_grs_type (h, &gri, p->subType, &node))
1004 data1_concat_text(p->dh, mem, node);
1006 /* ensure our data1 tree is UTF-8 */
1007 data1_iconv (p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1010 data1_pr_tree (p->dh, node, stdout);
1012 top = data1_get_root_tag (p->dh, node);
1014 logf (LOG_DEBUG, "grs_retrieve: size");
1015 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1017 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1019 dnew->u.data.what = DATA1I_text;
1020 dnew->u.data.data = dnew->lbuf;
1021 sprintf(dnew->u.data.data, "%d", p->recordSize);
1022 dnew->u.data.len = strlen(dnew->u.data.data);
1025 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1026 if (tagname && p->score >= 0 &&
1027 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1029 logf (LOG_DEBUG, "grs_retrieve: %s", tagname);
1030 dnew->u.data.what = DATA1I_num;
1031 dnew->u.data.data = dnew->lbuf;
1032 sprintf(dnew->u.data.data, "%d", p->score);
1033 dnew->u.data.len = strlen(dnew->u.data.data);
1036 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1037 "localControlNumber");
1038 if (tagname && p->localno > 0 &&
1039 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1041 logf (LOG_DEBUG, "grs_retrieve: %s", tagname);
1042 dnew->u.data.what = DATA1I_text;
1043 dnew->u.data.data = dnew->lbuf;
1045 sprintf(dnew->u.data.data, "%d", p->localno);
1046 dnew->u.data.len = strlen(dnew->u.data.data);
1049 data1_pr_tree (p->dh, node, stdout);
1051 #if YAZ_VERSIONL >= 0x010903L
1052 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1053 p->comp->u.complex->generic &&
1054 p->comp->u.complex->generic->which == Z_Schema_oid &&
1055 p->comp->u.complex->generic->schema.oid)
1057 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema.oid);
1059 requested_schema = oe->value;
1062 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1063 p->comp->u.complex->generic && p->comp->u.complex->generic->schema)
1065 oident *oe = oid_getentbyoid (p->comp->u.complex->generic->schema);
1067 requested_schema = oe->value;
1071 /* If schema has been specified, map if possible, then check that
1072 * we got the right one
1074 if (requested_schema != VAL_NONE)
1076 logf (LOG_DEBUG, "grs_retrieve: schema mapping");
1077 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1079 if (map->target_absyn_ref == requested_schema)
1082 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1091 if (node->u.root.absyn &&
1092 requested_schema != node->u.root.absyn->reference)
1094 p->diagnostic = 238;
1100 * Does the requested format match a known syntax-mapping? (this reflects
1101 * the overlap of schema and formatting which is inherent in the MARC
1104 yaz_log (LOG_DEBUG, "grs_retrieve: syntax mapping");
1105 if (node->u.root.absyn)
1106 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1108 if (map->target_absyn_ref == p->input_format)
1111 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1120 yaz_log (LOG_DEBUG, "grs_retrieve: schemaIdentifier");
1121 if (node->u.root.absyn &&
1122 node->u.root.absyn->reference != VAL_NONE &&
1123 p->input_format == VAL_GRS1)
1127 int oidtmp[OID_SIZE];
1129 oe.proto = PROTO_Z3950;
1130 oe.oclass = CLASS_SCHEMA;
1131 oe.value = node->u.root.absyn->reference;
1133 if ((oid = oid_ent_to_oid (&oe, oidtmp)))
1136 data1_handle dh = p->dh;
1140 for (ii = oid; *ii >= 0; ii++)
1144 sprintf(p, "%d", *ii);
1147 if ((dnew = data1_mk_tag_data_wd(dh, top,
1148 "schemaIdentifier", mem)))
1150 dnew->u.data.what = DATA1I_oid;
1151 dnew->u.data.data = (char *) nmem_malloc(mem, p - tmp);
1152 memcpy(dnew->u.data.data, tmp, p - tmp);
1153 dnew->u.data.len = p - tmp;
1158 logf (LOG_DEBUG, "grs_retrieve: element spec");
1159 if (p->comp && (res = process_comp(p->dh, node, p->comp)) > 0)
1161 p->diagnostic = res;
1163 data1_free_tree(p->dh, onode);
1164 data1_free_tree(p->dh, node);
1168 else if (p->comp && !res)
1172 data1_pr_tree (p->dh, node, stdout);
1174 logf (LOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1175 switch (p->output_format = (p->input_format != VAL_NONE ?
1176 p->input_format : VAL_SUTRS))
1179 zebra_xml_metadata (p, top, mem);
1182 data1_pr_tree (p->dh, node, stdout);
1186 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1188 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1190 p->diagnostic = 238;
1193 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1194 memcpy (new_buf, p->rec_buf, p->rec_len);
1195 p->rec_buf = new_buf;
1200 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1202 p->diagnostic = 238; /* not available in requested syntax */
1204 p->rec_len = (size_t) (-1);
1207 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1209 p->diagnostic = 238;
1211 p->rec_len = (size_t) (-1);
1214 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1216 p->diagnostic = 238;
1218 p->rec_len = (size_t) (-1);
1222 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1223 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1225 p->diagnostic = 238;
1228 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1229 memcpy (new_buf, p->rec_buf, p->rec_len);
1230 p->rec_buf = new_buf;
1234 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1236 p->diagnostic = 238;
1239 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1240 memcpy (new_buf, p->rec_buf, p->rec_len);
1241 p->rec_buf = new_buf;
1245 if (!node->u.root.absyn)
1247 p->diagnostic = 238;
1250 for (marctab = node->u.root.absyn->marc; marctab;
1251 marctab = marctab->next)
1252 if (marctab->reference == p->input_format)
1256 p->diagnostic = 238;
1260 data1_iconv (p->dh, mem, node, p->encoding, "UTF-8");
1261 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1262 selected, &p->rec_len)))
1263 p->diagnostic = 238;
1266 char *new_buf = (char*) odr_malloc (p->odr, p->rec_len);
1267 memcpy (new_buf, p->rec_buf, p->rec_len);
1268 p->rec_buf = new_buf;
1272 data1_free_tree(p->dh, node);
1274 data1_free_tree(p->dh, onode);
1279 static struct recType grs_type =
1288 RecType recTypeGrs = &grs_type;