]> git.mxchange.org Git - flightgear.git/blob - utils/xmlgrep/xmlgrep.c
532db40ddaa86cf3344547c3f2f74d366f46a85c
[flightgear.git] / utils / xmlgrep / xmlgrep.c
1 #include <stdio.h>
2
3 #define _GNU_SOURCE
4 #include <string.h>
5 #ifndef _MSC_VER
6 # include <strings.h>
7 #else
8 # define strncasecmp strnicmp
9 # include <stdlib.h>
10 #endif
11 #include <assert.h>
12
13 #include "xml.h"
14
15 static const char *_static_root = "/";
16 static const char *_static_element = "*";
17 static unsigned int _fcount = 0;
18 static char **_filenames = 0;
19 static char *_element = 0;
20 static char *_value = 0;
21 static char *_root = 0;
22 static char *_print = 0;
23 static char *_attribute = 0;
24 static int print_filenames = 0;
25
26 static void free_and_exit(int i);
27
28 #define SHOW_NOVAL(opt) \
29 { \
30     printf("option '%s' requires a value\n\n", (opt)); \
31     free_and_exit(-1); \
32 }
33
34 void
35 show_help ()
36 {
37     printf("usage: xmlgrep [options] [file ...]\n\n");
38     printf("Options:\n");
39     printf("\t-h\t\tshow this help message\n");
40     printf("\t-a <string>\tprint this attribute as the output\n");
41     printf("\t-e <id>\t\tshow sections that contain this element\n");
42     printf("\t-p <id>\t\tprint this element as the output\n");
43     printf("\t-r <path>\tspecify the XML search root\n");
44     printf("\t-v <string>\tfilter sections that contain this vale\n\n");
45     printf(" To print the contents of the 'type' element of the XML section ");
46     printf("that begins\n at '/printer/output' use the following command:\n\n");
47     printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
48     printf(" To filter 'output' elements under '/printer' that have attribute");
49     printf(" 'n' set to '1'\n use the following command:\n\n");
50     printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
51     printf(" To filter out sections that contain the 'driver' element with ");
52     printf("'generic' as\n it's value use the following command:");
53     printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
54     printf("\n\n");
55     free_and_exit(0);
56 }
57
58 void
59 free_and_exit(int ret)
60 {
61     if (_root && _root != _static_root) free(_root);
62     if (_element && _element != _static_element) free(_element);
63     if (_value) free(_value);
64     if (_print) free(_print);
65     if (_attribute) free(_attribute);
66     if (_filenames)
67     {
68         unsigned int i;
69         for (i=0; i < _fcount; i++)
70         {
71             if (_filenames[i])
72             {
73                 if (print_filenames) printf("%s\n", _filenames[i]);
74                 free(_filenames[i]);
75             }
76         }
77         free(_filenames);
78     }
79  
80     exit(ret);
81 }
82
83 int
84 parse_option(char **args, int n, int max)
85 {
86     char *opt, *arg = 0;
87     unsigned int alen = 0;
88     unsigned int olen;
89
90     opt = args[n];
91     if (strncmp(opt, "--", 2) == 0)
92         opt++;
93
94     if ((arg = strchr(opt, '=')) != NULL)
95     {
96         *arg++ = 0;
97     }
98     else if (++n < max)
99     {
100         arg = args[n];
101 #if 0
102         if (arg && arg[0] == '-')
103             arg = 0;
104 #endif
105     }
106
107     olen = strlen(opt);
108     if (strncmp(opt, "-help", olen) == 0)
109     {
110         show_help();
111     }
112     else if (strncmp(opt, "-root", olen) == 0)
113     {
114         if (arg == 0) SHOW_NOVAL(opt);
115         alen = strlen(arg)+1;
116         _root = malloc(alen);
117         memcpy(_root, arg, alen);
118         return 2;
119     }
120     else if (strncmp(opt, "-element", olen) == 0)
121     {
122         if (arg == 0) SHOW_NOVAL(opt);
123         alen = strlen(arg)+1;
124         _element = malloc(alen);
125         memcpy(_element, arg, alen);
126         return 2;
127     }
128     else if (strncmp(opt, "-value", olen) == 0)
129     {
130         if (arg == 0) SHOW_NOVAL(opt);
131         alen = strlen(arg)+1;
132         _value = malloc(alen);
133         memcpy(_value, arg, alen);
134         return 2;
135     }
136     else if (strncmp(opt, "-print", olen) == 0)
137     {
138         if (arg == 0) SHOW_NOVAL(opt);
139         alen = strlen(arg)+1;
140         _print = malloc(alen);
141         memcpy(_print, arg, alen);
142         return 2;
143     }
144     else if (strncmp(opt, "-attribute", olen) == 0)
145     {
146         if (arg == 0) SHOW_NOVAL(opt);
147         alen = strlen(arg)+1;
148         _attribute = malloc(alen);
149         memcpy(_attribute, arg, alen);
150         return 2;
151     }
152     else if (strncmp(opt, "-list-filenames", olen) == 0)
153     { /* undocumented test argument */
154         print_filenames = 1;
155         return 1;
156     }
157     else if (opt[0] == '-')
158     {
159         printf("Unknown option %s\n", opt);
160         free_and_exit(-1);
161     }
162     else
163     {
164         int pos = _fcount++;
165         if (_filenames == 0)
166         {
167             _filenames = (char **)malloc(sizeof(char*));
168         }
169         else
170         {
171             char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
172             if (ptr == 0)
173             {
174                 printf("Out of memory.\n\n");
175                 free_and_exit(-1);
176             }
177            _filenames = ptr;
178         }
179
180         alen = strlen(opt)+1;
181         _filenames[pos] = malloc(alen);
182         memcpy(_filenames[pos], opt, alen);
183     }
184
185     return 1;
186 }
187
188 void walk_the_tree(size_t num, void *xid, char *tree)
189 {
190     unsigned int i, no_elements;
191
192     if (!tree)                                  /* last node from the tree */
193     {
194         void *xmid = xmlMarkId(xid);
195         if (xmid && _print)
196         {
197             no_elements = xmlNodeGetNum(xid, _print);
198             for (i=0; i<no_elements; i++)
199             {
200                 if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
201                 {
202                     char value[1024];
203
204                     xmlCopyString(xmid, (char *)&value, 1024);
205                     if (_value && _attribute)
206                     {
207                        if (!xmlAttributeCompareString(xmid, _attribute, _value))
208                        {
209                           printf("%s: <%s %s=\"%s\">%s</%s>\n",
210                                  _filenames[num], _print, _attribute, _value,
211                                                   value, _print);
212                        }
213                     }
214                     else
215                     {
216                        printf("%s: <%s>%s</%s>\n",
217                               _filenames[num], _print, value, _print);
218                     }
219                 }
220             }
221             free(xmid);
222         }
223         else if (xmid && _value)
224         {
225             no_elements = xmlNodeGetNum(xmid, _element);
226             for (i=0; i<no_elements; i++)
227             {
228                 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
229                 {
230                     char nodename[64];
231
232                     xmlNodeCopyName(xmid, (char *)&nodename, 64);
233                     if (xmlCompareString(xmid, _value) == 0)
234                     {
235                         printf("%s: <%s>%s</%s>\n",
236                                _filenames[num], nodename, _value, nodename);
237                     }
238                 }
239             }
240             free(xmid);
241         }
242         else if (xmid && _element)
243         {
244             char parentname[64];
245
246             xmlNodeCopyName(xid, (char *)&parentname, 64);
247
248             no_elements = xmlNodeGetNum(xmid, _element);
249             for (i=0; i<no_elements; i++)
250             {
251                 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
252                 {
253                     char nodename[64];
254
255                     xmlNodeCopyName(xmid, (char *)&nodename, 64);
256                     if (strncasecmp((char *)&nodename, _element, 64) == 0)
257                     {
258                         char value[64];
259                         xmlCopyString(xmid, (char *)&value, 64);
260                         printf("%s: <%s> <%s>%s</%s> </%s>\n",
261                                 _filenames[num], parentname, nodename, value,
262                                                  nodename, parentname);
263                     }
264                 }
265             }
266         }
267         else printf("Error executing xmlMarkId\n");
268     }
269     else if (xid)                        /* walk the rest of the tree */
270     {
271         char *elem, *next;
272         void *xmid;
273
274         elem = tree;
275         if (*elem == '/') elem++;
276
277         next = strchr(elem, '/');
278         
279         xmid = xmlMarkId(xid);
280         if (xmid)
281         {
282             if (next)
283             {
284                *next++ = 0;
285             }
286
287             no_elements = xmlNodeGetNum(xid, elem);
288             for (i=0; i<no_elements; i++)
289             {
290                 if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
291                     walk_the_tree(num, xmid, next);
292             }
293
294             if (next)
295             {
296                *--next = '/';
297             }
298
299             free(xmid);
300         }
301         else printf("Error executing xmlMarkId\n");
302     }
303 }
304
305
306 void grep_file(unsigned num)
307 {
308     void *xid;
309
310     xid = xmlOpen(_filenames[num]);
311     if (xid)
312     {
313        void *xrid = xmlMarkId(xid);
314        walk_the_tree(num, xrid, _root);
315        free(xrid);
316     }
317     else
318     {
319         fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
320     }
321
322     xmlClose(xid);
323 }
324
325 int
326 main (int argc, char **argv)
327 {
328     unsigned int i;
329
330     if (argc == 1)
331         show_help();
332
333     for (i=1; i<argc;)
334     {
335         int ret = parse_option(argv, i, argc);
336         i += ret;
337     }
338
339     if (_root == 0) _root = (char *)_static_root;
340     if (_element == 0) _element = (char *)_static_element;
341
342     for (i=0; i<_fcount; i++)
343         grep_file(i);
344
345     free_and_exit(0);
346
347     return 0;
348 }