9 # define strncasecmp strnicmp
16 static const char *_static_root = "/";
17 static const char *_static_element = "*";
18 static unsigned int _fcount = 0;
19 static char **_filenames = 0;
20 static char *_element = 0;
21 static char *_value = 0;
22 static char *_root = 0;
23 static char *_print = 0;
24 static char *_attribute = 0;
25 static int print_filenames = 0;
27 static void free_and_exit(int i);
29 #define NODE_NAME_LEN 256
30 #define STRING_LEN 2048
32 #define SHOW_NOVAL(opt) \
34 printf("option '%s' requires a value\n\n", (opt)); \
41 printf("usage: xmlgrep [options] [file ...]\n\n");
43 printf("\t-h\t\tshow this help message\n");
44 printf("\t-a <string>\tprint this attribute as the output\n");
45 printf("\t-e <id>\t\tshow sections that contain this element\n");
46 printf("\t-p <id>\t\tprint this element as the output\n");
47 printf("\t-r <path>\tspecify the XML search root\n");
48 printf("\t-v <string>\tfilter sections that contain this vale\n\n");
49 printf(" To print the contents of the 'type' element of the XML section ");
50 printf("that begins\n at '/printer/output' use the following command:\n\n");
51 printf("\txmlgrep -r /printer/output -p type sample.xml\n\n");
52 printf(" To filter 'output' elements under '/printer' that have attribute");
53 printf(" 'n' set to '1'\n use the following command:\n\n");
54 printf("\txmlgrep -r /printer -p output -a n -v 1 sample.xml\n\n");
55 printf(" To filter out sections that contain the 'driver' element with ");
56 printf("'generic' as\n it's value use the following command:");
57 printf("\n\n\txmlgrep -r /printer/output -e driver -v generic sample.xml");
63 free_and_exit(int ret)
65 if (_root && _root != _static_root) free(_root);
66 if (_element && _element != _static_element) free(_element);
67 if (_value) free(_value);
68 if (_print) free(_print);
69 if (_attribute) free(_attribute);
73 for (i=0; i < _fcount; i++)
77 if (print_filenames) printf("%s\n", _filenames[i]);
88 parse_option(char **args, int n, int max)
91 unsigned int alen = 0;
95 if (strncmp(opt, "--", 2) == 0)
98 if ((arg = strchr(opt, '=')) != NULL)
106 if (arg && arg[0] == '-')
112 if (strncmp(opt, "-help", olen) == 0)
116 else if (strncmp(opt, "-root", olen) == 0)
118 if (arg == 0) SHOW_NOVAL(opt);
119 alen = strlen(arg)+1;
120 _root = malloc(alen);
121 memcpy(_root, arg, alen);
124 else if (strncmp(opt, "-element", olen) == 0)
126 if (arg == 0) SHOW_NOVAL(opt);
127 alen = strlen(arg)+1;
128 _element = malloc(alen);
129 memcpy(_element, arg, alen);
132 else if (strncmp(opt, "-value", olen) == 0)
134 if (arg == 0) SHOW_NOVAL(opt);
135 alen = strlen(arg)+1;
136 _value = malloc(alen);
137 memcpy(_value, arg, alen);
140 else if (strncmp(opt, "-print", olen) == 0)
142 if (arg == 0) SHOW_NOVAL(opt);
143 alen = strlen(arg)+1;
144 _print = malloc(alen);
145 memcpy(_print, arg, alen);
148 else if (strncmp(opt, "-attribute", olen) == 0)
150 if (arg == 0) SHOW_NOVAL(opt);
151 alen = strlen(arg)+1;
152 _attribute = malloc(alen);
153 memcpy(_attribute, arg, alen);
156 else if (strncmp(opt, "-list-filenames", olen) == 0)
157 { /* undocumented test argument */
161 else if (opt[0] == '-')
163 printf("Unknown option %s\n", opt);
171 _filenames = (char **)malloc(sizeof(char*));
175 char **ptr = (char **)realloc(_filenames, _fcount*sizeof(char*));
178 printf("Out of memory.\n\n");
184 alen = strlen(opt)+1;
185 _filenames[pos] = malloc(alen);
186 memcpy(_filenames[pos], opt, alen);
192 void walk_the_tree(size_t num, void *xid, char *tree)
194 unsigned int i, no_elements;
196 if (!tree) /* last node from the tree */
198 void *xmid = xmlMarkId(xid);
201 no_elements = xmlNodeGetNum(xid, _print);
202 for (i=0; i<no_elements; i++)
204 if (xmlNodeGetPos(xid, xmid, _print, i) != 0)
206 char value[STRING_LEN];
208 xmlCopyString(xmid, (char *)&value, STRING_LEN);
209 if (_value && _attribute)
211 if (!xmlAttributeCompareString(xmid, _attribute, _value))
213 printf("%s: <%s %s=\"%s\">%s</%s>\n",
214 _filenames[num], _print, _attribute, _value,
220 printf("%s: <%s>%s</%s>\n",
221 _filenames[num], _print, value, _print);
227 else if (xmid && _value)
229 no_elements = xmlNodeGetNum(xmid, _element);
230 for (i=0; i<no_elements; i++)
232 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
234 char nodename[NODE_NAME_LEN];
236 xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
237 if (xmlCompareString(xmid, _value) == 0)
239 printf("%s: <%s>%s</%s>\n",
240 _filenames[num], nodename, _value, nodename);
246 else if (xmid && _element)
248 char parentname[NODE_NAME_LEN];
250 xmlNodeCopyName(xid, (char *)&parentname, NODE_NAME_LEN);
252 no_elements = xmlNodeGetNum(xmid, _element);
253 for (i=0; i<no_elements; i++)
255 if (xmlNodeGetPos(xid, xmid, _element, i) != 0)
257 char nodename[NODE_NAME_LEN];
259 xmlNodeCopyName(xmid, (char *)&nodename, NODE_NAME_LEN);
260 if (!strncasecmp((char*)&nodename, _element, NODE_NAME_LEN))
262 char value[NODE_NAME_LEN];
263 xmlCopyString(xmid, (char *)&value, NODE_NAME_LEN);
264 printf("%s: <%s> <%s>%s</%s> </%s>\n",
265 _filenames[num], parentname, nodename, value,
266 nodename, parentname);
271 else printf("Error executing xmlMarkId\n");
273 else if (xid) /* walk the rest of the tree */
279 if (*elem == '/') elem++;
281 next = strchr(elem, '/');
283 xmid = xmlMarkId(xid);
291 no_elements = xmlNodeGetNum(xid, elem);
292 for (i=0; i<no_elements; i++)
294 if (xmlNodeGetPos(xid, xmid, elem, i) != 0)
295 walk_the_tree(num, xmid, next);
305 else printf("Error executing xmlMarkId\n");
310 void grep_file(unsigned num)
314 xid = xmlOpen(_filenames[num]);
317 void *xrid = xmlMarkId(xid);
320 walk_the_tree(num, xrid, _root);
322 r = xmlErrorGetNo(xrid, 0);
325 size_t n = xmlErrorGetLineNo(xrid, 0);
326 char *s = xmlErrorGetString(xrid, 1); /* clear the error */
327 printf("Error #%i at line %u: '%s'\n", r, n, s);
334 fprintf(stderr, "Error reading file '%s'\n", _filenames[num]);
341 main (int argc, char **argv)
350 int ret = parse_option(argv, i, argc);
354 if (_root == 0) _root = (char *)_static_root;
355 if (_element == 0) _element = (char *)_static_element;
357 for (i=0; i<_fcount; i++)