xelm support enhanced, now supports simpler predicates
[idzebra-moved-to-github.git] / util / xpath.c
1 /* $Id: xpath.c,v 1.1 2003-02-04 12:06:48 pop Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
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
10 version.
11
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
15 for more details.
16
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
20 02111-1307, USA.
21 */
22
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <ctype.h>
28 #include <yaz/nmem.h>
29 #include <zebra_xpath.h>
30
31 char *get_xp_part (char **strs, NMEM mem) {
32   char *str = *strs;
33   char *res = '\0';
34   char *cp = str;
35   char *co;
36   int quoted = 0;
37
38   /* ugly */
39   char *sep = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\" ";
40
41   while (*cp == ' ') {cp++; str++;}
42   if (!strchr("><=] ", *cp)) sep = "><=] ";
43
44   while (*cp && !(strchr(sep,*cp) && !quoted) && (*cp != ']')) {
45     if (*cp =='"') quoted = 1 - quoted;
46     cp++;
47   }  
48   /* removing leading and trailing " */
49   co = cp;
50   if (*str == '"') str++;
51   if (*(cp-1) == '"') cp--;
52   if (str < co) {
53     res = nmem_malloc(mem, cp - str + 1);
54     memcpy (res, str, (cp-str));
55     *(res + (cp-str)) = '\0';
56     *strs = co;
57   }
58
59   return (res);
60 }
61
62
63 struct xpath_predicate *get_xpath_predicate(char *predicates, NMEM mem) {
64   char *p1;
65   char *p2;
66   char *p3;
67   char *p4;
68
69   struct xpath_predicate *r1;
70   struct xpath_predicate *r2;
71   struct xpath_predicate *res = 0;
72
73   char *pr = predicates;
74
75   if ((p1 = get_xp_part(&pr, mem))) {
76     if ((p2 = get_xp_part(&pr, mem))) {
77       if (!strcmp (p2, "and") || !strcmp (p2, "or") || !strcmp (p2, "not")) {
78         r1=nmem_malloc(mem, sizeof(struct xpath_predicate));
79         r1->which = XPATH_PREDICATE_RELATION;
80         r1->u.relation.name = p1;
81         r1->u.relation.op = "";
82         r1->u.relation.value = "";
83         
84         r2 = get_xpath_predicate (pr, mem);
85       
86         res = nmem_malloc(mem, sizeof(struct xpath_predicate));
87         res->which = XPATH_PREDICATE_BOOLEAN;
88         res->u.boolean.op = p2;
89         res->u.boolean.left = r1;
90         res->u.boolean.right = r2;
91
92         return (res);
93       }
94
95       if (strchr("><=] ", *p2)) {
96         r1 = nmem_malloc(mem, sizeof(struct xpath_predicate));
97         
98         r1->which = XPATH_PREDICATE_RELATION;
99         r1->u.relation.name = p1;
100         r1->u.relation.op = p2;
101
102         if ((p3 = get_xp_part(&pr, mem))) {
103           r1->u.relation.value = p3;
104         } else {
105           /* error */
106         }
107       }
108       
109       if ((p4 = get_xp_part(&pr, mem))) {
110         if (!strcmp (p4, "and") || !strcmp (p4, "or") || !strcmp (p4, "not")) {
111
112           r2 = get_xpath_predicate (pr, mem);
113
114           res = nmem_malloc(mem, sizeof(struct xpath_predicate));
115           res->which = XPATH_PREDICATE_BOOLEAN;
116           res->u.boolean.op = p4;
117           res->u.boolean.left = r1;
118           res->u.boolean.right = r2;
119           return (res);
120         } else {
121           /* error */
122         }
123       } else {
124         return (r1);
125       }
126           
127     } else {
128         r1 = nmem_malloc(mem, sizeof(struct xpath_predicate));
129         
130         r1->which = XPATH_PREDICATE_RELATION;
131         r1->u.relation.name = p1;
132         r1->u.relation.op = "";
133         r1->u.relation.value = "";
134
135         return (r1);
136     }
137   }
138   return 0;
139 }
140
141 int parse_xpath_str(const char *xpath_string,
142                     struct xpath_location_step *xpath, NMEM mem)
143 {
144     const char *cp;
145     char *a;
146
147     int no = 0;
148     
149     if (!xpath_string || *xpath_string != '/')
150         return -1;
151     cp = xpath_string;
152
153     while (*cp)
154     {
155         int i = 0;
156         while (*cp && !strchr("/[",*cp))
157         {
158             i++;
159             cp++;
160         }
161         xpath[no].predicate = 0;
162         xpath[no].part = nmem_malloc (mem, i+1);
163         memcpy (xpath[no].part,  cp - i, i);
164         xpath[no].part[i] = 0;
165
166         if (*cp == '[')
167         {
168             cp++;
169             while (*cp == ' ')
170                 cp++;
171
172             a = (char *)cp;
173             xpath[no].predicate = get_xpath_predicate(a, mem);
174             while(*cp && *cp != ']') {
175               cp++;
176             }
177             if (*cp == ']')
178                 cp++;
179         } /* end of ] predicate */
180         no++;
181         if (*cp != '/')
182             break;
183         cp++;
184     }
185     return no;
186 }
187
188 void dump_xp_predicate (struct xpath_predicate *p) {
189     if (p) {
190       if (p->which == XPATH_PREDICATE_RELATION &&
191           p->u.relation.name[0]) {
192         fprintf (stderr, "%s,%s,%s", 
193                  p->u.relation.name,
194                  p->u.relation.op,
195                  p->u.relation.value);
196       } else {
197         fprintf (stderr, "(");
198         dump_xp_predicate(p->u.boolean.left);
199         fprintf (stderr, ") %s (", p->u.boolean.op);
200         dump_xp_predicate(p->u.boolean.right);
201         fprintf (stderr, ")");
202       }
203     }
204 }
205
206 void dump_xp_steps (struct xpath_location_step *xpath, int no) {
207   int i;
208   for (i=0; i<no; i++) {
209     fprintf (stderr, "Step %d: %s   ",i,xpath[i].part);
210     dump_xp_predicate(xpath[i].predicate);
211     fprintf (stderr, "\n");
212   }
213 }
214