blob: 4948fc0ea82853973d3a6f86576f87ac0f84f144 [file] [log] [blame]
/**
* @file xml.h
* @author Radek Krejci <rkrejci@cesnet.cz>
* @brief XML parser for libyang
*
* Copyright (c) 2015 CESNET, z.s.p.o.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of the Company nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*/
#ifndef LY_XML_H_
#define LY_XML_H_
#include <stdio.h>
/*
* Macro to test if character is #x20 | #x9 | #xA | #xD (whitespace)
*/
#define is_xmlws(c) (c == 0x20 || c == 0x9 || c == 0xa || c == 0xd)
#define is_xmlnamestartchar(c) ((c >= 'a' && c <= 'z') || c == '_' || \
(c >= 'A' && c <= 'Z') || c == ':' || \
(c >= 0x370 && c <= 0x1fff && c != 0x37e ) || \
(c >= 0xc0 && c <= 0x2ff && c != 0xd7 && c != 0xf7) || c == 0x200c || \
c == 0x200d || (c >= 0x2070 && c <= 0x218f) || \
(c >= 0x2c00 && c <= 0x2fef) || (c >= 0x3001 && c <= 0xd7ff) || \
(c >= 0xf900 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
(c >= 0x10000 && c <= 0xeffff))
#define is_xmlnamechar(c) ((c >= 'a' && c <= 'z') || c == '_' || c == '-' || \
(c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == ':' || \
c == '.' || c == 0xb7 || (c >= 0x370 && c <= 0x1fff && c != 0x37e ) ||\
(c >= 0xc0 && c <= 0x2ff && c != 0xd7 && c != 0xf7) || c == 0x200c || \
c == 0x200d || (c >= 0x300 && c <= 0x36f) || \
(c >= 0x2070 && c <= 0x218f) || (c >= 0x2030f && c <= 0x2040) || \
(c >= 0x2c00 && c <= 0x2fef) || (c >= 0x3001 && c <= 0xd7ff) || \
(c >= 0xf900 && c <= 0xfdcf) || (c >= 0xfdf0 && c <= 0xfffd) || \
(c >= 0x10000 && c <= 0xeffff))
/**
* @defgroup xmlparser XML Parser
* @{
*/
/*
* Structures
*/
/**
* @brief enumeration of attribute types
*/
typedef enum lyxml_attr_type {
LYXML_ATTR_STD = 1, /**< standard XML attribute */
LYXML_ATTR_NS = 2 /**< XML namespace definition */
} LYXML_ATTR_TYPE;
/**
* @brief Namespace definition.
*
* The structure is actually casted lyxml_attr structure which covers all
* attributes defined in an element. The namespace definition is in this case
* also covered by lyxml_attr structure.
*/
struct lyxml_ns {
LYXML_ATTR_TYPE type; /**< type of the attribute = LYXML_ATTR_NS */
struct lyxml_ns *next; /**< next sibling attribute */
struct lyxml_elem *parent; /**< parent node of the attribute */
const char *prefix; /**< the namespace prefix if defined, NULL for default namespace */
const char *value; /**< the namespace value */
};
/**
* @brief Element's attribute definition
*
* The structure actually covers both the attributes as well as namespace
* definitions.
*
* Attributes are being connected only into a singly linked list (compare it
* with the elements).
*/
struct lyxml_attr {
LYXML_ATTR_TYPE type; /**< type of the attribute */
struct lyxml_attr *next; /**< next sibling attribute */
const struct lyxml_ns *ns; /**< pointer to the namespace of the attribute if any */
const char *name; /**< name of the attribute (the LocalPart of the qualified name) */
const char *value; /**< data stored in the attribute */
};
/**
* @brief Structure describing an element in an XML tree.
*
* If the name item is NULL, then the content is part of the mixed content.
*
* Children elements are connected in a half ring doubly linked list:
* - first's prev pointer points to the last children
* - last's next pointer is NULL
*/
struct lyxml_elem {
struct lyxml_elem *parent; /**< parent node */
struct lyxml_elem *child; /**< first children element */
struct lyxml_elem *next; /**< next sibling node */
struct lyxml_elem *prev; /**< previous sibling node */
struct lyxml_attr *attr; /**< first attribute declared in the element */
const char *name; /**< name of the element */
const struct lyxml_ns *ns; /**< namespace of the element */
const char *content; /**< text content of the node if any */
char flags; /**< special flags */
#define LYXML_ELEM_MIXED 0x01 /* element contains mixed content */
#ifndef NDEBUG
unsigned int line; /**< input line number */
#endif
};
/*
* Functions
* Parser
*/
/**
* @brief Parse XML from in-memory string
*
* @param[in] data Pointer to a NULL-terminated string containing XML data to
* parse.
* @param[in] options Parser options. Currently ignored, no option defined yet.
* @return pointer to root of the parsed XML document tree.
*/
struct lyxml_elem *lyxml_read(struct ly_ctx *ctx, const char *data, int options);
/**
* @brief Parse XML from file descriptor - TODO: NOT IMPLEMENTED
*
* @param[in] fd File descriptor where read data to parse
* @param[in] options Parser options. Currently ignored, no option defined yet.
* @return pointer to root of the parsed XML document tree.
*/
struct lyxml_elem *lyxml_read_fd(struct ly_ctx *ctx, int fd, int options);
/**
* @brief Parse XML from filesystem - TODO: NOT IMPLEMENTED
*
* @param[in] filename Path to the file where read data to parse
* @param[in] options Parser options. Currently ignored, no option defined yet.
* @return pointer to root of the parsed XML document tree.
*/
struct lyxml_elem *lyxml_read_file(struct ly_ctx *ctx, const char *filename, int options);
/**
* @brief Dump XML tree to a IO stream
*
* @param[in] stream IO stream to print out the tree.
* @param[in] elem Root element of the XML tree to print
* @param[in] options Parser options. Currently ignored, no option defined yet.
* @return number of printed characters.
*
*/
int lyxml_dump(FILE * stream, struct lyxml_elem *elem, int options);
/*
* Functions
* Tree Manipulation
*/
/**
* @brief Connect the attribute into the specified element.
*
* @param[in] parent Element where to connect the attribute.
* @param[in] attr Attribute to connect. Can be both, the common attribute as
* well as a namespace definition.
* @return EXIT_SUCCESS or EXIT_FAILURE
*/
int lyxml_add_attr(struct lyxml_elem *parent, struct lyxml_attr *attr);
/**
* @brief Get value of the attribute in the specified element.
*/
const char *lyxml_get_attr(struct lyxml_elem *elem, const char *name, const char *ns);
/**
* @brief Add a child element into a parent element.
*
* The child is added as a last child.
*
* @param[in] ctx libyang context to use.
* @param[in] parent Element where to add the child.
* @param[in] child Element to be added as a last child of the parent.
* @return EXIT_SUCCESS or EXIT_FAILURE
*/
int lyxml_add_child(struct ly_ctx *ctx, struct lyxml_elem *parent, struct lyxml_elem *child);
struct lyxml_elem *lyxml_dup_elem(struct ly_ctx *ctx, struct lyxml_elem *elem,
struct lyxml_elem *parent, int recursive);
/**
* @brief Free attribute. Includes unlinking from an element if the attribute
* is placed anywhere.
*
* @param[in] ctx libyang context to use
* @param[in] parent Parent element where the attribute is placed
* @param[in] attr Attribute to free.
*/
void lyxml_free_attr(struct ly_ctx *ctx, struct lyxml_elem *parent, struct lyxml_attr *attr);
/**
* @brief Free (and unlink from their element) all attributes (including
* namespace definitions) of the specified element.
*
* @param[in] elem Element to modify.
*/
void lyxml_free_attrs(struct ly_ctx *ctx, struct lyxml_elem *elem);
/**
* @brief Free (and unlink from the XML tree) the specified element with all
* its attributes and namespace definitions.
*
* @param[in] ctx libyang context to use
* @param[in] elem Pointer to the element to free.
*/
void lyxml_free_elem(struct ly_ctx *ctx, struct lyxml_elem *elem);
/**
* @brief Unlink the attribute from its parent element. In contrast to
* lyxml_free_attr(), after return the caller can still manipulate with the
* attr.
*
* @param[in] attr Attribute to unlink from its parent (if any).
*/
void lyxml_unlink_attr(struct lyxml_attr *attr);
/**
* @brief Unlink the element from its parent. In contrast to lyxml_free_elem(),
* after return the caller can still manipulate with the elem.
*
* @param[in] ctx libyang context to use.
* @param[in] elem Element to unlink from its parent (if any).
* @param[in] copy_ns Flag true corrects NS of \p elem and children that are
* defined outside \p elem subtree (copy NS and update pointer).
* Flag false sets NS of \p elem and children that are defined
* outside \p elem subtree to NULL.
*/
void lyxml_unlink_elem(struct ly_ctx *ctx, struct lyxml_elem *elem, int copy_ns);
/**
* @brief Get namespace definition of the given prefix in context of the specified element.
*
* @param[in] elem Element where start namespace searching
* @param[in] prefix Prefix of the namespace to search for
* @return Namespace defintion or NULL if no such namespace exists
*/
struct lyxml_ns *lyxml_get_ns(struct lyxml_elem *elem, const char *prefix);
/**@}*/
#endif /* LY_XML_H_ */