18 #include <sys/types.h> 20 #include <libxml/parser.h> 21 #include <libxml/tree.h> 45 if (!fn(xml, user_data)) {
49 for (xml = pcmk__xml_first_child(xml); xml != NULL;
50 xml = pcmk__xml_next(xml)) {
62 if(xml == NULL || xml->doc == NULL || xml->doc->_private == NULL) {
75 set_parent_flag(xmlNode *xml,
long flag)
77 for(; xml; xml = xml->parent) {
80 if (nodepriv == NULL) {
91 if(xml && xml->doc && xml->doc->_private){
119 reset_xml_node_flags(xmlNode *xml,
void *user_data)
123 if (nodepriv != NULL) {
141 mark_xml_dirty_created(xmlNode *xml,
void *user_data)
145 if (nodepriv != NULL) {
175 #define XML_DOC_PRIVATE_MAGIC 0x81726354UL 176 #define XML_NODE_PRIVATE_MAGIC 0x54637281UL 180 free_deleted_object(
void *
data)
185 g_free(deleted_obj->
path);
194 if (docpriv != NULL) {
198 docpriv->
user = NULL;
200 if (docpriv->
acls != NULL) {
202 docpriv->
acls = NULL;
206 g_list_free_full(docpriv->
deleted_objs, free_deleted_object);
214 free_private_data(xmlNode *node)
242 if (node->name == NULL || node->name[0] !=
' ') {
243 if (node->_private) {
244 if (node->type == XML_DOCUMENT_NODE) {
245 reset_xml_private_data(node->_private);
251 free(node->_private);
252 node->_private = NULL;
259 new_private_data(xmlNode *node)
261 switch (node->type) {
262 case XML_DOCUMENT_NODE: {
269 node->_private = docpriv;
272 case XML_ELEMENT_NODE:
273 case XML_ATTRIBUTE_NODE:
274 case XML_COMMENT_NODE: {
281 node->_private = nodepriv;
292 case XML_CDATA_SECTION_NODE:
296 crm_trace(
"Ignoring %p %d", node, node->type);
306 crm_trace(
"Tracking changes%s to %p", enforce_acls?
" with ACLs":
"", xml);
309 if(acl_source == NULL) {
320 return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL)
327 return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL)
346 for (
const xmlNode *cIter = xml; cIter->prev; cIter = cIter->prev) {
369 accept_attr_deletions(xmlNode *xml,
void *user_data)
371 reset_xml_node_flags(xml, NULL);
389 if (needle->type == XML_COMMENT_NODE) {
393 const char *
id = pcmk__xe_id(needle);
394 const char *attr = (
id == NULL)? NULL :
PCMK_XA_ID;
411 crm_trace(
"Accepting changes to %p", xml);
412 docpriv = xml->doc->_private;
413 top = xmlDocGetRootElement(xml->doc);
415 reset_xml_private_data(xml->doc->_private);
441 const char *attr_n,
const char *attr_v)
443 xmlNode *child = NULL;
444 const char *parent_name =
"<null>";
446 CRM_CHECK((attr_v == NULL) || (attr_n != NULL),
return NULL);
450 while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
454 parent_name = (
const char *)
parent->name;
457 for (; child != NULL; child = pcmk__xe_next(child)) {
458 const char *value = NULL;
460 if ((node_name != NULL) && !pcmk__xe_is(child, node_name)) {
464 if (attr_n == NULL) {
471 if ((attr_v == NULL) && (value != NULL)) {
475 if ((attr_v != NULL) && (pcmk__str_eq(value, attr_v,
pcmk__str_none))) {
481 if (node_name == NULL) {
484 if (attr_n != NULL) {
485 crm_trace(
"XML child node <%s %s=%s> not found in %s",
486 node_name, attr_n, attr_v, parent_name);
488 crm_trace(
"XML child node <%s> not found in %s",
489 node_name, parent_name);
527 const char *old_value = NULL;
538 if (old_value != NULL) {
539 const char *n =
name;
540 const char *v = value;
543 for (; (*n == *v) && (*n !=
'\0'); n++, v++);
548 && ((*v ==
'+') || (*v ==
'='))) {
551 int old_value_i = (old_value != value)?
char2score(old_value) : 0;
564 if (old_value != value) {
588 for (xmlAttr *attr = pcmk__xe_first_attr(src); attr != NULL;
591 const char *
name = (
const char *) attr->name;
592 const char *value = pcmk__xml_attr_value(attr);
620 remove_xe_attr(xmlNode *element, xmlAttr *attr)
628 crm_trace(
"ACLs prevent removal of attributes from %s element",
629 (
const char *) element->name);
676 const char *
name = user_data;
693 bool (*match)(xmlAttrPtr,
void *),
696 xmlAttrPtr next = NULL;
698 for (xmlAttrPtr a = pcmk__xe_first_attr(element); a != NULL; a = next) {
700 if ((match == NULL) || match(a, user_data)) {
701 if (remove_xe_attr(element, a) !=
pcmk_rc_ok) {
722 xmlNode *node = NULL;
734 xmlDocSetRootElement(doc, node);
761 const char *content = NULL;
764 if (strchr(format,
'%') == NULL) {
771 va_start(ap, format);
775 content = va_arg(ap,
const char *);
784 xmlNodeSetContent(node, (
pcmkXmlStr) content);
802 free_xml_with_position(xmlNode *child,
int position)
811 nodepriv = child->_private;
813 if ((doc != NULL) && (xmlDocGetRootElement(doc) == child)) {
820 GString *xpath = NULL;
824 qb_log_from_external_source(__func__, __FILE__,
826 __LINE__, 0, xpath->str, nodepriv->
flags);
827 g_string_free(xpath, TRUE);
840 crm_trace(
"Deleting %s %p from %p", xpath->str, child, doc);
843 deleted_obj->
path = g_string_free(xpath, FALSE);
847 if (child->type == XML_COMMENT_NODE) {
869 free_xml_with_position(child, -1);
885 xmlNode *copy = NULL;
900 copy = xmlDocCopyNode(src, doc, 1);
903 xmlDocSetRootElement(doc, copy);
906 copy = xmlDocCopyNode(src,
parent->doc, 1);
909 xmlAddChild(
parent, copy);
925 xmlNode *iter = xml->children;
928 xmlNode *next = iter->next;
930 switch (iter->type) {
936 case XML_ELEMENT_NODE:
962 const char *
result = NULL;
965 pcmk__s(now_s,
"Could not determine current time"));
980 for (c =
id; *c; ++c) {
1005 va_start(ap, format);
1006 len = vasprintf(&
id, format, ap);
1034 while (*text !=
'\0') {
1046 if (g_ascii_iscntrl(*text)) {
1061 if (g_ascii_iscntrl(*text)) {
1085 text = g_utf8_next_char(text);
1112 GString *copy = NULL;
1117 copy = g_string_sized_new(strlen(text));
1119 while (*text !=
'\0') {
1121 if ((*text & 0x80) != 0) {
1122 size_t bytes = g_utf8_next_char(text) - text;
1124 g_string_append_len(copy, text, bytes);
1143 g_string_append_c(copy, *text);
1146 if (g_ascii_iscntrl(*text)) {
1147 g_string_append_printf(copy,
"&#x%.2X;", *text);
1149 g_string_append_c(copy, *text);
1170 if (g_ascii_iscntrl(*text)) {
1171 g_string_append_printf(copy,
"&#x%.2X;", *text);
1173 g_string_append_c(copy, *text);
1182 g_string_append(copy,
"\\\"");
1185 g_string_append(copy,
"\\n");
1188 g_string_append(copy,
"\\r");
1191 g_string_append(copy,
"\\t");
1194 g_string_append_c(copy, *text);
1204 text = g_utf8_next_char(text);
1206 return g_string_free(copy, FALSE);
1219 for (xmlAttr *attr = pcmk__xe_first_attr(xml); attr; attr = attr->next) {
1239 mark_attr_deleted(xmlNode *new_xml,
const char *element,
const char *attr_name,
1240 const char *old_value)
1243 xmlAttr *attr = NULL;
1254 nodepriv = attr->_private;
1255 nodepriv->
flags = 0;
1258 remove_xe_attr(new_xml, attr);
1260 crm_trace(
"XML attribute %s=%s was removed from %s",
1261 attr_name, old_value, element);
1269 mark_attr_changed(xmlNode *new_xml,
const char *element,
const char *attr_name,
1270 const char *old_value)
1274 crm_trace(
"XML attribute %s was changed from '%s' to '%s' in %s",
1275 attr_name, old_value, vcopy, element);
1297 mark_attr_moved(xmlNode *new_xml,
const char *element, xmlAttr *old_attr,
1298 xmlAttr *new_attr,
int p_old,
int p_new)
1302 crm_trace(
"XML attribute %s moved from position %d to %d in %s",
1303 old_attr->name, p_old, p_new, element);
1311 nodepriv = (p_old > p_new)? old_attr->_private : new_attr->_private;
1323 xml_diff_old_attrs(xmlNode *old_xml, xmlNode *new_xml)
1325 xmlAttr *attr_iter = pcmk__xe_first_attr(old_xml);
1327 while (attr_iter != NULL) {
1328 const char *
name = (
const char *) attr_iter->name;
1329 xmlAttr *old_attr = attr_iter;
1330 xmlAttr *new_attr = xmlHasProp(new_xml, attr_iter->name);
1331 const char *old_value = pcmk__xml_attr_value(attr_iter);
1333 attr_iter = attr_iter->next;
1334 if (new_attr == NULL) {
1335 mark_attr_deleted(new_xml, (
const char *) old_xml->name,
name,
1349 if (strcmp(new_value, old_value) != 0) {
1350 mark_attr_changed(new_xml, (
const char *) old_xml->name,
name,
1353 }
else if ((old_pos != new_pos)
1355 mark_attr_moved(new_xml, (
const char *) old_xml->name,
1356 old_attr, new_attr, old_pos, new_pos);
1372 mark_created_attrs(xmlNode *new_xml)
1374 xmlAttr *attr_iter = pcmk__xe_first_attr(new_xml);
1376 while (attr_iter != NULL) {
1377 xmlAttr *new_attr = attr_iter;
1380 attr_iter = attr_iter->next;
1382 const char *attr_name = (
const char *) new_attr->name;
1384 crm_trace(
"Created new attribute %s=%s in %s",
1385 attr_name, pcmk__xml_attr_value(new_attr),
1395 xmlUnsetProp(new_xml, new_attr->name);
1409 xml_diff_attrs(xmlNode *old_xml, xmlNode *new_xml)
1412 xml_diff_old_attrs(old_xml, new_xml);
1413 mark_created_attrs(new_xml);
1429 mark_child_deleted(xmlNode *old_child, xmlNode *new_parent)
1441 free_xml_with_position(candidate,
1451 mark_child_moved(xmlNode *old_child, xmlNode *new_parent, xmlNode *new_child,
1452 int p_old,
int p_new)
1457 PCMK_XA_ID "='%s' moved from position %d to %d under %s",
1458 new_child->name, pcmk__s(pcmk__xe_id(new_child),
"<no id>"),
1459 p_old, p_new, new_parent->name);
1463 if (p_old > p_new) {
1464 nodepriv = old_child->_private;
1466 nodepriv = new_child->_private;
1473 mark_xml_changes(xmlNode *old_xml, xmlNode *new_xml,
bool check_top)
1475 xmlNode *old_child = NULL;
1476 xmlNode *new_child = NULL;
1480 if (old_xml == NULL) {
1486 nodepriv = new_xml->_private;
1495 xml_diff_attrs(old_xml, new_xml);
1498 for (old_child = pcmk__xml_first_child(old_xml); old_child != NULL;
1499 old_child = pcmk__xml_next(old_child)) {
1503 if (new_child != NULL) {
1504 mark_xml_changes(old_child, new_child,
true);
1507 mark_child_deleted(old_child, new_xml);
1512 new_child = pcmk__xml_first_child(new_xml);
1513 while (new_child != NULL) {
1514 xmlNode *next = pcmk__xml_next(new_child);
1518 if (old_child == NULL) {
1520 nodepriv = new_child->_private;
1524 mark_xml_changes(old_child, new_child,
true);
1531 if(p_old != p_new) {
1532 mark_child_moved(old_child, new_xml, new_child, p_old, p_new);
1551 CRM_CHECK((old_xml != NULL) && (new_xml != NULL)
1552 && pcmk__xe_is(old_xml, (
const char *) new_xml->name)
1553 && pcmk__str_eq(pcmk__xe_id(old_xml), pcmk__xe_id(new_xml),
1561 mark_xml_changes(old_xml, new_xml, FALSE);
1575 xmlNode *a_child = NULL;
1578 CRM_CHECK(search_comment->type == XML_COMMENT_NODE,
return NULL);
1580 for (a_child = pcmk__xml_first_child(root); a_child != NULL;
1581 a_child = pcmk__xml_next(a_child)) {
1586 if (offset < search_offset) {
1589 }
else if (offset > search_offset) {
1598 if (a_child->type == XML_COMMENT_NODE
1599 && pcmk__str_eq((
const char *)a_child->content, (
const char *)search_comment->content,
pcmk__str_casei)) {
1625 CRM_CHECK(update->type == XML_COMMENT_NODE,
return);
1634 }
else if (!pcmk__str_eq((
const char *)
target->content, (
const char *)update->content,
pcmk__str_casei)) {
1635 xmlFree(
target->content);
1636 target->content = xmlStrdup(update->content);
1676 uint32_t
flags,
bool as_diff)
1682 const char *update_name = NULL;
1683 const char *update_id_attr = NULL;
1684 const char *update_id_val = NULL;
1685 char *trace_s = NULL;
1692 if (update->type == XML_COMMENT_NODE) {
1697 update_name = (
const char *) update->name;
1699 CRM_CHECK(update_name != NULL,
goto done);
1702 update_id_val = pcmk__xe_id(update);
1703 if (update_id_val != NULL) {
1708 if (update_id_val != NULL) {
1715 if (update_id_attr != NULL) {
1717 update_name, update_id_attr,
1735 crm_trace(
"Added %s", pcmk__s(trace_s, update_name));
1739 crm_trace(
"Found node %s to update", pcmk__s(trace_s, update_name));
1749 for (xmlAttrPtr a = pcmk__xe_first_attr(update); a != NULL;
1751 const char *p_value = pcmk__xml_attr_value(a);
1754 xmlUnsetProp(
target, a->name);
1759 for (xmlNode *child = pcmk__xml_first_child(update); child != NULL;
1760 child = pcmk__xml_next(child)) {
1762 crm_trace(
"Updating child of %s", pcmk__s(trace_s, update_name));
1766 crm_trace(
"Finished with %s", pcmk__s(trace_s, update_name));
1791 delete_xe_if_matching(xmlNode *xml,
void *user_data)
1793 xmlNode *search = user_data;
1795 if (!pcmk__xe_is(search, (
const char *) xml->name)) {
1800 for (
const xmlAttr *attr = pcmk__xe_first_attr(search); attr != NULL;
1801 attr = attr->next) {
1803 const char *search_val = pcmk__xml_attr_value(attr);
1842 CRM_CHECK((xml != NULL) && (search != NULL),
return EINVAL);
1845 xml = pcmk__xe_next(xml)) {
1869 replace_node(xmlNode *old, xmlNode *
new)
1871 new = xmlCopyNode(
new, 1);
1877 old = xmlReplaceNode(old,
new);
1905 replace_xe_if_matching(xmlNode *xml,
void *user_data)
1907 xmlNode *replace = user_data;
1908 const char *xml_id = NULL;
1909 const char *replace_id = NULL;
1911 xml_id = pcmk__xe_id(xml);
1912 replace_id = pcmk__xe_id(replace);
1914 if (!pcmk__xe_is(replace, (
const char *) xml->name)) {
1919 if ((replace_id != NULL)
1928 replace_node(xml, replace);
1960 CRM_CHECK((xml != NULL) && (replace != NULL),
return EINVAL);
1963 xml = pcmk__xe_next(xml)) {
1976 struct update_data {
2003 update_xe_if_matching(xmlNode *xml,
void *user_data)
2005 struct update_data *
data = user_data;
2006 xmlNode *update =
data->update;
2008 if (!pcmk__xe_is(update, (
const char *) xml->name)) {
2013 if (!pcmk__str_eq(pcmk__xe_id(xml), pcmk__xe_id(update),
pcmk__str_none)) {
2055 struct update_data
data = {
2060 CRM_CHECK((xml != NULL) && (update != NULL),
return EINVAL);
2074 xmlNode *child = NULL;
2075 GSList *nvpairs = NULL;
2087 child = pcmk__xe_next(child)) {
2110 for (xmlNode *match = pcmk__xe_next(node); match != NULL;
2111 match = pcmk__xe_next(match)) {
2113 if (pcmk__xe_is(match, (
const char *) node->name)) {
2123 static bool init =
true;
2132 xmlSetBufferAllocationScheme(XML_BUFFER_ALLOC_DOUBLEIT);
2135 xmlDeregisterNodeDefault(free_private_data);
2136 xmlRegisterNodeDefault(new_private_data);
2149 #define XPATH_MAX 512 2155 const char *ref = NULL;
2158 if (
input == NULL) {
2176 "a valid object " CRM_XS " xpath=%s",
2177 input->name, ref, xpath);
2186 static const char *base = NULL;
2192 if (pcmk__str_empty(base)) {
2206 crm_err(
"XML artefact family specified as %u not recognized", ns);
2234 crm_err(
"XML artefact family specified as %u not recognized", ns);
2247 ret = find_artefact(ns, base, filespec);
2250 if (stat(ret, &sb) != 0 || !S_ISREG(sb.st_mode)) {
2254 ret = find_artefact(ns, remote_schema_dir, filespec);
2264 const char *
name, *value;
2266 name = va_arg(pairs,
const char *);
2271 value = va_arg(pairs,
const char *);
2272 if (value != NULL) {
2282 va_start(pairs, node);
2289 int (*handler)(xmlNode *xml,
void *userdata),
2292 xmlNode *children = (xml? xml->children : NULL);
2296 for (xmlNode *node = children; node != NULL; node = node->next) {
2297 if ((node->type == XML_ELEMENT_NODE)
2298 && ((child_element_name == NULL)
2299 || pcmk__xe_is(node, child_element_name))) {
2300 int rc = handler(node, userdata);
2339 xmlDocSetRootElement(doc, node);
2347 xmlNode *child = NULL;
2351 child = xmlDocCopyNode(src_node,
parent->doc, 1);
2352 if (child == NULL) {
2355 xmlAddChild(
parent, child);
2371 if (xml_root != NULL && xml_root->children != NULL) {
2378 replace_text(
char *text,
size_t *index,
size_t *length,
const char *replace)
2381 size_t offset = strlen(replace) - 1;
2385 text = pcmk__realloc(text, *length + 1);
2388 for (
size_t i = *length; i > (*index + offset); i--) {
2389 text[i] = text[i - offset];
2394 memcpy(text + *index, replace, offset + 1);
2411 length = strlen(text);
2413 for (
size_t index = 0; index <= length; index++) {
2414 if(copy[index] & 0x80 && copy[index+1] & 0x80){
2418 switch (copy[index]) {
2423 copy = replace_text(copy, &index, &length,
"<");
2426 copy = replace_text(copy, &index, &length,
">");
2429 copy = replace_text(copy, &index, &length,
""");
2432 copy = replace_text(copy, &index, &length,
"'");
2435 copy = replace_text(copy, &index, &length,
"&");
2439 copy = replace_text(copy, &index, &length,
" ");
2442 copy = replace_text(copy, &index, &length,
"\\n");
2445 copy = replace_text(copy, &index, &length,
"\\r");
2449 if(copy[index] <
' ' || copy[index] >
'~') {
2452 copy = replace_text(copy, &index, &length, replace);
2464 xmlNode *copy = NULL;
2468 copy = xmlDocCopyNode(src, doc, 1);
2471 xmlDocSetRootElement(doc, copy);
2479 xmlNode *node = NULL;
2495 xmlDocSetRootElement(doc, node);
2509 const char *content)
2519 const char *class_name,
const char *text)
2538 if (search_path == NULL) {
2539 crm_warn(
"Will never find <NULL>");
2545 if (must_find && (
result == NULL)) {
2546 crm_warn(
"Could not find %s in %s",
2548 ((root != NULL)? (
const char *) root->name :
"<NULL>"));
2569 bool is_match =
false;
2570 const char *child_id = NULL;
2571 const char *update_id = NULL;
2574 CRM_CHECK(update != NULL,
return FALSE);
2576 child_id = pcmk__xe_id(child);
2577 update_id = pcmk__xe_id(update);
2582 is_match = (
parent != NULL)
2583 && pcmk__xe_is(update, (
const char *) child->name)
2584 && ((update_id == NULL)
2590 if (is_match && delete_only) {
2591 for (xmlAttr *attr = pcmk__xe_first_attr(update); attr != NULL;
2592 attr = attr->next) {
2593 const char *
name = (
const char *) attr->name;
2594 const char *update_val = pcmk__xml_attr_value(attr);
2613 replace_node(child, update);
2620 for (child = pcmk__xml_first_child(
parent); child != NULL;
2621 child = pcmk__xml_next(child)) {
2642 const char *field,
const char *value, gboolean search_matches)
2644 int match_found = 0;
2647 CRM_CHECK(children != NULL,
return FALSE);
2649 if ((tag != NULL) && !pcmk__xe_is(root, tag)) {
2651 }
else if ((value != NULL)
2656 if (*children == NULL) {
2663 if (search_matches || match_found == 0) {
2664 xmlNode *child = NULL;
2666 for (child = pcmk__xml_first_child(root); child != NULL;
2667 child = pcmk__xml_next(child)) {
2680 xmlNode *child = NULL;
2682 for (xmlAttrPtr a = pcmk__xe_first_attr(
target); a != NULL; a = a->next) {
2683 const char *p_name = (
const char *) a->name;
2684 const char *p_value = pcmk__xml_attr_value(a);
2689 child = pcmk__xe_next(child)) {
2699 crm_warn(
"No node to copy properties from");
2701 }
else if (
target == NULL) {
2702 crm_err(
"No node to copy properties into");
2705 for (xmlAttrPtr a = pcmk__xe_first_attr(src); a != NULL; a = a->next) {
2706 const char *p_name = (
const char *) a->name;
2707 const char *p_value = pcmk__xml_attr_value(a);
#define CRM_CHECK(expr, failure_action)
int pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name, int(*handler)(xmlNode *xml, void *userdata), void *userdata)
bool pcmk__tracking_xml_changes(xmlNode *xml, bool lazy)
void xml_calculate_significant_changes(xmlNode *old_xml, xmlNode *new_xml)
GSList * pcmk_sort_nvpairs(GSList *list)
Sort a list of name/value pairs.
#define PCMK__XML_ENTITY_LT
#define pcmk__if_tracing(if_action, else_action)
bool pcmk__xml_tree_foreach(xmlNode *xml, bool(*fn)(xmlNode *, void *), void *user_data)
void pcmk__xe_remove_attr(xmlNode *element, const char *name)
void pcmk_free_nvpairs(GSList *nvpairs)
Free a list of name/value pairs.
void pcmk__free_acls(GList *acls)
void xml_track_changes(xmlNode *xml, const char *user, xmlNode *acl_source, bool enforce_acls)
G_GNUC_INTERNAL void pcmk__mark_xml_attr_dirty(xmlAttr *a)
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
const char * crm_xml_add_int(xmlNode *node, const char *name, int value)
Create an XML attribute with specified name and integer value.
void crm_xml_sanitize_id(char *id)
Sanitize a string so it is usable as an XML ID.
#define pcmk__config_err(fmt...)
void fix_plus_plus_recursive(xmlNode *target)
void crm_xml_init(void)
Initialize the CRM XML subsystem.
xmlNode * first_named_child(const xmlNode *parent, const char *name)
xmlNode * pcmk__xe_create(xmlNode *parent, const char *name)
const char * crm_xml_add(xmlNode *node, const char *name, const char *value)
Create an XML attribute with specified name and value.
void pcmk_free_xml_subtree(xmlNode *xml)
#define PCMK_XA_CIB_LAST_WRITTEN
void pcmk__xe_set_props(xmlNodePtr node,...)
int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search)
void pcmk__apply_creation_acl(xmlNode *xml, bool check_top)
#define XML_DOC_PRIVATE_MAGIC
#define CRM_LOG_ASSERT(expr)
void crm_schema_init(void)
enum crm_ais_msg_types type
xmlNode * crm_next_same_xml(const xmlNode *sibling)
xmlNode * pcmk__xml_copy(xmlNode *parent, xmlNode *src)
bool pcmk__ends_with(const char *s, const char *match)
void crm_schema_cleanup(void)
const char * pcmk__env_option(const char *option)
xmlNode * pcmk__xe_first_child(const xmlNode *parent, const char *node_name, const char *attr_n, const char *attr_v)
xmlNode * get_xpath_object(const char *xpath, xmlNode *xml_obj, int error_level)
Deprecated Pacemaker XML API.
G_GNUC_INTERNAL bool pcmk__marked_as_deleted(xmlAttrPtr a, void *user_data)
void pcmk__xml_update(xmlNode *parent, xmlNode *target, xmlNode *update, uint32_t flags, bool as_diff)
int find_xml_children(xmlNode **children, xmlNode *root, const char *tag, const char *field, const char *value, gboolean search_matches)
void expand_plus_plus(xmlNode *target, const char *name, const char *value)
gchar * pcmk__xml_escape(const char *text, enum pcmk__xml_escape_type type)
#define PCMK__ENV_SCHEMA_DIRECTORY
int pcmk__xml_position(const xmlNode *xml, enum xml_private_flags ignore_if_set)
xmlNode * pcmk__xml_match(const xmlNode *haystack, const xmlNode *needle, bool exact)
char * pcmk__xml_artefact_root(enum pcmk__xml_artefact_ns ns)
#define crm_warn(fmt, args...)
void pcmk__xe_set_propv(xmlNodePtr node, va_list pairs)
void pcmk__strip_xml_text(xmlNode *xml)
xmlNode * copy_xml(xmlNode *src)
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
xmlNode * expand_idref(xmlNode *input, xmlNode *top)
char * crm_element_value_copy(const xmlNode *data, const char *name)
Retrieve a copy of the value of an XML attribute.
#define PCMK__XML_ENTITY_GT
const char * crm_element_value(const xmlNode *data, const char *name)
Retrieve the value of an XML attribute.
xmlNode * create_xml_node(xmlNode *parent, const char *name)
int char2score(const char *score)
Get the integer value of a score string.
void free_xml(xmlNode *child)
#define crm_trace(fmt, args...)
#define XML_NODE_PRIVATE_MAGIC
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void pcmk__mark_xml_node_dirty(xmlNode *xml)
#define pcmk_is_set(g, f)
Convenience alias for pcmk_all_flags_set(), to check single flag.
void pcmk__set_xml_doc_flag(xmlNode *xml, enum xml_private_flags flag)
Wrappers for and extensions to libxml2.
bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data)
void crm_xml_set_id(xmlNode *xml, const char *format,...)
Set the ID of an XML element using a format.
char * pcmk__xml_artefact_path(enum pcmk__xml_artefact_ns ns, const char *filespec)
void crm_xml_cleanup(void)
xmlNode * add_node_copy(xmlNode *parent, xmlNode *src_node)
xmlDoc * getDocPtr(xmlNode *node)
void pcmk__unpack_acl(xmlNode *source, xmlNode *target, const char *user)
int pcmk__add_scores(int score1, int score2)
#define pcmk__str_copy(str)
xmlNode * pcmk__html_create(xmlNode *parent, const char *name, const char *id, const char *class)
int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags)
const xmlChar * pcmkXmlStr
int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags)
bool pcmk__xml_needs_escape(const char *text, enum pcmk__xml_escape_type type)
void copy_in_properties(xmlNode *target, const xmlNode *src)
xmlNode * pcmk__xe_next_same(const xmlNode *node)
pcmk__action_result_t result
void pcmk__xml_mark_created(xmlNode *xml)
gboolean xml_has_children(const xmlNode *xml_root)
#define crm_err(fmt, args...)
#define CRM_SCHEMA_DIRECTORY
char * pcmk__epoch2str(const time_t *source, uint32_t flags)
const char * pcmk__remote_schema_dir(void)
bool pcmk__check_acl(xmlNode *xml, const char *name, enum xml_private_flags mode)
#define PCMK__XML_VERSION
libxml2 supports only XML version 1.0, at least as of libxml2-2.12.5
void pcmk__apply_acl(xmlNode *xml)
void xml_accept_changes(xmlNode *xml)
#define pcmk__mem_assert(ptr)
void crm_destroy_xml(gpointer data)
#define PCMK__XML_ENTITY_QUOT
void pcmk_nvpairs2xml_attrs(GSList *list, xmlNode *xml)
Add XML attributes based on a list of name/value pairs.
bool xml_acl_denied(const xmlNode *xml)
Check whether or not an XML node is ACL-denied.
char * crm_xml_escape(const char *text)
xmlNode * pcmk_create_html_node(xmlNode *parent, const char *element_name, const char *id, const char *class_name, const char *text)
gboolean update_xml_child(xmlNode *child, xmlNode *to_update)
GString * pcmk__element_xpath(const xmlNode *xml)
void pcmk__xe_set_content(xmlNode *node, const char *format,...)
xmlNode * pcmk_create_xml_text_node(xmlNode *parent, const char *name, const char *content)
xmlNode * sorted_xml(xmlNode *input, xmlNode *parent, gboolean recursive)
#define crm_log_xml_trace(xml, text)
xmlNode * find_xml_node(const xmlNode *root, const char *search_path, gboolean must_find)
bool xml_tracking_changes(xmlNode *xml)
void pcmk__xe_remove_matching_attrs(xmlNode *element, bool(*match)(xmlAttrPtr, void *), void *user_data)
#define pcmk__set_xml_flags(xml_priv, flags_to_set)
int add_node_nocopy(xmlNode *parent, const char *name, xmlNode *child)
#define pcmk__clear_xml_flags(xml_priv, flags_to_clear)
#define PCMK__XML_ENTITY_AMP
#define pcmk__assert_alloc(nmemb, size)
gboolean replace_xml_child(xmlNode *parent, xmlNode *child, xmlNode *update, gboolean delete_only)
void pcmk__xc_update(xmlNode *parent, xmlNode *target, xmlNode *update)
void xml_remove_prop(xmlNode *obj, const char *name)
const char * pcmk__xe_add_last_written(xmlNode *xe)
xmlNode * find_entity(xmlNode *parent, const char *node_name, const char *id)
GSList * pcmk_xml_attrs2nvpairs(const xmlNode *xml)
Create a list of name/value pairs from an XML node's attributes.
xmlNode * pcmk__xc_match(const xmlNode *root, const xmlNode *search_comment, bool exact)
Don't overwrite existing values.
bool xml_document_dirty(xmlNode *xml)
int pcmk__xe_set_score(xmlNode *target, const char *name, const char *value)