18 #include <sys/types.h> 20 #include <libxml/parser.h> 21 #include <libxml/tree.h> 29 #define XML_VERSION ((pcmkXmlStr) "1.0") 52 if (!fn(xml, user_data)) {
56 for (xml = pcmk__xml_first_child(xml); xml != NULL;
57 xml = pcmk__xml_next(xml)) {
69 if(xml == NULL || xml->doc == NULL || xml->doc->_private == NULL) {
84 for (; xml != NULL; xml = xml->parent) {
87 if (nodepriv != NULL) {
123 reset_xml_node_flags(xmlNode *xml,
void *user_data)
127 if (nodepriv != NULL) {
145 mark_xml_dirty_created(xmlNode *xml,
void *user_data)
149 if (nodepriv != NULL) {
164 mark_xml_tree_dirty_created(xmlNode *xml)
181 free_deleted_object(
void *
data)
186 g_free(deleted_obj->
path);
195 if (docpriv != NULL) {
199 docpriv->
user = NULL;
201 if (docpriv->
acls != NULL) {
203 docpriv->
acls = NULL;
207 g_list_free_full(docpriv->
deleted_objs, free_deleted_object);
225 new_private_data(xmlNode *node,
void *user_data)
229 if (node->_private != NULL) {
233 switch (node->type) {
234 case XML_DOCUMENT_NODE:
240 node->_private = docpriv;
245 case XML_ELEMENT_NODE:
246 case XML_ATTRIBUTE_NODE:
247 case XML_COMMENT_NODE:
253 node->_private = nodepriv;
256 for (xmlAttr *iter = pcmk__xe_first_attr(node); iter != NULL;
259 new_private_data((xmlNode *) iter, user_data);
266 case XML_CDATA_SECTION_NODE:
292 free_private_data(xmlNode *node,
void *user_data)
296 if (node->_private == NULL) {
300 if (node->type == XML_DOCUMENT_NODE) {
308 for (xmlAttr *iter = pcmk__xe_first_attr(node); iter != NULL;
311 free_private_data((xmlNode *) iter, user_data);
314 free(node->_private);
315 node->_private = NULL;
347 crm_trace(
"Tracking changes%s to %p", enforce_acls?
" with ACLs":
"", xml);
350 if(acl_source == NULL) {
361 return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL)
368 return (xml != NULL) && (xml->doc != NULL) && (xml->doc->_private != NULL)
387 for (
const xmlNode *cIter = xml; cIter->prev; cIter = cIter->prev) {
410 accept_attr_deletions(xmlNode *xml,
void *user_data)
412 reset_xml_node_flags(xml, NULL);
430 if (needle->type == XML_COMMENT_NODE) {
434 const char *
id = pcmk__xe_id(needle);
435 const char *attr = (
id == NULL)? NULL :
PCMK_XA_ID;
452 crm_trace(
"Accepting changes to %p", xml);
453 docpriv = xml->doc->_private;
454 top = xmlDocGetRootElement(xml->doc);
456 reset_xml_private_data(xml->doc->_private);
482 const char *attr_n,
const char *attr_v)
484 xmlNode *child = NULL;
485 const char *parent_name =
"<null>";
487 CRM_CHECK((attr_v == NULL) || (attr_n != NULL),
return NULL);
491 while ((child != NULL) && (child->type != XML_ELEMENT_NODE)) {
495 parent_name = (
const char *)
parent->name;
498 for (; child != NULL; child = pcmk__xe_next(child)) {
499 const char *value = NULL;
501 if ((node_name != NULL) && !pcmk__xe_is(child, node_name)) {
505 if (attr_n == NULL) {
512 if ((attr_v == NULL) && (value != NULL)) {
516 if ((attr_v != NULL) && (pcmk__str_eq(value, attr_v,
pcmk__str_none))) {
522 if (node_name == NULL) {
525 if (attr_n != NULL) {
526 crm_trace(
"XML child node <%s %s=%s> not found in %s",
527 node_name, attr_n, attr_v, parent_name);
529 crm_trace(
"XML child node <%s> not found in %s",
530 node_name, parent_name);
552 const char *value = NULL;
593 const char *old_value = NULL;
605 if (old_value != NULL) {
606 const char *n =
name;
607 const char *v = value;
610 for (; (*n == *v) && (*n !=
'\0'); n++, v++);
615 && ((*v ==
'+') || (*v ==
'='))) {
622 if (old_value != value) {
626 crm_trace(
"Using 0 before incrementing %s because '%s' " 627 "is not a score",
name, old_value);
638 crm_trace(
"Not incrementing %s because '%s' does not have " 639 "a valid increment",
name, value);
649 if (old_value != value) {
673 for (xmlAttr *attr = pcmk__xe_first_attr(src); attr != NULL;
676 const char *
name = (
const char *) attr->name;
677 const char *value = pcmk__xml_attr_value(attr);
726 const char *
name = user_data;
743 bool (*match)(xmlAttrPtr,
void *),
746 xmlAttrPtr next = NULL;
748 for (xmlAttrPtr a = pcmk__xe_first_attr(element); a != NULL; a = next) {
750 if ((match == NULL) || match(a, user_data)) {
772 xmlNode *node = NULL;
782 xmlDocSetRootElement(doc, node);
843 const char *content = NULL;
851 || (node->children->type == XML_TEXT_NODE),
854 if (strchr(format,
'%') == NULL) {
861 va_start(ap, format);
865 content = va_arg(ap,
const char *);
874 xmlNodeSetContent(node, (
pcmkXmlStr) content);
893 free_xml_with_position(xmlNode *child,
int position)
902 nodepriv = child->_private;
904 if ((doc != NULL) && (xmlDocGetRootElement(doc) == child)) {
911 GString *xpath = NULL;
915 qb_log_from_external_source(__func__, __FILE__,
917 __LINE__, 0, xpath->str, nodepriv->
flags);
918 g_string_free(xpath, TRUE);
931 crm_trace(
"Deleting %s %p from %p", xpath->str, child, doc);
934 deleted_obj->
path = g_string_free(xpath, FALSE);
938 if (child->type == XML_COMMENT_NODE) {
960 free_xml_with_position(child, -1);
976 xmlNode *copy = NULL;
989 copy = xmlDocCopyNode(src, doc, 1);
992 xmlDocSetRootElement(doc, copy);
995 copy = xmlDocCopyNode(src,
parent->doc, 1);
998 xmlAddChild(
parent, copy);
1014 xmlNode *iter = xml->children;
1017 xmlNode *next = iter->next;
1019 switch (iter->type) {
1025 case XML_ELEMENT_NODE:
1051 const char *
result = NULL;
1054 pcmk__s(now_s,
"Could not determine current time"));
1069 for (c =
id; *c; ++c) {
1094 va_start(ap, format);
1095 len = vasprintf(&
id, format, ap);
1123 while (*text !=
'\0') {
1135 if (g_ascii_iscntrl(*text)) {
1150 if (g_ascii_iscntrl(*text)) {
1174 text = g_utf8_next_char(text);
1201 GString *copy = NULL;
1206 copy = g_string_sized_new(strlen(text));
1208 while (*text !=
'\0') {
1210 if ((*text & 0x80) != 0) {
1211 size_t bytes = g_utf8_next_char(text) - text;
1213 g_string_append_len(copy, text, bytes);
1232 g_string_append_c(copy, *text);
1235 if (g_ascii_iscntrl(*text)) {
1236 g_string_append_printf(copy,
"&#x%.2X;", *text);
1238 g_string_append_c(copy, *text);
1259 if (g_ascii_iscntrl(*text)) {
1260 g_string_append_printf(copy,
"&#x%.2X;", *text);
1262 g_string_append_c(copy, *text);
1271 g_string_append(copy,
"\\\"");
1274 g_string_append(copy,
"\\n");
1277 g_string_append(copy,
"\\r");
1280 g_string_append(copy,
"\\t");
1283 g_string_append_c(copy, *text);
1293 text = g_utf8_next_char(text);
1295 return g_string_free(copy, FALSE);
1308 for (xmlAttr *attr = pcmk__xe_first_attr(xml); attr; attr = attr->next) {
1328 mark_attr_deleted(xmlNode *new_xml,
const char *element,
const char *attr_name,
1329 const char *old_value)
1332 xmlAttr *attr = NULL;
1343 attr = xmlHasProp(new_xml, (
pcmkXmlStr) attr_name);
1344 nodepriv = attr->_private;
1345 nodepriv->
flags = 0;
1350 crm_trace(
"XML attribute %s=%s was removed from %s",
1351 attr_name, old_value, element);
1359 mark_attr_changed(xmlNode *new_xml,
const char *element,
const char *attr_name,
1360 const char *old_value)
1365 crm_trace(
"XML attribute %s was changed from '%s' to '%s' in %s",
1366 attr_name, old_value, vcopy, element);
1390 mark_attr_moved(xmlNode *new_xml,
const char *element, xmlAttr *old_attr,
1391 xmlAttr *new_attr,
int p_old,
int p_new)
1395 crm_trace(
"XML attribute %s moved from position %d to %d in %s",
1396 old_attr->name, p_old, p_new, element);
1404 nodepriv = (p_old > p_new)? old_attr->_private : new_attr->_private;
1416 xml_diff_old_attrs(xmlNode *old_xml, xmlNode *new_xml)
1418 xmlAttr *attr_iter = pcmk__xe_first_attr(old_xml);
1420 while (attr_iter != NULL) {
1421 const char *
name = (
const char *) attr_iter->name;
1422 xmlAttr *old_attr = attr_iter;
1423 xmlAttr *new_attr = xmlHasProp(new_xml, attr_iter->name);
1424 const char *old_value = pcmk__xml_attr_value(attr_iter);
1426 attr_iter = attr_iter->next;
1427 if (new_attr == NULL) {
1428 mark_attr_deleted(new_xml, (
const char *) old_xml->name,
name,
1442 if (strcmp(new_value, old_value) != 0) {
1443 mark_attr_changed(new_xml, (
const char *) old_xml->name,
name,
1446 }
else if ((old_pos != new_pos)
1448 mark_attr_moved(new_xml, (
const char *) old_xml->name,
1449 old_attr, new_attr, old_pos, new_pos);
1465 mark_created_attrs(xmlNode *new_xml)
1467 xmlAttr *attr_iter = pcmk__xe_first_attr(new_xml);
1469 while (attr_iter != NULL) {
1470 xmlAttr *new_attr = attr_iter;
1473 attr_iter = attr_iter->next;
1475 const char *attr_name = (
const char *) new_attr->name;
1477 crm_trace(
"Created new attribute %s=%s in %s",
1478 attr_name, pcmk__xml_attr_value(new_attr),
1502 xml_diff_attrs(xmlNode *old_xml, xmlNode *new_xml)
1505 xml_diff_old_attrs(old_xml, new_xml);
1506 mark_created_attrs(new_xml);
1522 mark_child_deleted(xmlNode *old_child, xmlNode *new_parent)
1534 free_xml_with_position(candidate,
1544 mark_child_moved(xmlNode *old_child, xmlNode *new_parent, xmlNode *new_child,
1545 int p_old,
int p_new)
1550 PCMK_XA_ID "='%s' moved from position %d to %d under %s",
1551 new_child->name, pcmk__s(pcmk__xe_id(new_child),
"<no id>"),
1552 p_old, p_new, new_parent->name);
1556 if (p_old > p_new) {
1557 nodepriv = old_child->_private;
1559 nodepriv = new_child->_private;
1566 mark_xml_changes(xmlNode *old_xml, xmlNode *new_xml,
bool check_top)
1568 xmlNode *old_child = NULL;
1569 xmlNode *new_child = NULL;
1573 if (old_xml == NULL) {
1574 mark_xml_tree_dirty_created(new_xml);
1579 nodepriv = new_xml->_private;
1588 xml_diff_attrs(old_xml, new_xml);
1591 for (old_child = pcmk__xml_first_child(old_xml); old_child != NULL;
1592 old_child = pcmk__xml_next(old_child)) {
1596 if (new_child != NULL) {
1597 mark_xml_changes(old_child, new_child,
true);
1600 mark_child_deleted(old_child, new_xml);
1605 new_child = pcmk__xml_first_child(new_xml);
1606 while (new_child != NULL) {
1607 xmlNode *next = pcmk__xml_next(new_child);
1611 if (old_child == NULL) {
1613 nodepriv = new_child->_private;
1617 mark_xml_changes(old_child, new_child,
true);
1624 if(p_old != p_new) {
1625 mark_child_moved(old_child, new_xml, new_child, p_old, p_new);
1644 CRM_CHECK((old_xml != NULL) && (new_xml != NULL)
1645 && pcmk__xe_is(old_xml, (
const char *) new_xml->name)
1646 && pcmk__str_eq(pcmk__xe_id(old_xml), pcmk__xe_id(new_xml),
1654 mark_xml_changes(old_xml, new_xml, FALSE);
1693 uint32_t
flags,
bool as_diff)
1699 const char *update_name = NULL;
1700 const char *update_id_attr = NULL;
1701 const char *update_id_val = NULL;
1702 char *trace_s = NULL;
1709 if (update->type == XML_COMMENT_NODE) {
1714 update_name = (
const char *) update->name;
1716 CRM_CHECK(update_name != NULL,
goto done);
1719 update_id_val = pcmk__xe_id(update);
1720 if (update_id_val != NULL) {
1725 if (update_id_val != NULL) {
1732 if (update_id_attr != NULL) {
1734 update_name, update_id_attr,
1752 crm_trace(
"Added %s", pcmk__s(trace_s, update_name));
1756 crm_trace(
"Found node %s to update", pcmk__s(trace_s, update_name));
1766 for (xmlAttrPtr a = pcmk__xe_first_attr(update); a != NULL;
1768 const char *p_value = pcmk__xml_attr_value(a);
1769 xmlAttr *old_attr = xmlHasProp(
target, a->name);
1772 if (old_attr != NULL) {
1779 for (xmlNode *child = pcmk__xml_first_child(update); child != NULL;
1780 child = pcmk__xml_next(child)) {
1782 crm_trace(
"Updating child of %s", pcmk__s(trace_s, update_name));
1786 crm_trace(
"Finished with %s", pcmk__s(trace_s, update_name));
1811 delete_xe_if_matching(xmlNode *xml,
void *user_data)
1813 xmlNode *search = user_data;
1815 if (!pcmk__xe_is(search, (
const char *) xml->name)) {
1820 for (
const xmlAttr *attr = pcmk__xe_first_attr(search); attr != NULL;
1821 attr = attr->next) {
1823 const char *search_val = pcmk__xml_attr_value(attr);
1862 CRM_CHECK((xml != NULL) && (search != NULL),
return EINVAL);
1865 xml = pcmk__xe_next(xml)) {
1889 replace_node(xmlNode *old, xmlNode *
new)
1893 old = xmlReplaceNode(old,
new);
1927 replace_xe_if_matching(xmlNode *xml,
void *user_data)
1929 xmlNode *replace = user_data;
1930 const char *xml_id = NULL;
1931 const char *replace_id = NULL;
1933 xml_id = pcmk__xe_id(xml);
1934 replace_id = pcmk__xe_id(replace);
1936 if (!pcmk__xe_is(replace, (
const char *) xml->name)) {
1941 if ((replace_id != NULL)
1950 replace_node(xml, replace);
1982 CRM_CHECK((xml != NULL) && (replace != NULL),
return EINVAL);
1985 xml = pcmk__xe_next(xml)) {
1998 struct update_data {
2025 update_xe_if_matching(xmlNode *xml,
void *user_data)
2027 struct update_data *
data = user_data;
2028 xmlNode *update =
data->update;
2030 if (!pcmk__xe_is(update, (
const char *) xml->name)) {
2035 if (!pcmk__str_eq(pcmk__xe_id(xml), pcmk__xe_id(update),
pcmk__str_none)) {
2077 struct update_data
data = {
2082 CRM_CHECK((xml != NULL) && (update != NULL),
return EINVAL);
2096 xmlNode *child = NULL;
2097 GSList *nvpairs = NULL;
2109 child = pcmk__xe_next(child)) {
2132 for (xmlNode *match = pcmk__xe_next(node); match != NULL;
2133 match = pcmk__xe_next(match)) {
2135 if (pcmk__xe_is(match, (
const char *) node->name)) {
2145 static bool init =
true;
2154 xmlSetBufferAllocationScheme(XML_BUFFER_ALLOC_DOUBLEIT);
2167 #define XPATH_MAX 512 2173 const char *ref = NULL;
2176 if (
input == NULL) {
2194 "a valid object " CRM_XS " xpath=%s",
2195 input->name, ref, xpath);
2204 static const char *base = NULL;
2210 if (pcmk__str_empty(base)) {
2224 crm_err(
"XML artefact family specified as %u not recognized", ns);
2252 crm_err(
"XML artefact family specified as %u not recognized", ns);
2265 ret = find_artefact(ns, base, filespec);
2268 if (stat(ret, &sb) != 0 || !S_ISREG(sb.st_mode)) {
2272 ret = find_artefact(ns, remote_schema_dir, filespec);
2282 const char *
name, *value;
2284 name = va_arg(pairs,
const char *);
2289 value = va_arg(pairs,
const char *);
2290 if (value != NULL) {
2300 va_start(pairs, node);
2307 int (*handler)(xmlNode *xml,
void *userdata),
2310 xmlNode *children = (xml? xml->children : NULL);
2314 for (xmlNode *node = children; node != NULL; node = node->next) {
2315 if ((node->type == XML_ELEMENT_NODE)
2316 && ((child_element_name == NULL)
2317 || pcmk__xe_is(node, child_element_name))) {
2318 int rc = handler(node, userdata);
2357 xmlDocSetRootElement(doc, node);
2365 xmlNode *child = NULL;
2369 child = xmlDocCopyNode(src_node,
parent->doc, 1);
2370 if (child == NULL) {
2373 xmlAddChild(
parent, child);
2389 if (xml_root != NULL && xml_root->children != NULL) {
2396 replace_text(
char *text,
size_t *index,
size_t *length,
const char *replace)
2399 size_t offset = strlen(replace) - 1;
2403 text = pcmk__realloc(text, *length + 1);
2406 for (
size_t i = *length; i > (*index + offset); i--) {
2407 text[i] = text[i - offset];
2412 memcpy(text + *index, replace, offset + 1);
2429 length = strlen(text);
2431 for (
size_t index = 0; index <= length; index++) {
2432 if(copy[index] & 0x80 && copy[index+1] & 0x80){
2436 switch (copy[index]) {
2441 copy = replace_text(copy, &index, &length,
"<");
2444 copy = replace_text(copy, &index, &length,
">");
2447 copy = replace_text(copy, &index, &length,
""");
2450 copy = replace_text(copy, &index, &length,
"'");
2453 copy = replace_text(copy, &index, &length,
"&");
2457 copy = replace_text(copy, &index, &length,
" ");
2460 copy = replace_text(copy, &index, &length,
"\\n");
2463 copy = replace_text(copy, &index, &length,
"\\r");
2467 if(copy[index] <
' ' || copy[index] >
'~') {
2470 copy = replace_text(copy, &index, &length, replace);
2482 xmlNode *copy = NULL;
2484 copy = xmlDocCopyNode(src, doc, 1);
2487 xmlDocSetRootElement(doc, copy);
2496 xmlNode *node = NULL;
2508 xmlDocSetRootElement(doc, node);
2522 const char *content)
2532 const char *class_name,
const char *text)
2551 if (search_path == NULL) {
2552 crm_warn(
"Will never find <NULL>");
2558 if (must_find && (
result == NULL)) {
2559 crm_warn(
"Could not find %s in %s",
2561 ((root != NULL)? (
const char *) root->name :
"<NULL>"));
2582 bool is_match =
false;
2583 const char *child_id = NULL;
2584 const char *update_id = NULL;
2587 CRM_CHECK(update != NULL,
return FALSE);
2589 child_id = pcmk__xe_id(child);
2590 update_id = pcmk__xe_id(update);
2595 is_match = (
parent != NULL)
2596 && pcmk__xe_is(update, (
const char *) child->name)
2597 && ((update_id == NULL)
2603 if (is_match && delete_only) {
2604 for (xmlAttr *attr = pcmk__xe_first_attr(update); attr != NULL;
2605 attr = attr->next) {
2606 const char *
name = (
const char *) attr->name;
2607 const char *update_val = pcmk__xml_attr_value(attr);
2626 replace_node(child, update);
2633 for (child = pcmk__xml_first_child(
parent); child != NULL;
2634 child = pcmk__xml_next(child)) {
2655 const char *field,
const char *value, gboolean search_matches)
2657 int match_found = 0;
2660 CRM_CHECK(children != NULL,
return FALSE);
2662 if ((tag != NULL) && !pcmk__xe_is(root, tag)) {
2664 }
else if ((value != NULL)
2669 if (*children == NULL) {
2676 if (search_matches || match_found == 0) {
2677 xmlNode *child = NULL;
2679 for (child = pcmk__xml_first_child(root); child != NULL;
2680 child = pcmk__xml_next(child)) {
2693 xmlNode *child = NULL;
2695 for (xmlAttrPtr a = pcmk__xe_first_attr(
target); a != NULL; a = a->next) {
2696 const char *p_name = (
const char *) a->name;
2697 const char *p_value = pcmk__xml_attr_value(a);
2702 child = pcmk__xe_next(child)) {
2712 crm_warn(
"No node to copy properties from");
2714 }
else if (
target == NULL) {
2715 crm_err(
"No node to copy properties into");
2718 for (xmlAttrPtr a = pcmk__xe_first_attr(src); a != NULL; a = a->next) {
2719 const char *p_name = (
const char *) a->name;
2720 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)
#define XML_VERSION
libxml2 supports only XML version 1.0, at least as of libxml2-2.12.5
void pcmk__xml_free_private_data(xmlNode *xml)
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)
xmlDoc * pcmk__xml_new_doc(void)
void xml_calculate_changes(xmlNode *old_xml, xmlNode *new_xml)
#define PCMK__XML_DOC_PRIVATE_MAGIC
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__xml_new_private_data(xmlNode *xml)
G_GNUC_INTERNAL xmlAttr * pcmk__xe_set_attr_force(xmlNode *node, const char *name, const char *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 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)
G_GNUC_INTERNAL void pcmk__xc_update(xmlNode *parent, xmlNode *target, xmlNode *update)
int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace)
void pcmk__xml_free_doc(xmlDoc *doc)
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)
void free_xml(xmlNode *child)
#define crm_trace(fmt, args...)
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)
void pcmk__xml_set_parent_flags(xmlNode *xml, uint64_t flags)
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
#define PCMK__XML_NODE_PRIVATE_MAGIC
#define pcmk__assert(expr)
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)
int pcmk__xe_get_score(const xmlNode *xml, const char *name, int *score, int default_score)
xmlNode * pcmk__xe_next_same(const xmlNode *node)
pcmk__action_result_t result
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)
void pcmk__apply_acl(xmlNode *xml)
void xml_accept_changes(xmlNode *xml)
#define pcmk__mem_assert(ptr)
int pcmk_parse_score(const char *score_s, int *score, int default_score)
Parse an integer score from a string.
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)
G_GNUC_INTERNAL xmlNode * pcmk__xc_match(const xmlNode *root, const xmlNode *search_comment, bool exact)
#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 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.
G_GNUC_INTERNAL int pcmk__xa_remove(xmlAttr *attr, bool force)
Don't overwrite existing values.
bool xml_document_dirty(xmlNode *xml)
int pcmk__xe_set_score(xmlNode *target, const char *name, const char *value)