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