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