ae07689e239f4a44168d91b396f4a649fc68d134
[lttng-tools.git] / tests / regression / tools / mi / extract_xml.c
1 /*
2 * Copyright (C) 2014 - Jonathan Rajotte <jonathan.r.julien@gmail.com>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 */
16
17 /*
18 * Usage: extract_xml [-v|-e] xml_path xpath_expression
19 * Evaluate XPath expression and prints result node set.
20 * args[1] path to the xml file
21 * args[2] xpath expression to extract
22 * If -e look if node exist return "true" else nothing
23 * If -v is set the name of the node will appear with his value delimited by
24 * a semicolon(;)
25 * Ex:
26 * Command:extract_xml ../file.xml /test/node/text()
27 * Output:
28 * a
29 * b
30 * c
31 * With -v
32 * node;a;
33 * node;b;
34 * node;c;
35 */
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <assert.h>
40 #include <unistd.h>
41
42 #include <libxml/tree.h>
43 #include <libxml/parser.h>
44 #include <libxml/xpath.h>
45 #include <libxml/xpathInternals.h>
46 #include <common/defaults.h>
47
48 #if defined(LIBXML_XPATH_ENABLED)
49
50
51 int opt_verbose;
52 int node_exist;
53
54 /**
55 * print_xpath_nodes:
56 * nodes: the nodes set.
57 * output: the output file handle.
58 *
59 * Print the node content to the file
60 */
61 static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output)
62 {
63 int ret = 0;
64 int size;
65 int i;
66
67 xmlNodePtr cur;
68 xmlChar *node_child_value_string = NULL;
69
70 assert(output);
71 size = (nodes) ? nodes->nodeNr : 0;
72
73 for (i = 0; i < size; ++i) {
74 assert(nodes->nodeTab[i]);
75
76 if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
77 fprintf(stderr, "ERR:%s\n",
78 "This executable does not support xml namespacing\n");
79 ret = -1;
80 goto end;
81 } else if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
82 cur = nodes->nodeTab[i];
83
84 if (xmlChildElementCount(cur) == 0) {
85 if (xmlNodeIsText(cur->children)) {
86 node_child_value_string = xmlNodeListGetString(doc,
87 cur->children, 1);
88 if (node_exist) {
89 fprintf(output, "true\n");
90 } else if (opt_verbose) {
91 fprintf(output, "%s;%s;\n", cur->name,
92 node_child_value_string);
93 } else {
94 fprintf(output, "%s\n",
95 node_child_value_string);
96 }
97 xmlFree(node_child_value_string);
98 } else {
99 /* We don't want to print non-final element */
100 if (node_exist) {
101 fprintf(output, "true\n");
102 } else {
103 fprintf(stderr, "ERR:%s\n",
104 "Xpath expression return non-final xml element");
105 ret = -1;
106 goto end;
107 }
108 }
109 } else {
110 if (node_exist) {
111 fprintf(output, "true\n");
112 } else {
113 /* We don't want to print non-final element */
114 fprintf(stderr, "ERR:%s\n",
115 "Xpath expression return non-final xml element");
116 ret = -1;
117 goto end;
118 }
119 }
120
121 } else {
122 cur = nodes->nodeTab[i];
123 if (node_exist) {
124 fprintf(output, "true\n");
125 } else if (opt_verbose) {
126 fprintf(output, "%s;%s;\n", cur->parent->name, cur->content);
127 } else {
128 fprintf(output, "%s\n", cur->content);
129 }
130 }
131 }
132 /* Command Success */
133 ret = 0;
134
135 end:
136 return ret;
137 }
138
139 static int register_lttng_namespace(xmlXPathContextPtr xpathCtx)
140 {
141 int ret;
142 xmlChar *prefix;
143 xmlChar *ns = NULL;
144
145 prefix = xmlCharStrdup("lttng");
146 if (!prefix) {
147 ret = -1;
148 goto end;
149 }
150
151 ns = xmlCharStrdup(DEFAULT_LTTNG_MI_NAMESPACE);
152 if (!ns) {
153 ret = -1;
154 goto end;
155 }
156
157 ret = xmlXPathRegisterNs(xpathCtx, prefix, ns);
158 end:
159 xmlFree(prefix);
160 xmlFree(ns);
161 return ret;
162 }
163
164 /*
165 * Extract element corresponding to xpath
166 * xml_path The path to the xml file
167 * xpath: The xpath to evaluate.
168 *
169 * Evaluate an xpath expression onto an xml file.
170 * and print the result one by line.
171 *
172 * Returns 0 on success and a negative value otherwise.
173 */
174 static int extract_xpath(const char *xml_path, const xmlChar *xpath)
175 {
176 int ret;
177 xmlDocPtr doc = NULL;
178 xmlXPathContextPtr xpathCtx = NULL;
179 xmlXPathObjectPtr xpathObj = NULL;
180
181 assert(xml_path);
182 assert(xpath);
183
184 /* Parse the xml file */
185 doc = xmlParseFile(xml_path);
186 if (!doc) {
187 fprintf(stderr, "ERR parsing: xml file invalid \"%s\"\n", xml_path);
188 return -1;
189 }
190
191 /* Initialize a xpath context */
192 xpathCtx = xmlXPathNewContext(doc);
193 if (!xpathCtx) {
194 fprintf(stderr, "ERR: XPath context invalid\n");
195 xmlFreeDoc(doc);
196 return -1;
197 }
198
199 /* Register the LTTng MI namespace */
200 ret = register_lttng_namespace(xpathCtx);
201 if (ret) {
202 fprintf(stderr, "ERR: Could not register lttng namespace\n");
203 xmlXPathFreeContext(xpathCtx);
204 xmlFreeDoc(doc);
205 return -1;
206 }
207
208 /* Evaluate xpath expression */
209 xpathObj = xmlXPathEvalExpression(xpath, xpathCtx);
210 if (!xpathObj) {
211 fprintf(stderr, "ERR: invalid xpath expression \"%s\"\n", xpath);
212 xmlXPathFreeContext(xpathCtx);
213 xmlFreeDoc(doc);
214 return -1;
215 }
216
217 /* Print results */
218 if (print_xpath_nodes(doc, xpathObj->nodesetval, stdout)) {
219 xmlXPathFreeObject(xpathObj);
220 xmlXPathFreeContext(xpathCtx);
221 xmlFreeDoc(doc);
222 return -1;
223 }
224
225 /* Cleanup */
226 xmlXPathFreeObject(xpathObj);
227 xmlXPathFreeContext(xpathCtx);
228 xmlFreeDoc(doc);
229
230 return 0;
231 }
232
233 int main(int argc, char **argv)
234 {
235 int opt;
236
237 /* Parse command line and process file */
238 while ((opt = getopt(argc, argv, "ve")) != -1) {
239 switch (opt) {
240 case 'v':
241 opt_verbose = 1;
242 break;
243 case 'e':
244 node_exist = 1;
245 break;
246 default:
247 abort();
248 }
249 }
250
251 if (!(optind + 1 < argc)) {
252 fprintf(stderr, "ERR:%s\n", "Arguments missing");
253 return -1;
254 }
255
256 /* Init libxml */
257 xmlInitParser();
258 xmlKeepBlanksDefault(0);
259 if (access(argv[optind], F_OK)) {
260 fprintf(stderr, "ERR:%s\n", "Xml path not valid");
261 return -1;
262 }
263 /* Do the main job */
264 if (extract_xpath(argv[optind], (xmlChar *)argv[optind+1])) {
265 return -1;
266 }
267
268 /* Shutdown libxml */
269 xmlCleanupParser();
270
271 return 0;
272 }
273
274 #else
275 int main(void)
276 {
277 fprintf(stderr, "XPath support not compiled in\n");
278 return -1;
279 }
280 #endif
This page took 0.054393 seconds and 3 git commands to generate.