1 | /*
|
---|
2 | * Copyright (c) 1995-2000, Index Data.
|
---|
3 | * See the file LICENSE for details.
|
---|
4 | *
|
---|
5 | * d1_if.c : A simple interface for extracting strings from data1_node
|
---|
6 | * tree structures
|
---|
7 | *
|
---|
8 | * $Log$
|
---|
9 | * Revision 1.1 2000/08/03 03:11:32 johnmcp
|
---|
10 | * Added the YAZ toolkit source to the packages directory (for z39.50 stuff)
|
---|
11 | *
|
---|
12 | * Revision 1.5 2000/02/10 13:42:43 adam
|
---|
13 | * Removed C++ comment.
|
---|
14 | *
|
---|
15 | * Revision 1.4 2000/01/06 14:30:56 adam
|
---|
16 | * Minor change - to prevent warnings.
|
---|
17 | *
|
---|
18 | * Revision 1.3 2000/01/06 11:27:02 adam
|
---|
19 | * Minor fix so that this source compiles using Visual C++.
|
---|
20 | *
|
---|
21 | * Revision 1.2 2000/01/04 17:46:17 ian
|
---|
22 | * Added function to count occurences of a tag spec in a data1 tree.
|
---|
23 | *
|
---|
24 | * Revision 1.1 1999/12/21 14:16:19 ian
|
---|
25 | * Changed retrieval module to allow data1 trees with no associated absyn.
|
---|
26 | * Also added a simple interface for extracting values from data1 trees using
|
---|
27 | * a string based tagpath.
|
---|
28 | *
|
---|
29 | */
|
---|
30 |
|
---|
31 | #include <stdio.h>
|
---|
32 | #include <string.h>
|
---|
33 | #include <stdlib.h>
|
---|
34 | #include <string.h>
|
---|
35 |
|
---|
36 | #include <yaz/data1.h>
|
---|
37 | #include <yaz/log.h>
|
---|
38 |
|
---|
39 | #include <string.h>
|
---|
40 |
|
---|
41 |
|
---|
42 | /*
|
---|
43 | * Search for a token in the supplied string up to the supplied list of stop characters or EOL
|
---|
44 | * At the end, return the character causing the break and fill pTokenBuffer with the token string so far
|
---|
45 | * After the scan, *pPosInBuffer will point to the next character after the one causing the break and
|
---|
46 | * pTokenBuffer will contain the actual token
|
---|
47 | */
|
---|
48 | char data1_ScanNextToken(char* pBuffer,
|
---|
49 | char** pPosInBuffer,
|
---|
50 | char* pBreakChars,
|
---|
51 | char* pWhitespaceChars,
|
---|
52 | char* pTokenBuffer)
|
---|
53 | {
|
---|
54 | char* pBuff = pTokenBuffer;
|
---|
55 | *pBuff = '\0';
|
---|
56 |
|
---|
57 | while ( **pPosInBuffer )
|
---|
58 | {
|
---|
59 | if ( strchr(pBreakChars,**pPosInBuffer) != NULL )
|
---|
60 | {
|
---|
61 | /* Current character is a break character */
|
---|
62 | *pBuff++ = '\0';
|
---|
63 | return *((*pPosInBuffer)++);
|
---|
64 | }
|
---|
65 | else
|
---|
66 | {
|
---|
67 | if ( strchr(pWhitespaceChars, **pPosInBuffer) != NULL )
|
---|
68 | (*pPosInBuffer)++;
|
---|
69 | else
|
---|
70 | *pBuff++ = *((*pPosInBuffer)++);
|
---|
71 | }
|
---|
72 | }
|
---|
73 |
|
---|
74 | *pBuff++ = *((*pPosInBuffer)++);
|
---|
75 | return(**pPosInBuffer);
|
---|
76 | }
|
---|
77 |
|
---|
78 | /*
|
---|
79 | * Attempt to find a string value given the specified tagpath
|
---|
80 | *
|
---|
81 | * Need to make this safe by passing in a buffer.....
|
---|
82 | *
|
---|
83 | */
|
---|
84 | char *data1_getNodeValue(data1_node* node, char* pTagPath)
|
---|
85 | {
|
---|
86 | data1_node* n = NULL;
|
---|
87 |
|
---|
88 | n = data1_LookupNode(node, pTagPath );
|
---|
89 |
|
---|
90 | if ( n )
|
---|
91 | {
|
---|
92 | /* n should be a tag node with some data under it.... */
|
---|
93 | if ( n->child )
|
---|
94 | {
|
---|
95 | if ( n->child->which == DATA1N_data )
|
---|
96 | {
|
---|
97 | return n->child->u.data.data;
|
---|
98 | }
|
---|
99 | else
|
---|
100 | {
|
---|
101 | yaz_log(LOG_WARN,"Attempting to lookup data for tagpath: Child node is not a data node");
|
---|
102 | }
|
---|
103 | }
|
---|
104 | else
|
---|
105 | {
|
---|
106 | yaz_log(LOG_WARN,"Found a node matching the tagpath, but it has no child data nodes");
|
---|
107 | }
|
---|
108 | }
|
---|
109 | else
|
---|
110 | {
|
---|
111 | yaz_log(LOG_WARN,"Unable to lookup a node on the specified tag path");
|
---|
112 | }
|
---|
113 |
|
---|
114 | return "";
|
---|
115 | }
|
---|
116 |
|
---|
117 |
|
---|
118 | /* Max length of a tag */
|
---|
119 | #define MAX_TAG_SIZE 50
|
---|
120 |
|
---|
121 | /*
|
---|
122 | * data1_LookupNode : Try and find a node as specified by a tagpath
|
---|
123 | */
|
---|
124 | data1_node *data1_LookupNode(data1_node* node, char* pTagPath)
|
---|
125 | {
|
---|
126 | /* Node matching the pattern in the tagpath */
|
---|
127 | data1_node* matched_node = NULL;
|
---|
128 |
|
---|
129 | /* Current Child node as we search for nodes matching the pattern in the tagpath */
|
---|
130 | data1_node* current_child = node->child;
|
---|
131 |
|
---|
132 | /* Current position in string */
|
---|
133 | char* pCurrCharInPath = pTagPath;
|
---|
134 |
|
---|
135 | /* Work buffer */
|
---|
136 | char Buffer[MAX_TAG_SIZE];
|
---|
137 |
|
---|
138 | /* The tag type of this node */
|
---|
139 | int iTagType = 0;
|
---|
140 |
|
---|
141 | /* for non string tags, the tag value */
|
---|
142 | int iTagValue = 0;
|
---|
143 |
|
---|
144 | /* for string tags, the tag value */
|
---|
145 | char StringTagVal[MAX_TAG_SIZE];
|
---|
146 |
|
---|
147 | /* Which occurence of that tag under this node */
|
---|
148 | int iOccurences=0;
|
---|
149 |
|
---|
150 | /* Character causing a break */
|
---|
151 | char sepchr = '\0';
|
---|
152 | Buffer[0] = '\0';
|
---|
153 | StringTagVal[0] = '\0';
|
---|
154 |
|
---|
155 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",[(."," ", Buffer);
|
---|
156 |
|
---|
157 | if ( sepchr == '[' )
|
---|
158 | {
|
---|
159 | /* Next component in node value is [ TagType, TagVal, TagOccurence ] */
|
---|
160 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ","," ", Buffer);
|
---|
161 | iTagType = atoi(Buffer);
|
---|
162 |
|
---|
163 | /* Occurence is optional... */
|
---|
164 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ",]."," ", Buffer);
|
---|
165 |
|
---|
166 | if ( iTagType == 3 )
|
---|
167 | strcpy(StringTagVal,Buffer);
|
---|
168 | else
|
---|
169 | iTagValue = atoi(Buffer);
|
---|
170 |
|
---|
171 | /* If sepchar was a ',' there should be an instance */
|
---|
172 | if ( sepchr == ',' )
|
---|
173 | {
|
---|
174 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "]."," ", Buffer);
|
---|
175 | iOccurences = atoi(Buffer);
|
---|
176 | }
|
---|
177 |
|
---|
178 | if ( sepchr == ']' )
|
---|
179 | {
|
---|
180 | /* See if we can scan the . for the next component or the end of the line... */
|
---|
181 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
|
---|
182 | }
|
---|
183 | else
|
---|
184 | {
|
---|
185 | yaz_log(LOG_FATAL,"Node does not end with a ]");
|
---|
186 | /* Fatal Error */
|
---|
187 | return(NULL);
|
---|
188 | }
|
---|
189 | }
|
---|
190 | else
|
---|
191 | {
|
---|
192 | /* We have a TagName so Read up to ( or . or EOL */
|
---|
193 | iTagType = 3;
|
---|
194 | strcpy(StringTagVal,Buffer);
|
---|
195 |
|
---|
196 | if ( sepchr == '(' )
|
---|
197 | {
|
---|
198 | /* Read the occurence */
|
---|
199 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, ")"," ", Buffer);
|
---|
200 | iOccurences = atoi(Buffer);
|
---|
201 |
|
---|
202 | /* See if we can find the . at the end of this clause */
|
---|
203 | sepchr = data1_ScanNextToken(pTagPath, &pCurrCharInPath, "."," ", Buffer);
|
---|
204 | }
|
---|
205 |
|
---|
206 | }
|
---|
207 |
|
---|
208 | yaz_log(LOG_DEBUG,"search node for child like [%d,%d,%s,%d]",iTagType,iTagValue,StringTagVal,iOccurences);
|
---|
209 |
|
---|
210 |
|
---|
211 | /* OK.. We have extracted tagtype, Value and Occurence, see if we can find a node */
|
---|
212 | /* Under the current parent matching that description */
|
---|
213 |
|
---|
214 | while ( ( current_child ) && ( matched_node == NULL ) )
|
---|
215 | {
|
---|
216 | if ( current_child->which == DATA1N_tag )
|
---|
217 | {
|
---|
218 | if ( iTagType == 3 )
|
---|
219 | {
|
---|
220 | if ( ( current_child->u.tag.element == NULL ) &&
|
---|
221 | ( strcmp(current_child->u.tag.tag, StringTagVal) == 0 ) )
|
---|
222 | {
|
---|
223 | if ( iOccurences )
|
---|
224 | {
|
---|
225 | /* Everything matched, but not yet found the
|
---|
226 | right occurence of the given tag */
|
---|
227 | iOccurences--;
|
---|
228 | }
|
---|
229 | else
|
---|
230 | {
|
---|
231 | /* We have matched a string tag... Is there more to
|
---|
232 | process? */
|
---|
233 | matched_node = current_child;
|
---|
234 | }
|
---|
235 | }
|
---|
236 | }
|
---|
237 | else /* Attempt to match real element */
|
---|
238 | {
|
---|
239 | yaz_log(LOG_WARN,"Non string tag matching not yet implemented");
|
---|
240 | }
|
---|
241 | }
|
---|
242 | current_child = current_child->next;
|
---|
243 | }
|
---|
244 |
|
---|
245 |
|
---|
246 | /* If there is more... Continue */
|
---|
247 | if ( ( sepchr == '.' ) && ( matched_node ) )
|
---|
248 | {
|
---|
249 | return data1_LookupNode(matched_node, pCurrCharInPath);
|
---|
250 | }
|
---|
251 | else
|
---|
252 | {
|
---|
253 | return matched_node;
|
---|
254 | }
|
---|
255 | }
|
---|
256 |
|
---|
257 | /**
|
---|
258 |
|
---|
259 | data1_CountOccurences
|
---|
260 |
|
---|
261 | Count the number of occurences of the last instance on a tagpath.
|
---|
262 |
|
---|
263 | @param data1_node* node : The root of the tree we wish to look for occurences in
|
---|
264 | @param const char* pTagPath : The tagpath we want to count the occurences of...
|
---|
265 |
|
---|
266 | */
|
---|
267 | int data1_CountOccurences(data1_node* node, char* pTagPath)
|
---|
268 | {
|
---|
269 | int iRetVal = 0;
|
---|
270 | data1_node* n = NULL;
|
---|
271 | data1_node* pParent = NULL;
|
---|
272 |
|
---|
273 | n = data1_LookupNode(node, pTagPath );
|
---|
274 |
|
---|
275 |
|
---|
276 | if ( ( n ) &&
|
---|
277 | ( n->which == DATA1N_tag ) &&
|
---|
278 | ( n->parent ) )
|
---|
279 | {
|
---|
280 | data1_node* current_child;
|
---|
281 | pParent = n->parent;
|
---|
282 |
|
---|
283 | for ( current_child = pParent->child;
|
---|
284 | current_child;
|
---|
285 | current_child = current_child->next )
|
---|
286 | {
|
---|
287 | if ( current_child->which == DATA1N_tag )
|
---|
288 | {
|
---|
289 | if ( current_child->u.tag.element == NULL )
|
---|
290 | {
|
---|
291 | if ( ( n->u.tag.tag ) &&
|
---|
292 | ( current_child->u.tag.tag ) &&
|
---|
293 | ( strcmp(current_child->u.tag.tag, n->u.tag.tag) == 0 ) )
|
---|
294 | {
|
---|
295 | iRetVal++;
|
---|
296 | }
|
---|
297 | }
|
---|
298 | else if ( current_child->u.tag.element == n->u.tag.element )
|
---|
299 | {
|
---|
300 | /* Hmmm... Is the above right for non string tags???? */
|
---|
301 | iRetVal++;
|
---|
302 | }
|
---|
303 | }
|
---|
304 | }
|
---|
305 | }
|
---|
306 |
|
---|
307 | return iRetVal;
|
---|
308 | }
|
---|