Fix: include stdlib.h in compat/string.h
[lttng-tools.git] / tests / regression / tools / mi / extract_xml.c
CommitLineData
68270f0f
JRJ
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/*
71f82f2b 18 * Usage: extract_xml [-v|-e] xml_path xpath_expression
68270f0f
JRJ
19 * Evaluate XPath expression and prints result node set.
20 * args[1] path to the xml file
21 * args[2] xpath expression to extract
71f82f2b 22 * If -e look if node exist return "true" else nothing
68270f0f
JRJ
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 */
83d6d6c4
JR
36#include <assert.h>
37#include <stdbool.h>
68270f0f 38#include <stdio.h>
83d6d6c4 39#include <stdlib.h>
68270f0f 40#include <string.h>
68270f0f
JRJ
41#include <unistd.h>
42
43#include <libxml/tree.h>
44#include <libxml/parser.h>
45#include <libxml/xpath.h>
46#include <libxml/xpathInternals.h>
41af1adf 47#include <common/defaults.h>
68270f0f
JRJ
48
49#if defined(LIBXML_XPATH_ENABLED)
50
83d6d6c4
JR
51static int opt_verbose;
52static int node_exist;
53static bool result = false;
71f82f2b 54
68270f0f
JRJ
55/**
56 * print_xpath_nodes:
57 * nodes: the nodes set.
58 * output: the output file handle.
59 *
60 * Print the node content to the file
61 */
62static int print_xpath_nodes(xmlDocPtr doc, xmlNodeSetPtr nodes, FILE *output)
63{
71f82f2b 64 int ret = 0;
68270f0f
JRJ
65 int size;
66 int i;
67
68 xmlNodePtr cur;
69 xmlChar *node_child_value_string = NULL;
70
71 assert(output);
72 size = (nodes) ? nodes->nodeNr : 0;
73
74 for (i = 0; i < size; ++i) {
75 assert(nodes->nodeTab[i]);
76
77 if (nodes->nodeTab[i]->type == XML_NAMESPACE_DECL) {
78 fprintf(stderr, "ERR:%s\n",
79 "This executable does not support xml namespacing\n");
80 ret = -1;
81 goto end;
82 } else if (nodes->nodeTab[i]->type == XML_ELEMENT_NODE) {
83 cur = nodes->nodeTab[i];
84
85 if (xmlChildElementCount(cur) == 0) {
86 if (xmlNodeIsText(cur->children)) {
87 node_child_value_string = xmlNodeListGetString(doc,
88 cur->children, 1);
71f82f2b 89 if (node_exist) {
83d6d6c4 90 result = true;
71f82f2b 91 } else if (opt_verbose) {
68270f0f
JRJ
92 fprintf(output, "%s;%s;\n", cur->name,
93 node_child_value_string);
94 } else {
95 fprintf(output, "%s\n",
96 node_child_value_string);
97 }
98 xmlFree(node_child_value_string);
71f82f2b
JR
99 } else {
100 /* We don't want to print non-final element */
101 if (node_exist) {
83d6d6c4 102 result = true;
71f82f2b
JR
103 } else {
104 fprintf(stderr, "ERR:%s\n",
105 "Xpath expression return non-final xml element");
106 ret = -1;
107 goto end;
108 }
109 }
110 } else {
111 if (node_exist) {
83d6d6c4 112 result = true;
68270f0f
JRJ
113 } else {
114 /* We don't want to print non-final element */
115 fprintf(stderr, "ERR:%s\n",
116 "Xpath expression return non-final xml element");
117 ret = -1;
118 goto end;
119 }
68270f0f
JRJ
120 }
121
122 } else {
123 cur = nodes->nodeTab[i];
71f82f2b 124 if (node_exist) {
83d6d6c4 125 result = true;
71f82f2b 126 } else if (opt_verbose) {
68270f0f
JRJ
127 fprintf(output, "%s;%s;\n", cur->parent->name, cur->content);
128 } else {
129 fprintf(output, "%s\n", cur->content);
68270f0f
JRJ
130 }
131 }
132 }
133 /* Command Success */
134 ret = 0;
135
136end:
137 return ret;
138}
139
41af1adf
JG
140static int register_lttng_namespace(xmlXPathContextPtr xpathCtx)
141{
142 int ret;
143 xmlChar *prefix;
144 xmlChar *ns = NULL;
145
146 prefix = xmlCharStrdup("lttng");
147 if (!prefix) {
148 ret = -1;
149 goto end;
150 }
151
152 ns = xmlCharStrdup(DEFAULT_LTTNG_MI_NAMESPACE);
153 if (!ns) {
154 ret = -1;
155 goto end;
156 }
157
158 ret = xmlXPathRegisterNs(xpathCtx, prefix, ns);
41af1adf 159end:
0916f272 160 xmlFree(prefix);
41af1adf
JG
161 xmlFree(ns);
162 return ret;
163}
164
68270f0f
JRJ
165/*
166 * Extract element corresponding to xpath
167 * xml_path The path to the xml file
168 * xpath: The xpath to evaluate.
169 *
170 * Evaluate an xpath expression onto an xml file.
171 * and print the result one by line.
172 *
173 * Returns 0 on success and a negative value otherwise.
174 */
175static int extract_xpath(const char *xml_path, const xmlChar *xpath)
176{
41af1adf 177 int ret;
68270f0f
JRJ
178 xmlDocPtr doc = NULL;
179 xmlXPathContextPtr xpathCtx = NULL;
180 xmlXPathObjectPtr xpathObj = NULL;
181
182 assert(xml_path);
183 assert(xpath);
184
185 /* Parse the xml file */
186 doc = xmlParseFile(xml_path);
187 if (!doc) {
188 fprintf(stderr, "ERR parsing: xml file invalid \"%s\"\n", xml_path);
189 return -1;
190 }
191
192 /* Initialize a xpath context */
193 xpathCtx = xmlXPathNewContext(doc);
194 if (!xpathCtx) {
195 fprintf(stderr, "ERR: XPath context invalid\n");
196 xmlFreeDoc(doc);
197 return -1;
198 }
199
41af1adf
JG
200 /* Register the LTTng MI namespace */
201 ret = register_lttng_namespace(xpathCtx);
202 if (ret) {
203 fprintf(stderr, "ERR: Could not register lttng namespace\n");
204 xmlXPathFreeContext(xpathCtx);
205 xmlFreeDoc(doc);
206 return -1;
207 }
208
68270f0f
JRJ
209 /* Evaluate xpath expression */
210 xpathObj = xmlXPathEvalExpression(xpath, xpathCtx);
211 if (!xpathObj) {
212 fprintf(stderr, "ERR: invalid xpath expression \"%s\"\n", xpath);
213 xmlXPathFreeContext(xpathCtx);
214 xmlFreeDoc(doc);
215 return -1;
216 }
217
218 /* Print results */
219 if (print_xpath_nodes(doc, xpathObj->nodesetval, stdout)) {
220 xmlXPathFreeObject(xpathObj);
221 xmlXPathFreeContext(xpathCtx);
222 xmlFreeDoc(doc);
223 return -1;
224 }
83d6d6c4
JR
225 if (node_exist && result) {
226 fprintf(stdout, "true\n");
227 }
68270f0f
JRJ
228
229 /* Cleanup */
230 xmlXPathFreeObject(xpathObj);
231 xmlXPathFreeContext(xpathCtx);
232 xmlFreeDoc(doc);
233
234 return 0;
235}
236
237int main(int argc, char **argv)
238{
239 int opt;
240
241 /* Parse command line and process file */
71f82f2b 242 while ((opt = getopt(argc, argv, "ve")) != -1) {
68270f0f
JRJ
243 switch (opt) {
244 case 'v':
245 opt_verbose = 1;
246 break;
71f82f2b
JR
247 case 'e':
248 node_exist = 1;
249 break;
68270f0f
JRJ
250 default:
251 abort();
252 }
253 }
254
255 if (!(optind + 1 < argc)) {
256 fprintf(stderr, "ERR:%s\n", "Arguments missing");
257 return -1;
258 }
259
260 /* Init libxml */
261 xmlInitParser();
262 xmlKeepBlanksDefault(0);
263 if (access(argv[optind], F_OK)) {
264 fprintf(stderr, "ERR:%s\n", "Xml path not valid");
265 return -1;
266 }
267 /* Do the main job */
268 if (extract_xpath(argv[optind], (xmlChar *)argv[optind+1])) {
269 return -1;
270 }
271
272 /* Shutdown libxml */
273 xmlCleanupParser();
274
275 return 0;
276}
277
278#else
279int main(void)
280{
281 fprintf(stderr, "XPath support not compiled in\n");
282 return -1;
283}
284#endif
This page took 0.045071 seconds and 4 git commands to generate.