1 /* This file is part of the Zebra server.
2 Copyright (C) 1994-2009 Index Data
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include <sys/types.h>
26 #include <yaz/oid_db.h>
27 #include <yaz/diagbib1.h>
30 #include <idzebra/recgrs.h>
32 #define GRS_MAX_WORD 512
34 struct source_parser {
42 static int sp_lex(struct source_parser *sp)
44 while (*sp->src == ' ')
48 while (*sp->src && !strchr("<>();,-: ", *sp->src))
57 sp->lookahead = *sp->src;
64 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd);
66 static int sp_range(struct source_parser *sp, data1_node *n, RecWord *wrd)
73 if (sp->lookahead != '(')
75 sp_lex(sp); /* skip ( */
78 if (!sp_expr(sp, n, wrd))
81 if (sp->lookahead != ',')
83 sp_lex(sp); /* skip , */
86 if (!sp_expr(sp, n, &tmp_w))
88 start = atoi_n(tmp_w.term_buf, tmp_w.term_len);
90 if (sp->lookahead == ',')
92 sp_lex(sp); /* skip , */
95 if (!sp_expr(sp, n, &tmp_w))
97 len = atoi_n(tmp_w.term_buf, tmp_w.term_len);
103 if (sp->lookahead != ')')
107 if (wrd->term_buf && wrd->term_len)
109 wrd->term_buf += start;
110 wrd->term_len -= start;
111 if (wrd->term_len > len)
117 static int sp_first(struct source_parser *sp, data1_node *n, RecWord *wrd)
122 if (sp->lookahead != '(')
124 sp_lex(sp); /* skip ( */
125 if (!sp_expr(sp, n, wrd))
127 while (sp->lookahead == ',')
131 sp_lex(sp); /* skip , */
133 if (!sp_expr(sp, n, &search_w))
135 for (i = 0; i<wrd->term_len; i++)
138 for (j = 0; j<search_w.term_len && i+j < wrd->term_len; j++)
139 if (wrd->term_buf[i+j] != search_w.term_buf[j])
141 if (j == search_w.term_len) /* match ? */
143 if (min_pos == -1 || i < min_pos)
149 if (sp->lookahead != ')')
153 min_pos = 0; /* the default if not found */
154 sprintf(num_str, "%d", min_pos);
155 wrd->term_buf = nmem_strdup(sp->nmem, num_str);
156 wrd->term_len = strlen(wrd->term_buf);
160 static int sp_expr(struct source_parser *sp, data1_node *n, RecWord *wrd)
162 if (sp->lookahead != 't')
164 if (sp->len == 4 && !memcmp(sp->tok, "data", sp->len))
166 if (n->which == DATA1N_data)
168 wrd->term_buf = n->u.data.data;
169 wrd->term_len = n->u.data.len;
173 else if (sp->len == 3 && !memcmp(sp->tok, "tag", sp->len))
175 if (n->which == DATA1N_tag)
177 wrd->term_buf = n->u.tag.tag;
178 wrd->term_len = strlen(n->u.tag.tag);
182 else if (sp->len == 4 && !memcmp(sp->tok, "attr", sp->len))
186 if (sp->lookahead != '(')
190 if (!sp_expr(sp, n, &tmp_w))
195 if (n->which == DATA1N_tag)
197 data1_xattr *p = n->u.tag.attributes;
198 while (p && strlen(p->name) != tmp_w.term_len &&
199 memcmp (p->name, tmp_w.term_buf, tmp_w.term_len))
203 wrd->term_buf = p->value;
204 wrd->term_len = strlen(p->value);
207 if (sp->lookahead != ')')
211 else if (sp->len == 5 && !memcmp(sp->tok, "first", sp->len))
213 return sp_first(sp, n, wrd);
215 else if (sp->len == 5 && !memcmp(sp->tok, "range", sp->len))
217 return sp_range(sp, n, wrd);
219 else if (sp->len > 0 && isdigit(*(unsigned char *)sp->tok))
222 wrd->term_len = sp->len;
223 b = nmem_malloc(sp->nmem, sp->len);
224 memcpy(b, sp->tok, sp->len);
228 else if (sp->len > 2 && sp->tok[0] == '\'' && sp->tok[sp->len-1] == '\'')
231 wrd->term_len = sp->len - 2;
232 b = nmem_malloc(sp->nmem, wrd->term_len);
233 memcpy(b, sp->tok+1, wrd->term_len);
246 static struct source_parser *source_parser_create(void)
248 struct source_parser *sp = xmalloc(sizeof(*sp));
250 sp->nmem = nmem_create();
254 static void source_parser_destroy(struct source_parser *sp)
258 nmem_destroy(sp->nmem);
262 static int sp_parse(struct source_parser *sp,
263 data1_node *n, RecWord *wrd, const char *src)
269 nmem_reset(sp->nmem);
272 return sp_expr(sp, n, wrd);
275 int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
284 if (p->which == XPATH_PREDICATE_RELATION) {
285 if (p->u.relation.name[0]) {
286 if (*p->u.relation.name != '@') {
288 " Only attributes (@) are supported in xelm xpath predicates");
289 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
292 attname = p->u.relation.name + 1;
294 /* looking for the attribute with a specified name */
295 for (attr = n->u.tag.attributes; attr; attr = attr->next) {
296 if (!strcmp(attr->name, attname)) {
297 if (p->u.relation.op[0]) {
298 if (*p->u.relation.op != '=') {
300 "Only '=' relation is supported (%s)",p->u.relation.op);
301 yaz_log(YLOG_WARN, "predicate %s ignored", p->u.relation.name);
304 if (!strcmp(attr->value, p->u.relation.value)) {
309 /* attribute exists, no value specified */
319 else if (p->which == XPATH_PREDICATE_BOOLEAN) {
320 if (!strcmp(p->u.boolean.op,"and")) {
321 return d1_check_xpath_predicate(n, p->u.boolean.left)
322 && d1_check_xpath_predicate(n, p->u.boolean.right);
324 else if (!strcmp(p->u.boolean.op,"or")) {
325 return (d1_check_xpath_predicate(n, p->u.boolean.left)
326 || d1_check_xpath_predicate(n, p->u.boolean.right));
328 yaz_log(YLOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
337 static int dfa_match_first(struct DFA_state **dfaar, const char *text)
339 struct DFA_state *s = dfaar[0]; /* start state */
342 const char *p = text;
345 for (c = *p++, t = s->trans, i = s->tran_no; --i >= 0; t++)
347 if (c >= t->ch[0] && c <= t->ch[1])
351 /* move to next state and return if we get a match */
359 for (t = s->trans, i = s->tran_no; --i >= 0; t++)
360 if (c >= t->ch[0] && c <= t->ch[1])
370 New function, looking for xpath "element" definitions in abs, by
371 tagpath, using a kind of ugly regxp search.The DFA was built while
372 parsing abs, so here we just go trough them and try to match
373 against the given tagpath. The first matching entry is returned.
377 Added support for enhanced xelm. Now [] predicates are considered
378 as well, when selecting indexing rules... (why the hell it's called
385 data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
387 data1_absyn *abs = n->root->u.root.absyn;
389 data1_xpelement *xpe = 0;
392 struct xpath_location_step *xp;
394 char *pexpr = xmalloc(strlen(tagpath)+5);
396 sprintf(pexpr, "/%s\n", tagpath);
398 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
399 xpe->match_state = -1; /* don't know if it matches yet */
401 for (xpe = abs->xp_elements; xpe; xpe = xpe->next)
404 int ok = xpe->match_state;
406 { /* don't know whether there is a match yet */
407 data1_xpelement *xpe1;
410 ok = dfa_match_first(xpe->dfa->states, pexpr);
413 /* mark this and following ones with same regexp */
414 for (xpe1 = xpe; xpe1; xpe1 = xpe1->match_next)
415 xpe1->match_state = ok;
418 assert(ok == 0 || ok == 1);
421 /* we have to check the perdicates up to the root node */
424 /* find the first tag up in the node structure */
425 for (nn = n; nn && nn->which != DATA1N_tag; nn = nn->parent)
428 /* go from inside out in the node structure, while going
429 backwards trough xpath location steps ... */
430 for (i = xpe->xpath_len - 1; i>0; i--)
432 if (!d1_check_xpath_predicate(nn, xp[i].predicate))
438 if (nn->which == DATA1N_tag)
450 return xpe->termlists;
457 1 start element (tag)
459 3 start attr (and attr-exact)
467 Now, if there is a matching xelm described in abs, for the
468 indexed element or the attribute, then the data is handled according
469 to those definitions...
471 modified by pop, 2002-12-13
474 /* add xpath index for an attribute */
475 static void index_xpath_attr(char *tag_path, char *name, char *value,
476 char *structure, struct recExtractCtrl *p,
479 wrd->index_name = ZEBRA_XPATH_ELM_BEGIN;
480 wrd->index_type = "0";
481 wrd->term_buf = tag_path;
482 wrd->term_len = strlen(tag_path);
486 wrd->index_name = ZEBRA_XPATH_ATTR_CDATA;
487 wrd->index_type = "w";
488 wrd->term_buf = value;
489 wrd->term_len = strlen(value);
492 wrd->index_name = ZEBRA_XPATH_ELM_END;
493 wrd->index_type = "0";
494 wrd->term_buf = tag_path;
495 wrd->term_len = strlen(tag_path);
500 static void mk_tag_path_full(char *tag_path_full, size_t max, data1_node *n)
505 /* we have to fetch the whole path to the data tag */
506 for (nn = n; nn; nn = nn->parent)
508 if (nn->which == DATA1N_tag)
510 size_t tlen = strlen(nn->u.tag.tag);
511 if (tlen + flen > (max - 2))
513 memcpy(tag_path_full + flen, nn->u.tag.tag, tlen);
515 tag_path_full[flen++] = '/';
518 if (nn->which == DATA1N_root)
521 tag_path_full[flen] = 0;
525 static void index_xpath(struct source_parser *sp, data1_node *n,
526 struct recExtractCtrl *p,
527 int level, RecWord *wrd,
533 char tag_path_full[1024];
534 int termlist_only = 1;
537 if (!n->root->u.root.absyn
539 n->root->u.root.absyn->xpath_indexing == DATA1_XPATH_INDEXING_ENABLE)
548 wrd->term_buf = n->u.data.data;
549 wrd->term_len = n->u.data.len;
551 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
553 /* If we have a matching termlist... */
554 if (n->root->u.root.absyn &&
555 (tl = xpath_termlist_by_tagpath(tag_path_full, n)))
558 for (; tl; tl = tl->next)
560 /* need to copy recword because it may be changed */
562 wrd->index_type = tl->structure;
563 memcpy(&wrd_tl, wrd, sizeof(*wrd));
565 sp_parse(sp, n, &wrd_tl, tl->source);
567 /* this is just the old fashioned attribute based index */
568 wrd_tl.index_name = tl->index_name;
569 if (p->flagShowRecords)
572 printf("%*sIdx: [%s]", (level + 1) * 4, "",
574 printf("%s %s", tl->index_name, tl->source);
576 for (i = 0; i<wrd_tl.term_len && i < 40; i++)
577 fputc(wrd_tl.term_buf[i], stdout);
579 if (wrd_tl.term_len > 40)
585 (*p->tokenAdd)(&wrd_tl);
587 if (wrd_tl.seqno > max_seqno)
588 max_seqno = wrd_tl.seqno;
591 wrd->seqno = max_seqno;
594 /* xpath indexing is done, if there was no termlist given,
595 or no ! in the termlist, and default indexing is enabled... */
596 if (!p->flagShowRecords && !termlist_only)
598 wrd->index_name = xpath_index;
599 wrd->index_type = "w";
604 mk_tag_path_full(tag_path_full, sizeof(tag_path_full), n);
606 wrd->index_type = "0";
607 wrd->term_buf = tag_path_full;
608 wrd->term_len = strlen(tag_path_full);
609 wrd->index_name = xpath_index;
610 if (p->flagShowRecords)
612 printf("%*s tag=", (level + 1) * 4, "");
613 for (i = 0; i<wrd->term_len && i < 40; i++)
614 fputc(wrd->term_buf[i], stdout);
624 (*p->tokenAdd)(wrd); /* index element pag (AKA tag path) */
626 if (xpath_is_start == 1) /* only for the starting tag... */
628 #define MAX_ATTR_COUNT 50
629 data1_termlist *tll[MAX_ATTR_COUNT];
632 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
634 char attr_tag_path_full[1024];
636 /* this could be cached as well */
637 sprintf(attr_tag_path_full, "@%s/%s",
638 xp->name, tag_path_full);
640 tll[i] = xpath_termlist_by_tagpath(attr_tag_path_full,n);
644 /* attribute (no value) */
645 wrd->index_type = "0";
646 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
647 wrd->term_buf = xp->name;
648 wrd->term_len = strlen(xp->name);
655 strlen(xp->name) + strlen(xp->value) < sizeof(comb)-2)
657 /* attribute value exact */
658 strcpy(comb, xp->name);
660 strcat(comb, xp->value);
662 wrd->index_name = ZEBRA_XPATH_ATTR_NAME;
663 wrd->index_type = "0";
664 wrd->term_buf = comb;
665 wrd->term_len = strlen(comb);
675 for (xp = n->u.tag.attributes; xp; xp = xp->next) {
677 char attr_tag_path_full[1024];
680 sprintf(attr_tag_path_full, "@%s/%s",
681 xp->name, tag_path_full);
684 /* If there is a termlist given (=xelm directive) */
685 for (; tl; tl = tl->next)
689 /* add xpath index for the attribute */
690 index_xpath_attr(attr_tag_path_full, xp->name,
691 xp->value, tl->structure,
695 /* index attribute value (only path/@attr) */
698 wrd->index_name = tl->index_name;
699 wrd->index_type = tl->structure;
700 wrd->term_buf = xp->value;
701 wrd->term_len = strlen(xp->value);
707 /* if there was no termlist for the given path,
708 or the termlist didn't have a ! element, index
709 the attribute as "w" */
710 if (!xpdone && !termlist_only)
712 index_xpath_attr(attr_tag_path_full, xp->name,
713 xp->value, "w", p, wrd);
722 static void index_termlist(struct source_parser *sp, data1_node *par,
724 struct recExtractCtrl *p, int level, RecWord *wrd)
726 data1_termlist *tlist = 0;
727 data1_datatype dtype = DATA1K_string;
730 * cycle up towards the root until we find a tag with an att..
731 * this has the effect of indexing locally defined tags with
732 * the attribute of their ancestor in the record.
735 while (!par->u.tag.element)
736 if (!par->parent || !(par=get_parent_tag(p->dh, par->parent)))
738 if (!par || !(tlist = par->u.tag.element->termlists))
740 if (par->u.tag.element->tag)
741 dtype = par->u.tag.element->tag->kind;
743 for (; tlist; tlist = tlist->next)
745 /* consider source */
747 assert(tlist->source);
748 sp_parse(sp, n, wrd, tlist->source);
750 if (wrd->term_buf && wrd->term_len)
752 if (p->flagShowRecords)
755 printf("%*sIdx: [%s]", (level + 1) * 4, "",
757 printf("%s %s", tlist->index_name, tlist->source);
759 for (i = 0; i<wrd->term_len && i < 40; i++)
760 fputc(wrd->term_buf[i], stdout);
762 if (wrd->term_len > 40)
768 wrd->index_type = tlist->structure;
769 wrd->index_name = tlist->index_name;
776 static int dumpkeys_r(struct source_parser *sp,
777 data1_node *n, struct recExtractCtrl *p, int level,
780 for (; n; n = n->next)
782 if (p->flagShowRecords) /* display element description to user */
784 if (n->which == DATA1N_root)
786 printf("%*s", level * 4, "");
787 printf("Record type: '%s'\n", n->u.root.type);
789 else if (n->which == DATA1N_tag)
793 printf("%*s", level * 4, "");
794 if (!(e = n->u.tag.element))
795 printf("Local tag: '%s'\n", n->u.tag.tag);
798 printf("Elm: '%s' ", e->name);
801 data1_tag *t = e->tag;
803 printf("TagNam: '%s' ", t->names->name);
806 printf("%s[%d],", t->tagset->name, t->tagset->type);
809 if (t->which == DATA1T_numeric)
810 printf("%d)", t->value.numeric);
812 printf("'%s')", t->value.string);
819 if (n->which == DATA1N_tag)
821 index_termlist(sp, n, n, p, level, wrd);
822 /* index start tag */
823 if (n->root->u.root.absyn)
824 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_BEGIN,
829 if (dumpkeys_r(sp, n->child, p, level + 1, wrd) < 0)
833 if (n->which == DATA1N_data)
835 data1_node *par = get_parent_tag(p->dh, n);
837 if (p->flagShowRecords)
839 printf("%*s", level * 4, "");
841 if (n->u.data.len > 256)
842 printf("'%.170s ... %.70s'\n", n->u.data.data,
843 n->u.data.data + n->u.data.len-70);
844 else if (n->u.data.len > 0)
845 printf("'%.*s'\n", n->u.data.len, n->u.data.data);
851 index_termlist(sp, par, n, p, level, wrd);
853 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_CDATA,
857 if (n->which == DATA1N_tag)
860 index_xpath(sp, n, p, level, wrd, ZEBRA_XPATH_ELM_END,
864 if (p->flagShowRecords && n->which == DATA1N_root)
866 printf("%*s-------------\n\n", level * 4, "");
872 static int dumpkeys(data1_node *n, struct recExtractCtrl *p, RecWord *wrd)
874 struct source_parser *sp = source_parser_create();
875 int r = dumpkeys_r(sp, n, p, 0, wrd);
876 source_parser_destroy(sp);
880 int grs_extract_tree(struct recExtractCtrl *p, data1_node *n)
884 if (n->u.root.absyn && n->u.root.absyn->oid)
885 (*p->schemaAdd)(p, n->u.root.absyn->oid);
888 /* data1_pr_tree(p->dh, n, stdout); */
890 return dumpkeys(n, p, &wrd);
893 static int grs_extract_sub(void *clientData, struct recExtractCtrl *p,
895 data1_node *(*grs_read)(struct grs_read_info *))
898 struct grs_read_info gri;
901 gri.stream = p->stream;
904 gri.clientData = clientData;
906 n = (*grs_read)(&gri);
908 return RECCTRL_EXTRACT_EOF;
909 if (n->u.root.absyn && n->u.root.absyn->oid)
910 (*p->schemaAdd)(p, n->u.root.absyn->oid);
911 data1_concat_text(p->dh, mem, n);
913 /* ensure our data1 tree is UTF-8 */
914 data1_iconv(p->dh, mem, n, "UTF-8", data1_get_encoding(p->dh, n));
917 data1_remove_idzebra_subtree(p->dh, n);
920 data1_pr_tree(p->dh, n, stdout);
924 if (dumpkeys(n, p, &wrd) < 0)
926 return RECCTRL_EXTRACT_ERROR_GENERIC;
928 return RECCTRL_EXTRACT_OK;
931 int zebra_grs_extract(void *clientData, struct recExtractCtrl *p,
932 data1_node *(*grs_read)(struct grs_read_info *))
935 NMEM mem = nmem_create();
936 ret = grs_extract_sub(clientData, p, mem, grs_read);
942 * Return: -1: Nothing done. 0: Ok. >0: Bib-1 diagnostic.
944 static int process_comp(data1_handle dh, data1_node *n, Z_RecordComposition *c,
945 char **addinfo, ODR o)
947 data1_esetname *eset;
953 case Z_RecordComp_simple:
954 if (c->u.simple->which != Z_ElementSetNames_generic)
955 return 26; /* only generic form supported. Fix this later */
956 if (!(eset = data1_getesetbyname(dh, n->u.root.absyn,
957 c->u.simple->u.generic)))
959 yaz_log(YLOG_LOG, "Unknown esetname '%s'", c->u.simple->u.generic);
960 *addinfo = odr_strdup(o, c->u.simple->u.generic);
961 return 25; /* invalid esetname */
963 yaz_log(YLOG_DEBUG, "Esetname '%s' in simple compspec",
964 c->u.simple->u.generic);
967 case Z_RecordComp_complex:
968 if (c->u.complex->generic)
970 /* insert check for schema */
971 if ((p = c->u.complex->generic->elementSpec))
975 case Z_ElementSpec_elementSetName:
977 data1_getesetbyname(dh, n->u.root.absyn,
978 p->u.elementSetName)))
980 yaz_log(YLOG_DEBUG, "Unknown esetname '%s'",
981 p->u.elementSetName);
982 *addinfo = odr_strdup(o, p->u.elementSetName);
983 return 25; /* invalid esetname */
985 yaz_log(YLOG_DEBUG, "Esetname '%s' in complex compspec",
986 p->u.elementSetName);
989 case Z_ElementSpec_externalSpec:
990 if (p->u.externalSpec->which == Z_External_espec1)
992 yaz_log(YLOG_DEBUG, "Got Espec-1");
993 espec = p->u.externalSpec-> u.espec1;
997 yaz_log(YLOG_LOG, "Unknown external espec.");
998 return 25; /* bad. what is proper diagnostic? */
1005 return 26; /* fix */
1009 yaz_log(YLOG_DEBUG, "Element: Espec-1 match");
1010 return data1_doespec1(dh, n, espec);
1014 yaz_log(YLOG_DEBUG, "Element: all match");
1019 /* Add Zebra info in separate namespace ...
1022 <metadata xmlns="http://www.indexdata.dk/zebra/">
1024 <localnumber>447</localnumber>
1025 <filename>records/genera.xml</filename>
1030 static void zebra_xml_metadata(struct recRetrieveCtrl *p, data1_node *top,
1033 const char *idzebra_ns[3];
1034 const char *i2 = "\n ";
1035 const char *i4 = "\n ";
1038 idzebra_ns[0] = "xmlns";
1039 idzebra_ns[1] = "http://www.indexdata.dk/zebra/";
1042 data1_mk_text(p->dh, mem, i2, top);
1044 n = data1_mk_tag(p->dh, mem, "idzebra", idzebra_ns, top);
1046 data1_mk_text(p->dh, mem, "\n", top);
1048 data1_mk_text(p->dh, mem, i4, n);
1050 data1_mk_tag_data_int(p->dh, n, "size", p->recordSize, mem);
1054 data1_mk_text(p->dh, mem, i4, n);
1055 data1_mk_tag_data_int(p->dh, n, "score", p->score, mem);
1057 data1_mk_text(p->dh, mem, i4, n);
1058 data1_mk_tag_data_zint(p->dh, n, "localnumber", p->localno, mem);
1061 data1_mk_text(p->dh, mem, i4, n);
1062 data1_mk_tag_data_text(p->dh, n, "filename", p->fname, mem);
1064 data1_mk_text(p->dh, mem, i2, n);
1067 int zebra_grs_retrieve(void *clientData, struct recRetrieveCtrl *p,
1068 data1_node *(*grs_read)(struct grs_read_info *))
1070 data1_node *node = 0, *onode = 0, *top;
1073 int res, selected = 0;
1075 struct grs_read_info gri;
1076 const char *tagname;
1078 const Odr_oid *requested_schema = 0;
1079 data1_marctab *marctab;
1082 mem = nmem_create();
1083 gri.stream = p->stream;
1086 gri.clientData = clientData;
1088 yaz_log(YLOG_DEBUG, "grs_retrieve");
1089 node = (*grs_read)(&gri);
1092 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1096 data1_concat_text(p->dh, mem, node);
1098 data1_remove_idzebra_subtree(p->dh, node);
1101 data1_pr_tree(p->dh, node, stdout);
1103 top = data1_get_root_tag(p->dh, node);
1105 yaz_log(YLOG_DEBUG, "grs_retrieve: size");
1106 tagname = data1_systag_lookup(node->u.root.absyn, "size", "size");
1108 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1110 dnew->u.data.what = DATA1I_text;
1111 dnew->u.data.data = dnew->lbuf;
1112 sprintf(dnew->u.data.data, "%d", p->recordSize);
1113 dnew->u.data.len = strlen(dnew->u.data.data);
1116 tagname = data1_systag_lookup(node->u.root.absyn, "rank", "rank");
1117 if (tagname && p->score >= 0 &&
1118 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1120 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1121 dnew->u.data.what = DATA1I_num;
1122 dnew->u.data.data = dnew->lbuf;
1123 sprintf(dnew->u.data.data, "%d", p->score);
1124 dnew->u.data.len = strlen(dnew->u.data.data);
1127 tagname = data1_systag_lookup(node->u.root.absyn, "sysno",
1128 "localControlNumber");
1129 if (tagname && p->localno > 0 &&
1130 (dnew = data1_mk_tag_data_wd(p->dh, top, tagname, mem)))
1132 yaz_log(YLOG_DEBUG, "grs_retrieve: %s", tagname);
1133 dnew->u.data.what = DATA1I_text;
1134 dnew->u.data.data = dnew->lbuf;
1136 sprintf(dnew->u.data.data, ZINT_FORMAT, p->localno);
1137 dnew->u.data.len = strlen(dnew->u.data.data);
1140 if (!p->input_format)
1141 { /* SUTRS is default input_format */
1142 p->input_format = yaz_oid_recsyn_sutrs;
1144 assert(p->input_format);
1146 if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_xml))
1147 zebra_xml_metadata(p, top, mem);
1150 data1_pr_tree(p->dh, node, stdout);
1152 if (p->comp && p->comp->which == Z_RecordComp_complex &&
1153 p->comp->u.complex->generic &&
1154 p->comp->u.complex->generic->which == Z_Schema_oid &&
1155 p->comp->u.complex->generic->schema.oid)
1157 requested_schema = p->comp->u.complex->generic->schema.oid;
1159 /* If schema has been specified, map if possible, then check that
1160 * we got the right one
1162 if (requested_schema)
1164 yaz_log(YLOG_DEBUG, "grs_retrieve: schema mapping");
1165 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1167 // if (map->target_absyn_ref == requested_schema)
1168 if (!oid_oidcmp(map->oid, requested_schema))
1171 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1173 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1180 if (node->u.root.absyn
1181 && oid_oidcmp(requested_schema, node->u.root.absyn->oid))
1183 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1189 * Does the requested format match a known syntax-mapping? (this reflects
1190 * the overlap of schema and formatting which is inherent in the MARC
1193 yaz_log(YLOG_DEBUG, "grs_retrieve: syntax mapping");
1194 if (node->u.root.absyn)
1195 for (map = node->u.root.absyn->maptabs; map; map = map->next)
1197 if (!oid_oidcmp(map->oid, p->input_format))
1200 if (!(node = data1_map_record(p->dh, onode, map, mem)))
1202 p->diagnostic = YAZ_BIB1_SYSTEM_ERROR_IN_PRESENTING_RECORDS;
1209 yaz_log(YLOG_DEBUG, "grs_retrieve: schemaIdentifier");
1210 if (node->u.root.absyn && node->u.root.absyn->oid
1211 && !oid_oidcmp(p->input_format, yaz_oid_recsyn_grs_1))
1213 char oid_str[OID_STR_MAX];
1214 char *dot_str = oid_oid_to_dotstring(node->u.root.absyn->oid, oid_str);
1216 if (dot_str && (dnew = data1_mk_tag_data_wd(p->dh, top,
1217 "schemaIdentifier", mem)))
1219 dnew->u.data.what = DATA1I_oid;
1220 dnew->u.data.data = (char *) nmem_strdup(mem, dot_str);
1221 dnew->u.data.len = strlen(dot_str);
1225 yaz_log(YLOG_DEBUG, "grs_retrieve: element spec");
1226 if (p->comp && (res = process_comp(p->dh, node, p->comp, &p->addinfo,
1229 p->diagnostic = res;
1233 else if (p->comp && !res)
1237 data1_pr_tree(p->dh, node, stdout);
1239 yaz_log(YLOG_DEBUG, "grs_retrieve: transfer syntax mapping");
1241 p->output_format = p->input_format;
1243 assert(p->input_format);
1244 if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_xml))
1247 data1_pr_tree(p->dh, node, stdout);
1249 /* default output encoding for XML is UTF-8 */
1250 data1_iconv(p->dh, mem, node,
1251 p->encoding ? p->encoding : "UTF-8",
1252 data1_get_encoding(p->dh, node));
1254 if (!(p->rec_buf = data1_nodetoidsgml(p->dh, node, selected,
1256 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1259 char *new_buf = (char*) odr_malloc(p->odr, p->rec_len);
1260 memcpy(new_buf, p->rec_buf, p->rec_len);
1261 p->rec_buf = new_buf;
1264 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_grs_1))
1266 data1_iconv(p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1268 if (!(p->rec_buf = data1_nodetogr(p->dh, node, selected,
1270 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1274 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_explain))
1276 /* ensure our data1 tree is UTF-8 */
1277 data1_iconv(p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1279 if (!(p->rec_buf = data1_nodetoexplain(p->dh, node, selected,
1281 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1285 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_summary))
1287 /* ensure our data1 tree is UTF-8 */
1288 data1_iconv(p->dh, mem, node, "UTF-8", data1_get_encoding(p->dh, node));
1289 if (!(p->rec_buf = data1_nodetosummary(p->dh, node, selected,
1291 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1295 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_sutrs))
1298 data1_iconv(p->dh, mem, node, p->encoding,
1299 data1_get_encoding(p->dh, node));
1300 if (!(p->rec_buf = data1_nodetobuf(p->dh, node, selected,
1302 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1305 char *new_buf = (char*) odr_malloc(p->odr, p->rec_len);
1306 memcpy(new_buf, p->rec_buf, p->rec_len);
1307 p->rec_buf = new_buf;
1310 else if (!oid_oidcmp(p->input_format, yaz_oid_recsyn_soif))
1313 data1_iconv(p->dh, mem, node, p->encoding,
1314 data1_get_encoding(p->dh, node));
1315 if (!(p->rec_buf = data1_nodetosoif(p->dh, node, selected,
1317 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1320 char *new_buf = (char*) odr_malloc(p->odr, p->rec_len);
1321 memcpy(new_buf, p->rec_buf, p->rec_len);
1322 p->rec_buf = new_buf;
1327 if (!node->u.root.absyn)
1328 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1331 for (marctab = node->u.root.absyn->marc; marctab;
1332 marctab = marctab->next)
1333 if (marctab->oid && !oid_oidcmp(marctab->oid, p->input_format))
1336 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1340 data1_iconv(p->dh, mem, node, p->encoding,
1341 data1_get_encoding(p->dh, node));
1342 if (!(p->rec_buf = data1_nodetomarc(p->dh, marctab, node,
1343 selected, &p->rec_len)))
1344 p->diagnostic = YAZ_BIB1_RECORD_NOT_AVAILABLE_IN_REQUESTED_SYNTAX;
1347 char *new_buf = (char*) odr_malloc(p->odr, p->rec_len);
1348 memcpy(new_buf, p->rec_buf, p->rec_len);
1349 p->rec_buf = new_buf;
1361 * c-file-style: "Stroustrup"
1362 * indent-tabs-mode: nil
1364 * vim: shiftwidth=4 tabstop=8 expandtab