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