15#include <libxml/tree.h>
16#include <libxml/xmlstring.h>
17#include <libxml/xpath.h>
67 xmlNode *match = NULL;
69 CRM_CHECK((xpath_obj != NULL) && (index >= 0),
return NULL);
71 match = xmlXPathNodeSetItem(xpath_obj->nodesetval, index);
77 if (match->type != XML_NAMESPACE_DECL) {
78 xpath_obj->nodesetval->nodeTab[index] = NULL;
106 switch (match->type) {
107 case XML_ELEMENT_NODE:
110 case XML_DOCUMENT_NODE:
112 return xmlDocGetRootElement((xmlDoc *) match);
115 if ((match->parent != NULL)
116 && (match->parent->type == XML_ELEMENT_NODE)) {
119 return match->parent;
121 crm_err(
"Cannot get element from XPath expression match of type %s",
139 const xmlChar *xpath_expr = (
const xmlChar *)
path;
140 xmlXPathContext *xpath_context = NULL;
141 xmlXPathObject *xpath_obj = NULL;
143 CRM_CHECK((doc != NULL) && !pcmk__str_empty(
path),
return NULL);
145 xpath_context = xmlXPathNewContext(doc);
148 xpath_obj = xmlXPathEval(xpath_expr, xpath_context);
150 xmlXPathFreeContext(xpath_context);
171 void (*fn)(xmlNode *,
void *),
void *user_data)
173 xmlXPathObject *xpath_obj = NULL;
176 CRM_CHECK((doc != NULL) && !pcmk__str_empty(
path) && (fn != NULL),
return);
179 num_results = pcmk__xpath_num_results(xpath_obj);
181 for (
int i = 0; i < num_results; i++) {
188 xmlXPathFreeObject(xpath_obj);
210 xmlXPathObject *xpath_obj = NULL;
211 const xmlNode *root = NULL;
212 const char *root_name =
"(unknown)";
217 num_results = pcmk__xpath_num_results(xpath_obj);
219 if (num_results == 1) {
229 root = xmlDocGetRootElement(doc);
231 root_name = (
const char *) root->name;
234 if (num_results < 1) {
243 do_crm_log(level,
"Multiple matches for %s in <%s>",
path, root_name);
245 for (
int i = 0; i < num_results; i++) {
247 xmlChar *match_path = NULL;
254 match_path = xmlGetNodePath(match);
256 path, i, pcmk__s((
const char *) match_path,
"(unknown)"));
265 xmlXPathFreeObject(xpath_obj);
283 const xmlNode *
parent = NULL;
284 GString *xpath = NULL;
285 const char *
id = NULL;
294 xpath = g_string_sized_new(256);
299 g_string_append_c(xpath,
'/');
300 }
else if (
parent->parent == NULL) {
301 g_string_append(xpath, (
const gchar *) xml->name);
306 id = pcmk__xe_id(xml);
331 if (node == NULL || xpath == NULL) {
336 start = strstr(xpath, patt);
343 start += strlen(patt);
346 end = strstr(start,
"\'");
348 retval = strndup(start, end-start);
355output_attr_child(xmlNode *child,
void *userdata)
359 out->
info(out,
" Value: %s \t(id=%s)",
361 pcmk__s(pcmk__xe_id(child),
"<none>"));
378 if (out == NULL ||
name == NULL || search == NULL ||
379 search->children == NULL) {
403 xmlNode *match = NULL;
404 int max = pcmk__xpath_num_results(xpathObj);
407 CRM_CHECK(xpathObj != NULL,
return NULL);
410 crm_err(
"Requested index %d of only %d items", index, max);
413 }
else if(xpathObj->nodesetval->nodeTab[index] == NULL) {
418 match = xpathObj->nodesetval->nodeTab[index];
421 if (xpathObj->nodesetval->nodeTab[index]->type != XML_NAMESPACE_DECL) {
423 xpathObj->nodesetval->nodeTab[index] = NULL;
426 switch (match->type) {
427 case XML_ELEMENT_NODE:
430 case XML_DOCUMENT_NODE:
431 return match->children;
434 if ((match->parent != NULL)
435 && (match->parent->type == XML_ELEMENT_NODE)) {
436 return match->parent;
438 crm_warn(
"Unsupported XPath match type %d (bug?)", match->type);
446 int max = pcmk__xpath_num_results(xpathObj);
448 if (xpathObj == NULL) {
452 for (
int lpc = 0; lpc < max; lpc++) {
453 if (xpathObj->nodesetval->nodeTab[lpc] && xpathObj->nodesetval->nodeTab[lpc]->type != XML_NAMESPACE_DECL) {
454 xpathObj->nodesetval->nodeTab[lpc] = NULL;
459 xmlXPathFreeObject(xpathObj);
465 int max = pcmk__xpath_num_results(xpathObj);
467 if (xpathObj == NULL) {
471 for (
int lpc = 0; lpc < max; lpc++) {
473 gboolean dedup = FALSE;
475 if (xpathObj->nodesetval->nodeTab[lpc] == NULL) {
479 xml = xpathObj->nodesetval->nodeTab[lpc]->parent;
481 for (; xml; xml = xml->parent) {
484 for (lpc2 = 0; lpc2 < max; lpc2++) {
485 if (xpathObj->nodesetval->nodeTab[lpc2] == xml) {
486 xpathObj->nodesetval->nodeTab[lpc] = NULL;
501 void (*helper)(xmlNode*,
void*),
void *user_data)
503 xmlXPathObject *xpathObj = NULL;
509 nresults = pcmk__xpath_num_results(xpathObj);
511 for (
int i = 0; i < nresults; i++) {
522 (*helper)(
result, user_data);
526 xmlXPathFreeObject(xpathObj);
534 xmlXPathObject *xpathObj = NULL;
535 char *nodePath = NULL;
536 char *matchNodePath = NULL;
543 nodePath = (
char *)xmlGetNodePath(xml_obj);
544 max = pcmk__xpath_num_results(xpathObj);
548 do_crm_log(error_level,
"No match for %s in %s",
549 xpath, pcmk__s(nodePath,
"unknown path"));
553 }
else if (max > 1) {
557 do_crm_log(error_level,
"Too many matches for %s in %s",
558 xpath, pcmk__s(nodePath,
"unknown path"));
560 for (lpc = 0; lpc < max; lpc++) {
569 matchNodePath = (
char *) xmlGetNodePath(match);
572 pcmk__s(matchNodePath,
573 "unrecognizable match"));
588 xmlXPathFreeObject(xpathObj);
G_GNUC_INTERNAL const char * pcmk__xml_element_type_text(xmlElementType type)
#define do_crm_log(level, fmt, args...)
Log a message.
#define crm_warn(fmt, args...)
#define CRM_LOG_ASSERT(expr)
#define crm_log_xml_explicit(xml, text)
#define CRM_CHECK(expr, failure_action)
#define crm_err(fmt, args...)
pcmk__action_result_t result
#define pcmk__assert(expr)
#define pcmk__mem_assert(ptr)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__g_strcat(GString *buffer,...) G_GNUC_NULL_TERMINATED
This structure contains everything that makes up a single output formatter.
int(* info)(pcmk__output_t *out, const char *format,...) G_GNUC_PRINTF(2
Wrappers for and extensions to libxml2.
Deprecated Pacemaker XML API.
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
void dedupXpathResults(xmlXPathObjectPtr xpathObj)
void crm_foreach_xpath_result(xmlNode *xml, const char *xpath, void(*helper)(xmlNode *, void *), void *user_data)
xmlXPathObject * pcmk__xpath_search(xmlDoc *doc, const char *path)
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
xmlNode * getXpathResult(xmlXPathObjectPtr xpathObj, int index)
xmlNode * pcmk__xpath_result(xmlXPathObject *xpath_obj, int index)
void freeXpathObject(xmlXPathObjectPtr xpathObj)
void pcmk__warn_multiple_name_matches(pcmk__output_t *out, xmlNode *search, const char *name)
GString * pcmk__element_xpath(const xmlNode *xml)
xmlNode * pcmk__xpath_match_element(xmlNode *match)
xmlNode * pcmk__xpath_find_one(xmlDoc *doc, const char *path, uint8_t level)
xmlXPathObjectPtr xpath_search(const xmlNode *xml_top, const char *path)
char * pcmk__xpath_node_id(const char *xpath, const char *node)
void pcmk__xpath_foreach_result(xmlDoc *doc, const char *path, void(*fn)(xmlNode *, void *), void *user_data)