1 /*
2 * "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $"
3 *
4 * Attribute support code for Mini-XML, a small XML-like file parsing library.
5 *
6 * Copyright 2003-2010 by Michael R Sweet.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Michael R Sweet and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "COPYING"
11 * which should have been included with this file. If this file is
12 * missing or damaged, see the license at:
13 *
14 * http://www.minixml.org/
15 *
16 * Contents:
17 *
18 * mxmlElementDeleteAttr() - Delete an attribute.
19 * mxmlElementGetAttr() - Get an attribute.
20 * mxmlElementSetAttr() - Set an attribute.
21 * mxmlElementSetAttrf() - Set an attribute with a formatted value.
22 * mxml_set_attr() - Set or add an attribute name/value pair.
23 */
25 /*
26 * Include necessary headers...
27 */
29 #include "config.h"
30 #include "mxml.h"
33 /*
34 * Local functions...
35 */
37 static int mxml_set_attr(mxml_node_t *node, const char *name,
38 char *value);
41 /*
42 * 'mxmlElementDeleteAttr()' - Delete an attribute.
43 *
44 * @since Mini-XML 2.4@
45 */
47 void
48 mxmlElementDeleteAttr(mxml_node_t *node,/* I - Element */
49 const char *name)/* I - Attribute name */
50 {
51 int i; /* Looping var */
52 mxml_attr_t *attr; /* Cirrent attribute */
55 #ifdef DEBUG
56 fprintf(stderr, "mxmlElementDeleteAttr(node=%p, name=\"%s\")\n",
57 node, name ? name : "(null)");
58 #endif /* DEBUG */
60 /*
61 * Range check input...
62 */
64 if (!node || node->type != MXML_ELEMENT || !name)
65 return;
67 /*
68 * Look for the attribute...
69 */
71 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
72 i > 0;
73 i --, attr ++)
74 {
75 #ifdef DEBUG
76 printf(" %s=\"%s\"\n", attr->name, attr->value);
77 #endif /* DEBUG */
79 if (!strcmp(attr->name, name))
80 {
81 /*
82 * Delete this attribute...
83 */
85 free(attr->name);
86 free(attr->value);
88 i --;
89 if (i > 0)
90 memmove(attr, attr + 1, i * sizeof(mxml_attr_t));
92 node->value.element.num_attrs --;
93 return;
94 }
95 }
96 }
99 /*
100 * 'mxmlElementGetAttr()' - Get an attribute.
101 *
102 * This function returns NULL if the node is not an element or the
103 * named attribute does not exist.
104 */
106 const char * /* O - Attribute value or NULL */
107 mxmlElementGetAttr(mxml_node_t *node, /* I - Element node */
108 const char *name) /* I - Name of attribute */
109 {
110 int i; /* Looping var */
111 mxml_attr_t *attr; /* Cirrent attribute */
114 #ifdef DEBUG
115 fprintf(stderr, "mxmlElementGetAttr(node=%p, name=\"%s\")\n",
116 node, name ? name : "(null)");
117 #endif /* DEBUG */
119 /*
120 * Range check input...
121 */
123 if (!node || node->type != MXML_ELEMENT || !name)
124 return (NULL);
126 /*
127 * Look for the attribute...
128 */
130 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
131 i > 0;
132 i --, attr ++)
133 {
134 #ifdef DEBUG
135 printf(" %s=\"%s\"\n", attr->name, attr->value);
136 #endif /* DEBUG */
138 if (!strcmp(attr->name, name))
139 {
140 #ifdef DEBUG
141 printf(" Returning \"%s\"!\n", attr->value);
142 #endif /* DEBUG */
143 return (attr->value);
144 }
145 }
147 /*
148 * Didn't find attribute, so return NULL...
149 */
151 #ifdef DEBUG
152 puts(" Returning NULL!\n");
153 #endif /* DEBUG */
155 return (NULL);
156 }
159 /*
160 * 'mxmlElementSetAttr()' - Set an attribute.
161 *
162 * If the named attribute already exists, the value of the attribute
163 * is replaced by the new string value. The string value is copied
164 * into the element node. This function does nothing if the node is
165 * not an element.
166 */
168 void
169 mxmlElementSetAttr(mxml_node_t *node, /* I - Element node */
170 const char *name, /* I - Name of attribute */
171 const char *value) /* I - Attribute value */
172 {
173 char *valuec; /* Copy of value */
176 #ifdef DEBUG
177 fprintf(stderr, "mxmlElementSetAttr(node=%p, name=\"%s\", value=\"%s\")\n",
178 node, name ? name : "(null)", value ? value : "(null)");
179 #endif /* DEBUG */
181 /*
182 * Range check input...
183 */
185 if (!node || node->type != MXML_ELEMENT || !name)
186 return;
188 if (value)
189 valuec = strdup(value);
190 else
191 valuec = NULL;
193 if (mxml_set_attr(node, name, valuec))
194 free(valuec);
195 }
198 /*
199 * 'mxmlElementSetAttrf()' - Set an attribute with a formatted value.
200 *
201 * If the named attribute already exists, the value of the attribute
202 * is replaced by the new formatted string. The formatted string value is
203 * copied into the element node. This function does nothing if the node
204 * is not an element.
205 *
206 * @since Mini-XML 2.3@
207 */
209 void
210 mxmlElementSetAttrf(mxml_node_t *node, /* I - Element node */
211 const char *name, /* I - Name of attribute */
212 const char *format,/* I - Printf-style attribute value */
213 ...) /* I - Additional arguments as needed */
214 {
215 va_list ap; /* Argument pointer */
216 char *value; /* Value */
219 #ifdef DEBUG
220 fprintf(stderr,
221 "mxmlElementSetAttrf(node=%p, name=\"%s\", format=\"%s\", ...)\n",
222 node, name ? name : "(null)", format ? format : "(null)");
223 #endif /* DEBUG */
225 /*
226 * Range check input...
227 */
229 if (!node || node->type != MXML_ELEMENT || !name || !format)
230 return;
232 /*
233 * Format the value...
234 */
236 va_start(ap, format);
237 value = _mxml_vstrdupf(format, ap);
238 va_end(ap);
240 if (!value)
241 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
242 name, node->value.element.name);
243 else if (mxml_set_attr(node, name, value))
244 free(value);
245 }
248 /*
249 * 'mxml_set_attr()' - Set or add an attribute name/value pair.
250 */
252 static int /* O - 0 on success, -1 on failure */
253 mxml_set_attr(mxml_node_t *node, /* I - Element node */
254 const char *name, /* I - Attribute name */
255 char *value) /* I - Attribute value */
256 {
257 int i; /* Looping var */
258 mxml_attr_t *attr; /* New attribute */
261 /*
262 * Look for the attribute...
263 */
265 for (i = node->value.element.num_attrs, attr = node->value.element.attrs;
266 i > 0;
267 i --, attr ++)
268 if (!strcmp(attr->name, name))
269 {
270 /*
271 * Free the old value as needed...
272 */
274 if (attr->value)
275 free(attr->value);
277 attr->value = value;
279 return (0);
280 }
282 /*
283 * Add a new attribute...
284 */
286 if (node->value.element.num_attrs == 0)
287 attr = malloc(sizeof(mxml_attr_t));
288 else
289 attr = realloc(node->value.element.attrs,
290 (node->value.element.num_attrs + 1) * sizeof(mxml_attr_t));
292 if (!attr)
293 {
294 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
295 name, node->value.element.name);
296 return (-1);
297 }
299 node->value.element.attrs = attr;
300 attr += node->value.element.num_attrs;
302 if ((attr->name = strdup(name)) == NULL)
303 {
304 mxml_error("Unable to allocate memory for attribute '%s' in element %s!",
305 name, node->value.element.name);
306 return (-1);
307 }
309 attr->value = value;
311 node->value.element.num_attrs ++;
313 return (0);
314 }
317 /*
318 * End of "$Id: mxml-attr.c 408 2010-09-19 05:26:46Z mike $".
319 */