1 /*
2 * Copyright 2017-2024 the Pacemaker project contributors
3 *
4 * The version control history for this file may have further details.
5 *
6 * This source code is licensed under the GNU Lesser General Public License
7 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
8 */
9
10 #ifndef PCMK__CRM_COMMON_XML_ELEMENT_INTERNAL__H
11 #define PCMK__CRM_COMMON_XML_ELEMENT_INTERNAL__H
12
13 /*
14 * Internal-only wrappers for and extensions to libxml2 for processing XML
15 * elements
16 */
17
18 #include <stdbool.h> // bool
19 #include <stdint.h> // uint32_t
20 #include <stdio.h> // NULL
21 #include <string.h> // strcmp()
22
23 #include <libxml/tree.h> // xmlNode, etc.
24
25 #include <crm/common/iso8601.h> // crm_time_t
26 #include <crm/common/xml_element.h> // crm_element_value()
27 #include <crm/common/xml_names.h> // PCMK_XA_ID
28
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32
33 const char *pcmk__xe_add_last_written(xmlNode *xe);
34
35 xmlNode *pcmk__xe_first_child(const xmlNode *parent, const char *node_name,
36 const char *attr_n, const char *attr_v);
37
38 void pcmk__xe_remove_attr(xmlNode *element, const char *name);
39 bool pcmk__xe_remove_attr_cb(xmlNode *xml, void *user_data);
40 void pcmk__xe_remove_matching_attrs(xmlNode *element,
41 bool (*match)(xmlAttrPtr, void *),
42 void *user_data);
43 int pcmk__xe_delete_match(xmlNode *xml, xmlNode *search);
44 int pcmk__xe_replace_match(xmlNode *xml, xmlNode *replace);
45 int pcmk__xe_update_match(xmlNode *xml, xmlNode *update, uint32_t flags);
46
47 /*!
48 * \internal
49 * \brief Retrieve the value of the \c PCMK_XA_ID XML attribute
50 *
51 * \param[in] xml XML element to check
52 *
53 * \return Value of the \c PCMK_XA_ID attribute (may be \c NULL)
54 */
55 static inline const char *
56 pcmk__xe_id(const xmlNode *xml)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
57 {
58 return crm_element_value(xml, PCMK_XA_ID);
59 }
60
61 /*!
62 * \internal
63 * \brief Check whether an XML element is of a particular type
64 *
65 * \param[in] xml XML element to compare
66 * \param[in] name XML element name to compare
67 *
68 * \return \c true if \p xml is of type \p name, otherwise \c false
69 */
70 static inline bool
71 pcmk__xe_is(const xmlNode *xml, const char *name)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
72 {
73 return (xml != NULL) && (xml->name != NULL) && (name != NULL)
74 && (strcmp((const char *) xml->name, name) == 0);
75 }
76
77 xmlNode *pcmk__xe_create(xmlNode *parent, const char *name);
78 xmlNode *pcmk__xe_next(const xmlNode *node, const char *element_name);
79
80 void pcmk__xe_set_content(xmlNode *node, const char *format, ...)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
81 G_GNUC_PRINTF(2, 3);
82
83 int pcmk__xe_get_score(const xmlNode *xml, const char *name, int *score,
84 int default_score);
85
86 int pcmk__xe_copy_attrs(xmlNode *target, const xmlNode *src, uint32_t flags);
87 void pcmk__xe_sort_attrs(xmlNode *xml);
88
89 void pcmk__xe_set_id(xmlNode *xml, const char *format, ...)
90 G_GNUC_PRINTF(2, 3);
91
92 /*!
93 * \internal
94 * \brief Like pcmk__xe_set_props, but takes a va_list instead of
95 * arguments directly.
96 *
97 * \param[in,out] node XML to add attributes to
98 * \param[in] pairs NULL-terminated list of name/value pairs to add
99 */
100 void
101 pcmk__xe_set_propv(xmlNodePtr node, va_list pairs);
102
103 /*!
104 * \internal
105 * \brief Add a NULL-terminated list of name/value pairs to the given
106 * XML node as properties.
107 *
108 * \param[in,out] node XML node to add properties to
109 * \param[in] ... NULL-terminated list of name/value pairs
110 *
111 * \note A NULL name terminates the arguments; a NULL value will be skipped.
112 */
113 void
114 pcmk__xe_set_props(xmlNodePtr node, ...)
115 G_GNUC_NULL_TERMINATED;
116
117 /*!
118 * \internal
119 * \brief Get first attribute of an XML element
120 *
121 * \param[in] xe XML element to check
122 *
123 * \return First attribute of \p xe (or NULL if \p xe is NULL or has none)
124 */
125 static inline xmlAttr *
126 pcmk__xe_first_attr(const xmlNode *xe)
127 {
128 return (xe == NULL)? NULL : xe->properties;
129 }
130
131 /*!
132 * \internal
133 * \brief Iterate over child elements of \p xml
134 *
135 * This function iterates over the children of \p xml, performing the
136 * callback function \p handler on each node. If the callback returns
137 * a value other than pcmk_rc_ok, the iteration stops and the value is
138 * returned. It is therefore possible that not all children will be
139 * visited.
140 *
141 * \param[in,out] xml The starting XML node. Can be NULL.
142 * \param[in] child_element_name The name that the node must match in order
143 * for \p handler to be run. If NULL, all
144 * child elements will match.
145 * \param[in] handler The callback function.
146 * \param[in,out] userdata User data to pass to the callback function.
147 * Can be NULL.
148 *
149 * \return Standard Pacemaker return code
150 */
151 int
152 pcmk__xe_foreach_child(xmlNode *xml, const char *child_element_name,
153 int (*handler)(xmlNode *xml, void *userdata),
154 void *userdata);
155
156 int pcmk__xe_get_datetime(const xmlNode *xml, const char *attr, crm_time_t **t);
157 int pcmk__xe_get_flags(const xmlNode *xml, const char *name, uint32_t *dest,
158 uint32_t default_value);
159
160 void pcmk__xe_set_bool_attr(xmlNodePtr node, const char *name, bool value);
161 int pcmk__xe_get_bool_attr(const xmlNode *node, const char *name, bool *value);
162 bool pcmk__xe_attr_is_true(const xmlNode *node, const char *name);
163
164 #ifdef __cplusplus
165 }
166 #endif
167
168 #endif // PCMK__CRM_COMMON_XML_ELEMENT_INTERNAL__H