+int d1_check_xpath_predicate(data1_node *n, struct xpath_predicate *p)
+{
+ int res = 1;
+ char *attname;
+ data1_xattr *attr;
+
+ if (!p) {
+ return 1;
+ } else {
+ if (p->which == XPATH_PREDICATE_RELATION) {
+ if (p->u.relation.name[0]) {
+ if (*p->u.relation.name != '@') {
+ yaz_log(LOG_WARN,
+ " Only attributes (@) are supported in xelm xpath predicates");
+ yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
+ return (1);
+ }
+ attname = p->u.relation.name + 1;
+ res = 0;
+ /* looking for the attribute with a specified name */
+ for (attr = n->u.tag.attributes; attr; attr = attr->next) {
+ yaz_log(LOG_DEBUG," - attribute %s <-> %s", attname, attr->name );
+
+ if (!strcmp(attr->name, attname)) {
+ if (p->u.relation.op[0]) {
+ if (*p->u.relation.op != '=') {
+ yaz_log(LOG_WARN,
+ "Only '=' relation is supported (%s)",p->u.relation.op);
+ yaz_log(LOG_WARN, "predicate %s ignored", p->u.relation.name);
+ res = 1; break;
+ } else {
+ yaz_log(LOG_DEBUG," - value %s <-> %s",
+ p->u.relation.value, attr->value );
+ if (!strcmp(attr->value, p->u.relation.value)) {
+ res = 1; break;
+ }
+ }
+ } else {
+ /* attribute exists, no value specified */
+ res = 1; break;
+ }
+ }
+ }
+ yaz_log(LOG_DEBUG, "return %d", res);
+ return res;
+ } else {
+ return 1;
+ }
+ }
+ else if (p->which == XPATH_PREDICATE_BOOLEAN) {
+ if (!strcmp(p->u.boolean.op,"and")) {
+ return d1_check_xpath_predicate(n, p->u.boolean.left)
+ && d1_check_xpath_predicate(n, p->u.boolean.right);
+ }
+ else if (!strcmp(p->u.boolean.op,"or")) {
+ return (d1_check_xpath_predicate(n, p->u.boolean.left)
+ || d1_check_xpath_predicate(n, p->u.boolean.right));
+ } else {
+ yaz_log(LOG_WARN, "Unknown boolean relation %s, ignored",p->u.boolean.op);
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+/* *ostrich*
+
+New function, looking for xpath "element" definitions in abs, by
+tagpath, using a kind of ugly regxp search.The DFA was built while
+parsing abs, so here we just go trough them and try to match
+against the given tagpath. The first matching entry is returned.
+
+pop, 2002-12-13
+
+Added support for enhanced xelm. Now [] predicates are considered
+as well, when selecting indexing rules... (why the hell it's called
+termlist???)
+
+pop, 2003-01-17
+
+*/
+
+data1_termlist *xpath_termlist_by_tagpath(char *tagpath, data1_node *n)
+{
+ data1_absyn *abs = n->root->u.root.absyn;
+ data1_xpelement *xpe = abs->xp_elements;
+ data1_node *nn;
+#ifdef ENHANCED_XELM
+ struct xpath_location_step *xp;
+
+#endif
+ char *pexpr = xmalloc(strlen(tagpath)+2);
+ int ok = 0;
+
+ sprintf (pexpr, "%s\n", tagpath);
+ yaz_log(LOG_DEBUG,"Checking tagpath %s",tagpath);
+ while (xpe)
+ {
+ struct DFA_state **dfaar = xpe->dfa->states;
+ struct DFA_state *s=dfaar[0];
+ struct DFA_tran *t;
+ const char *p;
+ int i;
+ unsigned char c;
+ int start_line = 1;
+
+ c = *pexpr++; t = s->trans; i = s->tran_no;
+ if ((c >= t->ch[0] && c <= t->ch[1]) || (!t->ch[0])) {
+ p = pexpr;
+ do {
+ if ((s = dfaar[t->to])->rule_no &&
+ (start_line || s->rule_nno)) {
+ ok = 1;
+ break;
+ }
+ for (t=s->trans, i=s->tran_no; --i >= 0; t++) {
+ if ((unsigned) *p >= t->ch[0] && (unsigned) *p <= t->ch[1])
+ break;
+ }
+ p++;
+ } while (i >= 0);
+ }
+ if (ok)
+ yaz_log(LOG_DEBUG," xpath match %s",xpe->xpath_expr);
+ else
+ yaz_log(LOG_DEBUG," xpath no match %s",xpe->xpath_expr);
+
+ pexpr--;
+ if (ok) {
+#ifdef ENHANCED_XELM
+ /* we have to check the perdicates up to the root node */
+ xp = xpe->xpath;
+
+ /* find the first tag up in the node structure */
+ nn = n; while (nn && nn->which != DATA1N_tag) {
+ nn = nn->parent;
+ }
+
+ /* go from inside out in the node structure, while going
+ backwards trough xpath location steps ... */
+ for (i=xpe->xpath_len - 1; i>0; i--) {
+
+ yaz_log(LOG_DEBUG,"Checking step %d: %s on tag %s",
+ i,xp[i].part,nn->u.tag.tag);
+
+ if (!d1_check_xpath_predicate(nn, xp[i].predicate)) {
+ yaz_log(LOG_DEBUG," Predicates didn't match");
+ ok = 0;
+ break;
+ }
+
+ if (nn->which == DATA1N_tag) {
+ nn = nn->parent;
+ }
+ }
+#endif
+ if (ok) {
+ break;
+ }
+ }
+ xpe = xpe->next;
+ }
+
+ xfree(pexpr);
+
+ if (ok) {
+ yaz_log(LOG_DEBUG,"Got it");
+ return xpe->termlists;
+ } else {
+ return NULL;
+ }
+}
+