1 /**
2  * @file xml.h
3  * @author Radek Krejci <rkrejci@cesnet.cz>
4  * @brief Public API of libyang XML parser
5  *
6  * Copyright (c) 2015 CESNET, z.s.p.o.
7  *
8  * This source code is licensed under BSD 3-Clause License (the "License").
9  * You may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     https://opensource.org/licenses/BSD-3-Clause
13  */
14 
15 #ifndef LY_XML_H_
16 #define LY_XML_H_
17 
18 #include <sys/types.h>
19 #include <stdio.h>
20 
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24 
25 /**
26  * @defgroup xmlparser XML Parser
27  *
28  * Simplified libyang XML parser for XML data modeled by YANG.
29  *
30  * @{
31  */
32 
33 /*
34  * Structures
35  */
36 
37 /*
38  * structure definition from context.h
39  */
40 struct ly_ctx;
41 
42 /**
43  * @brief enumeration of attribute types
44  */
45 typedef enum lyxml_attr_type {
46     LYXML_ATTR_STD = 1,              /**< standard XML attribute */
47     LYXML_ATTR_NS = 2,               /**< XML namespace definition */
48     LYXML_ATTR_STD_UNRES = 3         /**< standard XML attribute with unresolved namespace, its ns attribute is actually prefix */
49 } LYXML_ATTR_TYPE;
50 
51 /**
52  * @brief Namespace definition.
53  *
54  * The structure is actually casted lyxml_attr structure which covers all
55  * attributes defined in an element. The namespace definition is in this case
56  * also covered by lyxml_attr structure.
57  */
58 struct lyxml_ns {
59     LYXML_ATTR_TYPE type;            /**< type of the attribute = LYXML_ATTR_NS */
60     struct lyxml_ns *next;           /**< next sibling attribute */
61     struct lyxml_elem *parent;       /**< parent node of the attribute */
62     const char *prefix;              /**< the namespace prefix if defined, NULL for default namespace */
63     const char *value;               /**< the namespace value */
64 };
65 
66 /**
67  * @brief Element's attribute definition
68  *
69  * The structure actually covers both the attributes as well as namespace
70  * definitions.
71  *
72  * Attributes are being connected only into a singly linked list (compare it
73  * with the elements).
74  */
75 struct lyxml_attr {
76     LYXML_ATTR_TYPE type;            /**< type of the attribute */
77     struct lyxml_attr *next;         /**< next sibling attribute */
78     const struct lyxml_ns *ns;       /**< pointer to the namespace of the attribute if any */
79     const char *name;                /**< name of the attribute (the LocalPart of the qualified name) */
80     const char *value;               /**< data stored in the attribute */
81 };
82 
83 /**
84  * @brief Structure describing an element in an XML tree.
85  *
86  * If the name item is NULL, then the content is part of the mixed content.
87  *
88  * Children elements are connected in a half ring doubly linked list:
89  * - first's prev pointer points to the last children
90  * - last's next pointer is NULL
91  */
92 struct lyxml_elem {
93     char flags;                      /**< special flags */
94 #define LYXML_ELEM_MIXED 0x01 /* element contains mixed content */
95 /* 0x80 is reserved and cannot be set! */
96 
97     struct lyxml_elem *parent;       /**< parent node */
98     struct lyxml_attr *attr;         /**< first attribute declared in the element */
99     struct lyxml_elem *child;        /**< first children element */
100     struct lyxml_elem *next;         /**< next sibling node */
101     struct lyxml_elem *prev;         /**< previous sibling node */
102 
103     const char *name;                /**< name of the element */
104     const struct lyxml_ns *ns;       /**< namespace of the element */
105     const char *content;             /**< text content of the node if any */
106 };
107 
108 /*
109  * Functions
110  * Parser
111  */
112 
113 /**
114  * @defgroup xmlreadoptions XML parser options
115  * @ingroup xmlparser
116  *
117  * Various options to change behavior of XML read functions (lyxml_parse_*()).
118  *
119  * @{
120  */
121 #define LYXML_PARSE_MULTIROOT 0x01 /**< By default, XML is supposed to be well-formed so the input file or memory chunk
122                                         contains only a single XML tree. This option make parser to read multiple XML
123                                         trees from a single source (regular file terminated by EOF or memory chunk
124                                         terminated by NULL byte). In such a case, the returned XML element has other
125                                         siblings representing the other XML trees from the source. */
126 #define LYXML_PARSE_NOMIXEDCONTENT 0x02 /**< By default, the parser allows elements with mixed content (text content
127                                         mixed with standard XML children). This option cases to handle such elements
128                                         as invalid input (#LYVE_XML_INVAL). */
129 
130 /**
131  * @}
132  */
133 
134 /**
135  * @brief Parse XML from in-memory string
136  *
137  * @param[in] ctx libyang context to use
138  * @param[in] data Pointer to a NULL-terminated string containing XML data to
139  * parse.
140  * @param[in] options Parser options, see @ref xmlreadoptions.
141  * @return Pointer to the root of the parsed XML document tree or NULL in case of empty \p data. To free the
142  *         returned data, use lyxml_free(). In these cases, the function sets #ly_errno to LY_SUCCESS. In case
143  *         of error, #ly_errno contains appropriate error code (see #LY_ERR).
144  */
145 struct lyxml_elem *lyxml_parse_mem(struct ly_ctx *ctx, const char *data, int options);
146 
147 /**
148  * @brief Parse XML from filesystem
149  *
150  * @param[in] ctx libyang context to use
151  * @param[in] filename Path to the file where read data to parse
152  * @param[in] options Parser options, see @ref xmlreadoptions.
153  * @return Pointer to the root of the parsed XML document tree or NULL in case of empty file. To free the
154  *         returned data, use lyxml_free(). In these cases, the function sets #ly_errno to LY_SUCCESS. In case
155  *         of error, #ly_errno contains appropriate error code (see #LY_ERR).
156  */
157 struct lyxml_elem *lyxml_parse_path(struct ly_ctx *ctx, const char *filename, int options);
158 
159 /**
160  * @defgroup xmldumpoptions XML printer options
161  * @ingroup xmlparser
162  *
163  * Various options to change behavior of XML dump functions (lyxml_print_*()).
164  *
165  * When no option is specified (value 0), dumper prints all the content at once.
166  *
167  * @{
168  */
169 #define LYXML_PRINT_OPEN   0x01  /**< print only the open part of the XML element.
170                                    If used in combination with #LYXML_PRINT_CLOSE, it prints the element without
171                                    its children: \<element/\>. If none of these two options is used, the element
172                                    is printed including all its children. */
173 #define LYXML_PRINT_FORMAT 0x02  /**< format the output.
174                                    If option is not used, the element and its children are printed without indentantion.
175                                    If used in combination with #LYXML_PRINT_CLOSE or LYXML_PRINT_ATTRS or LYXML_PRINT_OPEN,
176                                    it has no effect.*/
177 #define LYXML_PRINT_CLOSE  0x04  /**< print only the closing part of the XML element.
178                                    If used in combination with #LYXML_PRINT_OPEN, it prints the element without
179                                    its children: \<element/\>. If none of these two options is used, the element
180                                    is printed including all its children. */
181 #define LYXML_PRINT_ATTRS  0x08  /**< dump only attributes and namespace declarations of the element (element name
182                                    is not printed). This option cannot be used in combination with
183                                    #LYXML_PRINT_OPEN and/or #LYXML_PRINT_CLOSE */
184 #define LYXML_PRINT_SIBLINGS 0x10/**< dump all top-level siblings. By default, the given XML element is supposed to be
185                                    the only root element (and document is supposed to be well-formed XML). With this
186                                    option the printer consider that the given XML element can has some sibling
187                                    elements and print them all (so the given element is not necessarily printed as
188                                    the first one). */
189 #define LYXML_PRINT_NO_LAST_NEWLINE 0x20 /**< makes sense only combined with LYXML_PRINT_FORMAT and causes the very
190                                            last newline not to be printed - necessary for correct anyxml XML structure
191                                            print. */
192 
193 /**
194  * @}
195  */
196 
197 /**
198  * @brief Dump XML tree to a IO stream
199  *
200  * To write data into a file descriptor instead of file stream, use lyxml_print_fd().
201  *
202  * @param[in] stream IO stream to print out the tree.
203  * @param[in] elem Root element of the XML tree to print
204  * @param[in] options Dump options, see @ref xmldumpoptions.
205  * @return number of printed characters.
206  */
207 int lyxml_print_file(FILE * stream, const struct lyxml_elem *elem, int options);
208 
209 /**
210  * @brief Dump XML tree to a IO stream
211  *
212  * Same as lyxml_dump(), but it writes data into the given file descriptor.
213  *
214  * @param[in] fd File descriptor to print out the tree.
215  * @param[in] elem Root element of the XML tree to print
216  * @param[in] options Dump options, see @ref xmldumpoptions.
217  * @return number of printed characters.
218  */
219 int lyxml_print_fd(int fd, const struct lyxml_elem *elem, int options);
220 
221 /**
222  * @brief Dump XML tree to a IO stream
223  *
224  * Same as lyxml_dump(), but it allocates memory and store the data into it.
225  * It is up to caller to free the returned string by free().
226  *
227  * @param[out] strp Pointer to store the resulting dump.
228  * @param[in] elem Root element of the XML tree to print
229  * @param[in] options Dump options, see @ref xmldumpoptions.
230  * @return number of printed characters.
231  */
232 int lyxml_print_mem(char **strp, const struct lyxml_elem *elem, int options);
233 
234 /**
235  * @brief Dump XML tree to a IO stream
236  *
237  * Same as lyxml_dump(), but it writes data via the provided callback.
238  *
239  * @param[in] writeclb Callback function to write the data (see write(1)).
240  * @param[in] arg Optional caller-specific argument to be passed to the \p writeclb callback.
241  * @param[in] elem Root element of the XML tree to print
242  * @param[in] options Dump options, see @ref xmldumpoptions.
243  * @return number of printed characters.
244  */
245 int lyxml_print_clb(ssize_t (*writeclb)(void *arg, const void *buf, size_t count), void *arg, const struct lyxml_elem *elem, int options);
246 
247 /**
248  * @brief Duplicate the XML tree into the different content.
249  *
250  * Date parser requires to have the input XML tree in the same context as the resulting data tree. Therefore,
251  * if you need to parse a single XML tree into a different contexts, you have to duplicate the source XML
252  * tree into the required context first.
253  *
254  * @param[in] ctx Target context for the result.
255  * @param[in] root Root node of the XML tree to duplicate. If an internal node is provided,
256  *            the parents are not duplicated and only the specified subtree is duplicated.
257  * @result Pointer to the duplicated tree or NULL on error.
258  */
259 struct lyxml_elem *lyxml_dup(struct ly_ctx *ctx, struct lyxml_elem *root);
260 
261 /**
262  * @brief Free (and unlink from the XML tree) the specified element with all
263  * its attributes and namespace definitions.
264  *
265  * @param[in] ctx libyang context to use
266  * @param[in] elem Pointer to the element to free.
267  */
268 void lyxml_free(struct ly_ctx *ctx, struct lyxml_elem *elem);
269 
270 /**
271  * @brief Free (and unlink from the XML tree) the specified (sub)tree with all
272  * its attributes and namespace definitions. In contrast to lyxml_free(), free also
273  * all the element's siblings (preceding as well as following).
274  *
275  * @param[in] ctx libyang context to use
276  * @param[in] elem Pointer to the element to free.
277  */
278 void lyxml_free_withsiblings(struct ly_ctx *ctx, struct lyxml_elem *elem);
279 
280 /**
281  * @brief Unlink the element from its parent. In contrast to lyxml_free(),
282  * after return the caller can still manipulate with the elem. Any namespaces
283  * are corrected and copied, if needed.
284  *
285  * @param[in] ctx libyang context to use.
286  * @param[in] elem Element to unlink from its parent (if any).
287  */
288 void lyxml_unlink(struct ly_ctx *ctx, struct lyxml_elem *elem);
289 
290 /**
291  * @brief Get value of the attribute in the specified element.
292  */
293 const char *lyxml_get_attr(const struct lyxml_elem *elem, const char *name, const char *ns);
294 
295 /**
296  * @brief Get namespace definition of the given prefix in context of the specified element.
297  *
298  * @param[in] elem Element where start namespace searching
299  * @param[in] prefix Prefix of the namespace to search for
300  * @return Namespace definition or NULL if no such namespace exists
301  */
302 const struct lyxml_ns *lyxml_get_ns(const struct lyxml_elem *elem, const char *prefix);
303 
304 /**@}*/
305 
306 #ifdef __cplusplus
307 }
308 #endif
309 
310 #endif /* LY_XML_H_ */
311