Mstdlib-1.24.0
m_xml.h
1/* The MIT License (MIT)
2 *
3 * Copyright (c) 2015 Monetra Technologies, LLC.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifndef __M_XML_H__
25#define __M_XML_H__
26
27/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
28
29#include <mstdlib/base/m_defs.h>
30#include <mstdlib/base/m_types.h>
31#include <mstdlib/base/m_fs.h>
32#include <mstdlib/base/m_hash_dict.h>
33#include <mstdlib/base/m_list_str.h>
34#include <mstdlib/base/m_buf.h>
35
36/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
37
38__BEGIN_DECLS
39
40/*! \addtogroup m_xml XML
41 * \ingroup m_formats
42 *
43 * DOM based XML data processing.
44 *
45 * This is a simple API for reading, creating, manipulating, searching, and writing
46 * XML data.
47 *
48 * It is possible to construct an invalid XML document. It is also possible that
49 * an invalid XML document created with M_xml will not be readable by M_xml.
50 * Specifically, when dealing with attribute and text encoding options for M_xml_read
51 * and M_xml_write. Also, attribute keys and tag names are not validated to ensure
52 * they are valid XML names. This must happen outside of M_xml.
53 *
54 * M_xml is not susceptible to common XML entity expansion attaches such as
55 * billion laughs, quadratic blowup, and external entity expansion. Only basic
56 * XML entities are expanded and only one level is expanded. Further external
57 * entity references are not downloaded. Neither are external DTDs. This will
58 * mitigate against network based attacks relying on retrieval.
59 *
60 * Example:
61 *
62 * \code{.c}
63 * #include <mstdlib/mstdlib.h>
64 * #include <mstdlib/mstdlib_formats.h>
65 *
66 * int main(int argc, char** argv)
67 * {
68 * M_xml_node_t *xml;
69 * const char *data = "<r><tag1>abc</tag1><tag2>123</tag2><tag3>xyz</tag3></r>";
70 * char *out;
71 *
72 * xml = M_xml_read(data, M_str_len(data), M_XML_READER_NONE, NULL, NULL, NULL, NULL);
73 * if (xml == NULL) {
74 * M_printf("xml parse error\n");
75 * return M_FALSE;
76 * }
77 *
78 * M_xml_create_element_with_text("AbCd", "blah blah blah", 0, xml);
79 *
80 * out = M_xml_write(xml, M_XML_WRITER_LOWER_TAGS|M_XML_WRITER_LOWER_ATTRS|M_XML_WRITER_PRETTYPRINT_SPACE, NULL);
81 * M_printf("out=\n%s\n", out);
82 * M_free(out);
83 * return 0;
84 * }
85 * \endcode
86 *
87 * @{
88 */
89
90 struct M_xml_node;
91 typedef struct M_xml_node M_xml_node_t;
92
93
94/*! Node types in our XML tree structure */
95typedef enum {
96 M_XML_NODE_TYPE_UNKNOWN = 0, /*!< An invalid node type. */
97 M_XML_NODE_TYPE_DOC = 1, /*!< The base of every XML tree and provides access to the
98 documents data.
99 Supports: Nodes.
100 Does not support: Name, Attributes, Text, Tag data. */
101 M_XML_NODE_TYPE_ELEMENT = 2, /*!< Element (tag).
102 E.g: \code{xml}<name key="val" />, <name>...</name>\endcode.
103 Supports: Attributes, Nodes, Name.
104 Does not support: Text, Tag data. */
105 M_XML_NODE_TYPE_TEXT = 3, /*!< Text.
106 E.g: abc.
107 Supports: Text.
108 Does not support: Nodes, Name, Attributes, Tag data. */
109 M_XML_NODE_TYPE_PROCESSING_INSTRUCTION = 4, /*!< Conveys information.
110 E.g: \code{xml}<?xml version="1.0" encoding="UTF-8" ?>\endcode
111 Supports: Name, Attributes, Tag data.
112 Does not support: Nodes, Text. */
113 M_XML_NODE_TYPE_DECLARATION = 5, /*!< HTML/DTD declaration.
114 E.g: \code{xml}<!DOCTYPE html>, <!ELEMENT element-name category>, <!ATTLIST payment type CDATA "check">\endcode
115 Supports: Name, Tag data.
116 Does not support: Nodes, Attributes, text. */
117 M_XML_NODE_TYPE_COMMENT = 6 /*!< Comment.
118 E.g: \code{xml}<!-- comment -->\endcode
119 Supports: Tag data.
120 Does not support: Nodes, Name, Attributes, Text. */
122
123
124/*! Flags to control the behavior of the XML writer. */
125typedef enum {
126 M_XML_READER_NONE = 0, /*!< Normal operation. */
127 M_XML_READER_IGNORE_COMMENTS = 1 << 0, /*!< Don't include comments as part of the output during parse. */
128 M_XML_READER_TAG_CASECMP = 1 << 1, /*!< Compare open and close tags case insensitive. */
129 M_XML_READER_DONT_DECODE_TEXT = 1 << 2, /*!< By default text data will be xml entity decoded.
130 This prevents the decode from taking place. It should be paired
131 with the equivalent don't encode option when writing. */
132 M_XML_READER_DONT_DECODE_ATTRS = 1 << 3 /*!< By default attribute values will be attribute entity decoded.
133 This prevents the decode from taking place. It should be paired
134 with the equivalent don't encode option when writing. */
136
137
138/*! Flags to control the behavior of the XML reader. */
139typedef enum {
140 M_XML_WRITER_NONE = 0, /*!< No indent. All data on a single line. */
141 M_XML_WRITER_IGNORE_COMMENTS = 1 << 0, /*!< Comments are not included. */
142 M_XML_WRITER_LOWER_TAGS = 1 << 1, /*!< All tags are written lower case. */
143 M_XML_WRITER_LOWER_ATTRS = 1 << 2, /*!< All attribute keys are written lower case. */
144 M_XML_WRITER_DONT_ENCODE_TEXT = 1 << 3, /*!< By default text data will be xml entity encoded.
145 This prevents the encode from taking place. It should be paired
146 with the equivalent don't decode option when reading. */
147 M_XML_WRITER_DONT_ENCODE_ATTRS = 1 << 4, /*!< By default attribute values will be attribute entity encoded.
148 This prevents the encode from taking place. It should be paired
149 with the equivalent don't decode option when reading. */
150 M_XML_WRITER_PRETTYPRINT_SPACE = 1 << 5, /*!< 2 space indent. */
151 M_XML_WRITER_PRETTYPRINT_TAB = 1 << 6, /*!< Tab indent. */
152 M_XML_WRITER_SELFCLOSE_SPACE = 1 << 7 /*!< Add a space before the closing slash for self closing tags. */
154
155
156/*! Error codes. */
157typedef enum {
158 M_XML_ERROR_SUCCESS = 0, /*!< success */
159 M_XML_ERROR_GENERIC, /*!< generic error */
160 M_XML_ERROR_MISUSE, /*!< API misuse */
161 M_XML_ERROR_ATTR_EXISTS, /*!< the attribute already exists on the node */
162 M_XML_ERROR_NO_ELEMENTS, /*!< unexpected end of XML, no elements in data */
163 M_XML_ERROR_INVALID_START_TAG, /*!< invalid tag start character */
164 M_XML_ERROR_INVALID_CHAR_IN_START_TAG, /*!< invalid character '<' found in tag */
165 M_XML_ERROR_EMPTY_START_TAG, /*!< only whitespace after tag start */
166 M_XML_ERROR_MISSING_DECLARATION_NAME, /*!< missing name after ! */
167 M_XML_ERROR_INELIGIBLE_FOR_CLOSE, /*!< cannot close element of this type */
168 M_XML_ERROR_UNEXPECTED_CLOSE, /*!< cannot close element with the given tag */
169 M_XML_ERROR_MISSING_CLOSE_TAG, /*!< missing closing element statement(s) */
170 M_XML_ERROR_MISSING_PROCESSING_INSTRUCTION_END, /*!< missing processing instruction close */
171 M_XML_ERROR_EXPECTED_END /*!< expected end but more data found */
173
174
175/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
176
177/*! Create an XML document.
178 *
179 * \return An XML node on success. NULL on failure.
180 *
181 * \see M_xml_node_destroy
182 */
183M_API M_xml_node_t *M_xml_create_doc(void) M_MALLOC;
184
185
186/*! Create an XML element node.
187 *
188 * \param[in] name The tag name for the element.
189 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
190 * if the node should be created without a parent.
191 *
192 * \return An XML node on success. NULL on failure.
193 *
194 * \see M_xml_node_destroy
195 */
196M_API M_xml_node_t *M_xml_create_element(const char *name, M_xml_node_t *parent) M_MALLOC;
197
198
199/*! Create an XML element with text node.
200 *
201 * \param[in] name The tag name for the element.
202 * \param[in] text The text for the element.
203 * \param[in] max_len The maximum length the text is allowed to be when xml encoded. If the encoded length
204 * is greater an error will result. Use 0 to specify that the text length should not be
205 * checked and any length is allowed.
206 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
207 * if the node should be created without a parent.
208 *
209 * \return An XML node on success. NULL on failure.
210 *
211 * \see M_xml_node_destroy
212 */
213M_API M_xml_node_t *M_xml_create_element_with_text(const char *name, const char *text, size_t max_len, M_xml_node_t *parent) M_MALLOC;
214
215
216/*! Create an XML element with text set from num.
217 *
218 * \param[in] name The tag name for the element.
219 * \param[in] num The number to be inserted as the text for the element.
220 * \param[in] max_len The maximum length the text is allowed to be when xml encoded. If the encoded length
221 * is greater an error will result. Use 0 to specify that the text length should not be
222 * checked and any length is allowed.
223 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
224 * if the node should be created without a parent.
225 *
226 * \return A XML node on success. NULL on failure.
227 *
228 * \see M_xml_node_destroy
229 */
230M_API M_xml_node_t *M_xml_create_element_with_num(const char *name, M_int64 num, size_t max_len, M_xml_node_t *parent) M_MALLOC;
231
232
233/*! Create an XML text node.
234 *
235 * \param[in] text The text.
236 * \param[in] max_len The maximum length the text is allowed to be when xml encoded. If the encoded length
237 * is greater an error will result. Use 0 to specify that the text length should not be
238 * checked and any length is allowed.
239 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
240 * if the node should be created without a parent.
241 *
242 * \return An XML node on success. NULL on failure.
243 *
244 * \see M_xml_node_destroy
245 */
246M_API M_xml_node_t *M_xml_create_text(const char *text, size_t max_len, M_xml_node_t *parent) M_MALLOC;
247
248
249/*! Create an XML declaration node.
250 *
251 * E.g:
252 * - <?xml version="1.0" encoding="UTF-8" ?>
253 *
254 * \param[in] encoding The encoding.
255 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
256 * if the node should be created without a parent.
257 *
258 * \return An XML node on success. NULL on failure.
259 *
260 * \see M_xml_node_destroy
261 */
262M_API M_xml_node_t *M_xml_create_xml_declaration(const char *encoding, M_xml_node_t *parent) M_MALLOC;
263
264
265/*! Create a declaration node.
266 *
267 * E.g:
268 * - \code{xml}<!DOCTYPE html>\endcode
269 * - \code{xml}<!ELEMENT element-name category>\endcode
270 * - \code{xml}<!ATTLIST payment type CDATA "check">\endcode
271 *
272 * \param[in] name The tag name for the declaration.
273 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
274 * if the node should be created without a parent.
275 *
276 * \return An XML node on success. NULL on failure.
277 *
278 * \see M_xml_node_destroy
279 */
280M_API M_xml_node_t *M_xml_create_declaration(const char *name, M_xml_node_t *parent) M_MALLOC;
281
282
283/*! Create a declaration node.
284 *
285 * E.g:
286 * - \code{xml}<!DOCTYPE html>\endcode
287 * - \code{xml}<!ELEMENT element-name category>\endcode
288 * - \code{xml}<!ATTLIST payment type CDATA "check">\endcode
289 *
290 * \param[in] name The tag name for the declaration.
291 * \param[in] data The tag data.
292 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
293 * if the node should be created without a parent.
294 *
295 * \return An XML node on success. NULL on failure.
296 *
297 * \see M_xml_node_destroy
298 */
299M_API M_xml_node_t *M_xml_create_declaration_with_tag_data(const char *name, const char *data, M_xml_node_t *parent) M_MALLOC;
300
301
302/*! Create an XML processing instruction node.
303 *
304 * \param[in] name The instruction name for the node.
305 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
306 * if the node should be created without a parent.
307 *
308 * \return An XML node on success. NULL on failure.
309 *
310 * \see M_xml_node_destroy
311 */
312M_API M_xml_node_t *M_xml_create_processing_instruction(const char *name, M_xml_node_t *parent) M_MALLOC;
313
314
315/*! Create an XML comment node.
316 *
317 * \param[in] comment The comment.
318 * \param[in,out] parent The parent this node should be inserted into. Optional, pass NULL
319 * if the node should be created without a parent.
320 *
321 * \return An XML node on success. NULL on failure.
322 *
323 * \see M_xml_node_destroy
324 */
325M_API M_xml_node_t *M_xml_create_comment(const char *comment, M_xml_node_t *parent) M_MALLOC;
326
327
328/*! Destroy an XML node.
329 *
330 * Destroying a node will destroy every node under it and remove it from it's parent node if it is a child.
331 *
332 * \param[in] node The node to destroy.
333 */
334M_API void M_xml_node_destroy(M_xml_node_t *node) M_FREE(1);
335
336
337/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
338
339/*! Parse a string into an XML object.
340 *
341 * \param[in] data The data to parse.
342 * \param[in] data_len The length of the data to parse.
343 * \param[in] flags M_xml_reader_flags_t flags to control the behavior of the reader.
344 * \param[out] processed_len Length of data processed. Useful if you could have multiple XML documents
345 * in a stream. Optional pass NULL if not needed.
346 * \param[out] error Error code if creation failed. Optional, Pass NULL if not needed.
347 * \param[out] error_line The line the error occurred. Optional, pass NULL if not needed.
348 * \param[out] error_pos The column the error occurred if error_line is not NULL, otherwise the position
349 * in the stream the error occurred. Optional, pass NULL if not needed.
350 * \return The XML doc node of the parsed data, or NULL on error.
351 */
352M_API M_xml_node_t *M_xml_read(const char *data, size_t data_len, M_uint32 flags, size_t *processed_len, M_xml_error_t *error, size_t *error_line, size_t *error_pos) M_MALLOC;
353
354
355/*! Parse a file into an XML object.
356 *
357 * \param[in] path The file to read.
358 * \param[in] flags M_xml_reader_flags_t flags to control the behavior of the reader.
359 * \param[in] max_read The maximum amount of data to read from the file. If the data in the file is
360 * larger than max_read an error will most likely result. Optional pass 0 to read all data.
361 * \param[out] error Error code if creation failed. Optional, Pass NULL if not needed.
362 * \param[out] error_line The line the error occurred. Optional, pass NULL if not needed.
363 * \param[out] error_pos The column the error occurred if error_line is not NULL, otherwise the position
364 * in the stream the error occurred. Optional, pass NULL if not needed.
365 *
366 * \return The XML doc node of the parsed data, or NULL on error.
367 */
368M_API M_xml_node_t *M_xml_read_file(const char *path, M_uint32 flags, size_t max_read, M_xml_error_t *error, size_t *error_line, size_t *error_pos) M_MALLOC;
369
370
371/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
372
373/*! Write XML to a string.
374 *
375 * This writes nodes to a string. The string may not be directly usable by M_xml_read.
376 * E.g. If you are only writing a string node.
377 *
378 * \param[in] node The node to write. This will write the node and any nodes under it.
379 * \param[in] flags M_xml_writer_flags_t flags to control writing.
380 * \param[out] len The length of the string that was returned. Optional, pass NULL if not needed.
381 *
382 * \return A string with data or NULL on error.
383 */
384M_API char *M_xml_write(const M_xml_node_t *node, M_uint32 flags, size_t *len) M_WARN_UNUSED_RESULT M_MALLOC;
385
386
387/*! Write XML to a buffer.
388 *
389 * This writes nodes out to a buffer. The resulting string may not be directly usable by M_xml_read -
390 * for example, you can write out a string node or other component of an XML document, without writing
391 * the whole thing.
392 *
393 * \param[out] buf buffer to write XML to
394 * \param[in] node the node to write (children of this node are also included in output)
395 * \param[in] flags OR'd combo of M_xml_write_flags_t values (to control writing)
396 * \return M_TRUE if successful, M_FALSE otherwise.
397 */
398M_API M_bool M_xml_write_buf(M_buf_t *buf, const M_xml_node_t *node, M_uint32 flags);
399
400
401/*! Write XML to a file.
402 *
403 * This writes nodes to a string. The string may not be directly usable by M_xml_read_file.
404 * E.g. If you are only writing a string node.
405 *
406 * \param[in] node The node to write. This will write the node and any nodes under it.
407 * \param[in] path The filename and path to write the data to.
408 * \param[in] flags M_xml_writer_flags_t flags to control writing.
409 *
410 * \return Result.
411 */
412M_API M_fs_error_t M_xml_write_file(const M_xml_node_t *node, const char *path, M_uint32 flags);
413
414
415/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
416
417/*! Convert an XML error code to a string.
418 *
419 * \param[in] err error code
420 * \return name of error code (not a description, just the enum name, like M_XML_ERROR_SUCCESS)
421 */
422M_API const char *M_xml_errcode_to_str(M_xml_error_t err);
423
424/*! Get the type of node.
425 *
426 * \param[in] node The node.
427 *
428 * \return The type.
429 */
431
432
433/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
434
435/*! Using XPath expressions, scan for matches.
436 *
437 * Note that full XPath support does not yet exist. Also only element nodes are currently returned unless text() is
438 * used to return text nodes.
439 *
440 * This will return an array of nodes within the tree. The nodes in the return are not copies, they are
441 * references. Changing a node in the xpath return will modify the node in the tree.
442 *
443 * Supports:
444 * Syntax | Meaning
445 * -------------------|---------
446 * tag | Selects children of the current element node with the given tag name.
447 * *:tag | Selects children of the current element node with the given tag name ignoring any namespace on the tag. Also matches tags without a namespace.
448 * * | Selects all children of the current element node.
449 * / | Selects children one level below the current element node.
450 * // | Selects children on all levels bellow the current element node.
451 * . | Selects the current element node.
452 * .. | Selects the parent of the current element node.
453 * text() | Selects all text nodes.
454 * [\@attrib] | Selects elements which have an attribute attrib.
455 * [\@attrib=val] | Selects elements which have an attribute attrib with a value of val.
456 * [\@attrib="val"] | Selects elements which have an attribute attrib with a value of val.
457 * [\@attrib='val'] | Selects elements which have an attribute attrib with a value of val.
458 * [\@*] | Selects elements which have an (any) attribute set.
459 * [idx] | Select an element at a given position.
460 * [position() ? idx] | Select an element at a given position.
461 *
462 * More information about [idx]:
463 *
464 * Index matching can either be an integer (starting from 1) or the expression "last()". "last()" can
465 * be followed by a negative integer in order to count backwards from the last elements. For example: "last()-1"
466 * is the second to last element. The idx is not the index within the parent the node but the index of the
467 * matching nodes. idx must be preceded by either a tag or text().
468 *
469 * More information about [position() ? idx]:
470 *
471 * Position matching can use the equality modifiers '=', '<=', '>=', '<', '>'. These will select one or
472 * more nodes that match the given criteria. "last()" can be used as the index.
473 *
474 * E.g: "a/b[2]" for `<a><b/><c/><b/></a>` will select the second "b" after "c".
475 *
476 * \param[in] node The node.
477 * \param[in] search search expression
478 * \param[in] flags M_xml_reader_flags_t flags to control the behavior of the search.
479 * valid flags are:
480 * - M_XML_READER_NONE
481 * - M_XML_READER_TAG_CASECMP
482 * \param[out] num_matches Number of matches found
483 *
484 * \return array of M_xml_node_t pointers on success (must free array, but not internal pointers), NULL on failure
485 */
486M_API M_xml_node_t **M_xml_xpath(M_xml_node_t *node, const char *search, M_uint32 flags, size_t *num_matches) M_MALLOC;
487
488
489/*! Using XPath expressions, scan for matches and return the first text value.
490 *
491 * This will only return the first text node. Meaning if multiple text nodes are inserted in a row only the
492 * text from the first will be returned. If the XML tree was created using M_xml_read or M_xml_read_file then
493 * the fist text node will contain all of the text.
494 *
495 * \see M_xml_xpath for information about supported XPath features.
496 *
497 * \param[in] node The node.
498 * \param[in] search search expression
499 *
500 * \return Text on success otherwise NULL.
501 */
502M_API const char *M_xml_xpath_text_first(M_xml_node_t *node, const char *search);
503
504
505/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
506
507/*! Get the parent node of a given node.
508 *
509 * \param[in] node The node.
510 *
511 * \return The parent node or NULL if there is no parent.
512 */
514
515
516/*! Take a node from its parent but does not destroy the node.
517 *
518 * This allows a node to be moved between different parents.
519 *
520 * \param[in,out] node The node.
521 */
523
524
525/*! Insert a node into a doc or element node.
526 *
527 * The parent node will take ownership of the child node.
528 *
529 * Only parentless nodes can be insert into other nodes. You must use M_xml_take_from_parent first if you
530 * are moving nodes from one parent to another.
531 *
532 * \param[in,out] parent The parent node.
533 * \param[in] child The child node.
534 *
535 * \return M_TRUE on success otherwise M_FALSE.
536 */
538
539
540/*! Insert a node into a doc or element node at a given position.
541 *
542 * The parent node will take ownership of the child node.
543 *
544 * \param[in,out] parent The parent node.
545 * \param[in] child The child node.
546 * \param[in] idx The location where the node should be inserted.
547 *
548 * \return M_TRUE on success otherwise M_FALSE.
549 */
550M_API M_bool M_xml_node_insert_node_at(M_xml_node_t *parent, M_xml_node_t *child, size_t idx);
551
552
553/*! Get the number of child nodes for a doc or element node.
554 *
555 * \param[in] node The node.
556 *
557 * \return The number of children.
558 *
559 * \see M_xml_node_child
560 */
561M_API size_t M_xml_node_num_children(const M_xml_node_t *node);
562
563
564/*! Get the child node at the given position for a doc or element node.
565 *
566 * \param[in] node The node.
567 * \param[in] idx The position for the child to retrieve.
568 *
569 * \return The child node or NULL if a child does not exist at the given position.
570 *
571 * \see M_xml_node_num_children
572 */
573M_API M_xml_node_t *M_xml_node_child(const M_xml_node_t *node, size_t idx);
574
575
576/*! Get the sibling for the node.
577 *
578 * The sibling is the node at the same level as the current node which is either
579 * before or after the node.
580 *
581 * \param[in] node The node.
582 * \param[in] after M_TRUE to return the node after. M_FALSE to return the one before.
583 *
584 * \return The sibling node. NULL if there is no sibling in the given direction.
585 */
586M_API M_xml_node_t *M_xml_node_sibling(const M_xml_node_t *node, M_bool after);
587
588
589/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
590
591/*! Set the tag name for an element or processing instruction node.
592 *
593 * The name is the tag name. E.g. "<name>".
594 * This will change the name of the node.
595 *
596 * \param[in,out] node The node.
597 * \param[in] name The name.
598 *
599 * \return M_TRUE on sucess otherwise M_FALSE.
600 */
601M_API M_bool M_xml_node_set_name(M_xml_node_t *node, const char *name);
602
603
604/*! Get the tag name for node an element or processing instruction node.
605 *
606 * \param[in] node The node.
607 *
608 * \return The name.
609 */
610M_API const char *M_xml_node_name(const M_xml_node_t *node);
611
612
613/*! Set the text for a text node.
614 *
615 * \param[in,out] node The node.
616 * \param[in] text The text.
617 * \param[in] max_len The maximum length the text is allowed to be when xml encoded. If the encoded length
618 * is greater an error will result. Use 0 to specify that the text length should not be
619 * checked and any length is allowed.
620 *
621 * \return M_TRUE on success, otherwise M_FALSE.
622 */
623M_API M_bool M_xml_node_set_text(M_xml_node_t *node, const char *text, size_t max_len);
624
625
626/*! Get the text for a text node.
627 *
628 * \param[in] node The node
629 *
630 * \return The node's text.
631 */
632M_API const char *M_xml_node_text(const M_xml_node_t *node);
633
634
635/*! Set the tag data for a node.
636 *
637 * \param[in,out] node The node.
638 * \param[in] data The tag data.
639 *
640 * \return M_TRUE on success, otherwise M_FALSE.
641 */
642M_API M_bool M_xml_node_set_tag_data(M_xml_node_t *node, const char *data);
643
644
645/*! Get the tag data for a node.
646 *
647 * \param[in] node The node
648 *
649 * \return The node's tag data.
650 */
651M_API const char *M_xml_node_tag_data(const M_xml_node_t *node);
652
653
654/*! Insert an attribute into an element or processing instruction node.
655 *
656 * \param[in,out] node The node.
657 * \param[in] key The attribute key.
658 * \param[in] val The attribute value.
659 * \param[in] max_len The maximum length the text is allowed to be when xml encoded. If the encoded length
660 * is greater an error will result. Use 0 to specify that the text length should not be
661 * checked and any length is allowed.
662 * \param[in] overwrite Action to take when the given key exists. If M_TRUE the value will be overwritten when
663 * with the given value. If M_FALSE the attribute will not be written. This will be treated
664 * as an error condition.
665 *
666 * \return M_TRUE on success, otherwise M_FALSE.
667 */
668M_API M_bool M_xml_node_insert_attribute(M_xml_node_t *node, const char *key, const char *val, size_t max_len, M_bool overwrite);
669
670
671/*! Remove an attribute from an element or processing instruction node.
672 *
673 * \param[in,out] node The node.
674 * \param[in] key The attribute key.
675 *
676 * \return M_TRUE on success, otherwise M_FALSE.
677 */
678M_API M_bool M_xml_node_remove_attribute(M_xml_node_t *node, const char *key);
679
680
681/*! Get a list of all attribute keys set for an element or processing instruction node.
682 *
683 * \param[in] node The node.
684 *
685 * \return A list of keys.
686 */
688
689
690/*! Get a dictionary of all attribute set for an element or processing instruction node.
691 *
692 * \param[in] node The node.
693 *
694 * \return A dictionary with attributes.
695 */
697
698
699/*! Get the value of a given attribute for an element or processing instruction node.
700 *
701 * \param[in] node The node.
702 * \param[in] key The attribute key.
703 *
704 * \return The value of the attribute. NULL if the key does not exist.
705 */
706M_API const char *M_xml_node_attribute(const M_xml_node_t *node, const char *key);
707
708/*! @} */
709
710__END_DECLS
711
712#endif /* __M_XML_H__ */
struct M_buf M_buf_t
Definition: m_buf.h:77
M_fs_error_t
Definition: m_fs.h:154
struct M_hash_dict M_hash_dict_t
Definition: m_hash_dict.h:52
struct M_list_str M_list_str_t
Definition: m_list_str.h:80
M_xml_node_t * M_xml_node_child(const M_xml_node_t *node, size_t idx)
M_fs_error_t M_xml_write_file(const M_xml_node_t *node, const char *path, M_uint32 flags)
M_bool M_xml_node_remove_attribute(M_xml_node_t *node, const char *key)
M_xml_node_t * M_xml_create_declaration(const char *name, M_xml_node_t *parent) M_MALLOC
M_xml_node_type_t M_xml_node_type(const M_xml_node_t *node)
M_xml_node_t * M_xml_node_parent(const M_xml_node_t *node)
char * M_xml_write(const M_xml_node_t *node, M_uint32 flags, size_t *len) M_WARN_UNUSED_RESULT M_MALLOC
M_xml_node_t * M_xml_create_text(const char *text, size_t max_len, M_xml_node_t *parent) M_MALLOC
void M_xml_take_from_parent(M_xml_node_t *node)
M_xml_node_t * M_xml_create_processing_instruction(const char *name, M_xml_node_t *parent) M_MALLOC
M_xml_writer_flags_t
Definition: m_xml.h:139
M_bool M_xml_node_set_tag_data(M_xml_node_t *node, const char *data)
M_bool M_xml_node_insert_node_at(M_xml_node_t *parent, M_xml_node_t *child, size_t idx)
const char * M_xml_xpath_text_first(M_xml_node_t *node, const char *search)
M_bool M_xml_node_insert_node(M_xml_node_t *parent, M_xml_node_t *child)
M_xml_node_type_t
Definition: m_xml.h:95
M_bool M_xml_node_set_text(M_xml_node_t *node, const char *text, size_t max_len)
M_xml_error_t
Definition: m_xml.h:157
M_bool M_xml_write_buf(M_buf_t *buf, const M_xml_node_t *node, M_uint32 flags)
M_xml_node_t * M_xml_node_sibling(const M_xml_node_t *node, M_bool after)
const M_hash_dict_t * M_xml_node_attributes(const M_xml_node_t *node)
const char * M_xml_errcode_to_str(M_xml_error_t err)
const char * M_xml_node_name(const M_xml_node_t *node)
M_xml_node_t * M_xml_create_element(const char *name, M_xml_node_t *parent) M_MALLOC
M_bool M_xml_node_set_name(M_xml_node_t *node, const char *name)
const char * M_xml_node_attribute(const M_xml_node_t *node, const char *key)
void M_xml_node_destroy(M_xml_node_t *node) M_FREE(1)
M_bool M_xml_node_insert_attribute(M_xml_node_t *node, const char *key, const char *val, size_t max_len, M_bool overwrite)
M_xml_node_t * M_xml_create_element_with_num(const char *name, M_int64 num, size_t max_len, M_xml_node_t *parent) M_MALLOC
const char * M_xml_node_tag_data(const M_xml_node_t *node)
size_t M_xml_node_num_children(const M_xml_node_t *node)
M_xml_node_t ** M_xml_xpath(M_xml_node_t *node, const char *search, M_uint32 flags, size_t *num_matches) M_MALLOC
struct M_xml_node M_xml_node_t
Definition: m_xml.h:91
M_list_str_t * M_xml_node_attribute_keys(const M_xml_node_t *node) M_MALLOC
M_xml_node_t * M_xml_create_comment(const char *comment, M_xml_node_t *parent) M_MALLOC
M_xml_node_t * M_xml_read_file(const char *path, M_uint32 flags, size_t max_read, M_xml_error_t *error, size_t *error_line, size_t *error_pos) M_MALLOC
const char * M_xml_node_text(const M_xml_node_t *node)
M_xml_node_t * M_xml_create_doc(void) M_MALLOC
M_xml_node_t * M_xml_create_declaration_with_tag_data(const char *name, const char *data, M_xml_node_t *parent) M_MALLOC
M_xml_reader_flags_t
Definition: m_xml.h:125
M_xml_node_t * M_xml_create_xml_declaration(const char *encoding, M_xml_node_t *parent) M_MALLOC
M_xml_node_t * M_xml_read(const char *data, size_t data_len, M_uint32 flags, size_t *processed_len, M_xml_error_t *error, size_t *error_line, size_t *error_pos) M_MALLOC
M_xml_node_t * M_xml_create_element_with_text(const char *name, const char *text, size_t max_len, M_xml_node_t *parent) M_MALLOC
@ M_XML_WRITER_DONT_ENCODE_TEXT
Definition: m_xml.h:144
@ M_XML_WRITER_PRETTYPRINT_SPACE
Definition: m_xml.h:150
@ M_XML_WRITER_IGNORE_COMMENTS
Definition: m_xml.h:141
@ M_XML_WRITER_LOWER_ATTRS
Definition: m_xml.h:143
@ M_XML_WRITER_PRETTYPRINT_TAB
Definition: m_xml.h:151
@ M_XML_WRITER_SELFCLOSE_SPACE
Definition: m_xml.h:152
@ M_XML_WRITER_DONT_ENCODE_ATTRS
Definition: m_xml.h:147
@ M_XML_WRITER_NONE
Definition: m_xml.h:140
@ M_XML_WRITER_LOWER_TAGS
Definition: m_xml.h:142
@ M_XML_NODE_TYPE_ELEMENT
Definition: m_xml.h:101
@ M_XML_NODE_TYPE_COMMENT
Definition: m_xml.h:117
@ M_XML_NODE_TYPE_TEXT
Definition: m_xml.h:105
@ M_XML_NODE_TYPE_PROCESSING_INSTRUCTION
Definition: m_xml.h:109
@ M_XML_NODE_TYPE_DECLARATION
Definition: m_xml.h:113
@ M_XML_NODE_TYPE_DOC
Definition: m_xml.h:97
@ M_XML_NODE_TYPE_UNKNOWN
Definition: m_xml.h:96
@ M_XML_ERROR_INVALID_CHAR_IN_START_TAG
Definition: m_xml.h:164
@ M_XML_ERROR_MISUSE
Definition: m_xml.h:160
@ M_XML_ERROR_EXPECTED_END
Definition: m_xml.h:171
@ M_XML_ERROR_INELIGIBLE_FOR_CLOSE
Definition: m_xml.h:167
@ M_XML_ERROR_EMPTY_START_TAG
Definition: m_xml.h:165
@ M_XML_ERROR_INVALID_START_TAG
Definition: m_xml.h:163
@ M_XML_ERROR_MISSING_CLOSE_TAG
Definition: m_xml.h:169
@ M_XML_ERROR_SUCCESS
Definition: m_xml.h:158
@ M_XML_ERROR_UNEXPECTED_CLOSE
Definition: m_xml.h:168
@ M_XML_ERROR_GENERIC
Definition: m_xml.h:159
@ M_XML_ERROR_ATTR_EXISTS
Definition: m_xml.h:161
@ M_XML_ERROR_NO_ELEMENTS
Definition: m_xml.h:162
@ M_XML_ERROR_MISSING_PROCESSING_INSTRUCTION_END
Definition: m_xml.h:170
@ M_XML_ERROR_MISSING_DECLARATION_NAME
Definition: m_xml.h:166
@ M_XML_READER_DONT_DECODE_TEXT
Definition: m_xml.h:129
@ M_XML_READER_DONT_DECODE_ATTRS
Definition: m_xml.h:132
@ M_XML_READER_NONE
Definition: m_xml.h:126
@ M_XML_READER_TAG_CASECMP
Definition: m_xml.h:128
@ M_XML_READER_IGNORE_COMMENTS
Definition: m_xml.h:127