1 /* This file is part of the YAZ toolkit.
2 * Copyright (C) 1995-2013 Index Data
3 * See the file LICENSE for details.
7 * \brief Implements SRU 2.0 facets
16 #include <yaz/wrbuf.h>
18 #include <libxml/parser.h>
19 #include <libxml/tree.h>
24 #include <yaz/pquery.h>
25 #include <yaz/facet.h>
27 static void insert_field(WRBUF w, const char *field, size_t length,
30 const char *cp0 = wrbuf_cstr(w);
35 const char *cp2 = strstr(cp, "@attr 1=");
39 if (!strncmp(cp, field, length) &&
40 (cp[length] == ' ' || cp[length] == ',' || cp[length] == '\0'))
45 wrbuf_insert(w, cp - cp0, attr, strlen(attr));
46 wrbuf_insert(w, cp - cp0, " ", 1);
49 while (*cp && *cp != ',')
54 wrbuf_puts(w, "@attr 1=");
55 wrbuf_write(w, field, length);
60 void yaz_sru_facet_request(ODR o, Z_FacetList **facetList, const char **limit,
61 const char **start, const char **sort)
63 if (o->direction == ODR_ENCODE)
65 Z_FacetList *fl = *facetList;
68 WRBUF w_limit = wrbuf_alloc();
69 WRBUF w_start = wrbuf_alloc();
70 WRBUF w_sort = wrbuf_alloc();
72 for (i = 0; i < fl->num; i++)
74 struct yaz_facet_attr av;
75 yaz_facet_attr_init(&av);
76 yaz_facet_attr_get_z_attributes(fl->elements[i]->attributes,
82 wrbuf_printf(w_limit, "%d", av.limit);
84 wrbuf_printf(w_limit, ":%s", av.useattr);
85 wrbuf_puts(w_limit, ",");
87 if (av.start || av.useattr)
89 wrbuf_printf(w_start, "%d", av.start);
91 wrbuf_printf(w_start, ":%s", av.useattr);
92 wrbuf_puts(w_start, ",");
94 if (av.sortorder == 1)
96 /* allow sorting per field */
97 /* not really according to spec */
98 wrbuf_printf(w_sort, "alphanumeric");
100 wrbuf_printf(w_sort, ":%s", av.useattr);
101 wrbuf_puts(w_sort, ",");
105 if (wrbuf_len(w_limit) > 1)
107 wrbuf_cut_right(w_limit, 1); /* remove , */
108 *limit = odr_strdup(o, wrbuf_cstr(w_limit));
110 if (wrbuf_len(w_start) > 1)
112 wrbuf_cut_right(w_start, 1); /* remove , */
113 *start = odr_strdup(o, wrbuf_cstr(w_start));
115 if (wrbuf_len(w_sort) > 1)
117 wrbuf_cut_right(w_sort, 1); /* remove , */
118 *sort = odr_strdup(o, wrbuf_cstr(w_sort));
120 wrbuf_destroy(w_limit);
121 wrbuf_destroy(w_start);
122 wrbuf_destroy(w_sort);
125 else if (o->direction == ODR_DECODE)
127 WRBUF w = wrbuf_alloc();
131 const char *cp = *limit;
134 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
137 if (*cp == ':') /* field name follows */
140 const char *cp0 = ++cp;
141 while (*cp && *cp != ',')
143 sprintf(tmp, "@attr 3=%d", val);
144 insert_field(w, cp0, cp - cp0, tmp);
153 const char *cp = *start;
156 while (sscanf(cp, "%d%n", &val, &nor) >= 1 && nor > 0)
159 if (*cp == ':') /* field name follows */
162 const char *cp0 = ++cp;
163 while (*cp && *cp != ',')
165 sprintf(tmp, "@attr 4=%d", val);
166 insert_field(w, cp0, cp - cp0, tmp);
176 const char *cp = *sort;
180 const char *cp0 = cp;
181 while (*cp && *cp != ':' && *cp != ',')
183 if (!strncmp(cp0, "alphanumeric", cp - cp0))
185 if (*cp == ':') /* field name follows */
189 while (*cp && *cp != ',')
191 sprintf(tmp, "@attr 2=%d", val);
192 insert_field(w, cp0, cp - cp0, tmp);
201 *facetList = yaz_pqf_parse_facet_list(o, wrbuf_cstr(w));
209 void yaz_sru_facet_response(ODR o, Z_FacetList **facetList, xmlNodePtr n)
211 if (o->direction == ODR_ENCODE)
213 Z_FacetList *fl = *facetList;
218 "http://docs.oasis-open.org/ns/search-ws/facetedResults";
219 xmlNode *p1 = xmlNewChild(n, 0, BAD_CAST "facetedResults", 0);
220 xmlNsPtr ns_fr = xmlNewNs(p1, BAD_CAST ns, BAD_CAST "fr");
222 for (i = 0; i < fl->num; i++)
224 Z_FacetField *ff = fl->elements[i];
225 xmlNode *p2 = xmlNewChild(p1, 0, BAD_CAST "facet", 0);
228 struct yaz_facet_attr av;
229 yaz_facet_attr_init(&av);
230 yaz_facet_attr_get_z_attributes(ff->attributes, &av);
231 add_xsd_string(p2, "index", av.useattr);
232 p3 = xmlNewChild(p2, 0, BAD_CAST "terms", 0);
233 for (j = 0; j < ff->num_terms; j++)
235 Z_FacetTerm *ft = ff->terms[j];
236 Z_Term *zt = ft->term;
237 xmlNode *p4 = xmlNewChild(p3, 0, BAD_CAST "term", 0);
238 if (zt->which == Z_Term_general)
239 add_xsd_string_n(p4, "actualTerm",
240 (char *) zt->u.general->buf,
243 add_xsd_integer(p4, "count", ft->count);
248 else if (o->direction == ODR_DECODE)
250 Z_FacetList *fl = (Z_FacetList *) odr_malloc(o, sizeof(*fl));
254 for (p1 = n->children; p1; p1 = p1->next)
255 if (yaz_match_xsd_element(p1, "facet"))
261 fl->elements = (Z_FacetField **)
262 odr_malloc(o, sizeof(*fl->elements) * fl->num);
263 for (p1 = n->children; p1; p1 = p1->next)
264 if (yaz_match_xsd_element(p1, "facet"))
266 char *index_name = 0;
267 xmlNode *p_terms = 0;
268 xmlNode *p2 = p1->children;
269 Z_FacetField *ff = (Z_FacetField *)
270 odr_malloc(o, sizeof(*ff));
271 fl->elements[i++] = ff;
275 for (; p2; p2 = p2->next)
277 if (yaz_match_xsd_string(p2, "index", o, &index_name))
279 else if (yaz_match_xsd_element(p2, "terms"))
284 Z_AttributeList *al =
285 (Z_AttributeList*) odr_malloc(o, sizeof(*al));
286 Z_ComplexAttribute *ca =
287 (Z_ComplexAttribute *) odr_malloc(o, sizeof(*ca));
288 Z_AttributeElement *ae =
289 (Z_AttributeElement *) odr_malloc(o, sizeof(*ae));
290 al->num_attributes = 1;
291 al->attributes = (Z_AttributeElement **)
292 odr_malloc(o, sizeof(*al->attributes));
293 al->attributes[0] = ae;
294 ae->attributeSet = 0;
295 ae->attributeType = odr_intdup(o, 1);
296 ae->which = Z_AttributeValue_complex;
297 ae->value.complex = ca;
298 ca->num_semanticAction = 0;
299 ca->semanticAction = 0;
301 ca->list = (Z_StringOrNumeric **)
302 odr_malloc(o, sizeof(*ca->list));
303 ca->list[0] = (Z_StringOrNumeric *)
304 odr_malloc(o, sizeof(**ca->list));
305 ca->list[0]->which = Z_StringOrNumeric_string;
306 ca->list[0]->u.string = index_name;
313 for (p = p_terms->children; p; p = p->next)
315 if (yaz_match_xsd_element(p, "term"))
319 ff->terms = (Z_FacetTerm **)
321 sizeof(*ff->terms) * ff->num_terms);
322 for (p = p_terms->children; p; p = p->next)
324 if (yaz_match_xsd_element(p, "term"))
328 xmlNode *p2 = p->children;
329 for (; p2; p2 = p2->next)
331 if (yaz_match_xsd_string(p2, "actualTerm", o,
334 else if (yaz_match_xsd_integer(p2, "count", o,
341 facet_term_create_cstr(o, cstr, *count);
346 if (ff->num_terms == 0)
361 * c-file-style: "Stroustrup"
362 * indent-tabs-mode: nil
364 * vim: shiftwidth=4 tabstop=8 expandtab