CliXoN
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
Macros | Functions
clixon_xml.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <fnmatch.h>
#include <stdint.h>
#include <assert.h>
#include <cligen/cligen.h>
#include "clixon_err.h"
#include "clixon_log.h"
#include "clixon_queue.h"
#include "clixon_chunk.h"
#include "clixon_xml.h"
#include "clixon_xml_parse.h"

Macros

#define BUFLEN   1024 /* Size of xml read buffer */
 
#define XML_INDENT   3 /* maybe we should set this programmatically? */
 

Functions

char * xml_name (cxobj *xn)
 
int xml_name_set (cxobj *xn, char *name)
 
char * xml_namespace (cxobj *xn)
 
int xml_namespace_set (cxobj *xn, char *namespace)
 
cxobj * xml_parent (cxobj *xn)
 
int xml_parent_set (cxobj *xn, cxobj *parent)
 
uint16_t xml_flag (cxobj *xn, uint16_t flag)
 
int xml_flag_set (cxobj *xn, uint16_t flag)
 
int xml_flag_reset (cxobj *xn, uint16_t flag)
 
char * xml_value (cxobj *xn)
 
int xml_value_set (cxobj *xn, char *val)
 
char * xml_value_append (cxobj *xn, char *val)
 
enum cxobj_type xml_type (cxobj *xn)
 
enum cxobj_type xml_type_set (cxobj *xn, enum cxobj_type type)
 
int xml_index (cxobj *xn)
 
int xml_index_set (cxobj *xn, int index)
 
cg_var * xml_cv_get (cxobj *xn)
 
int xml_cv_set (cxobj *xn, cg_var *cv)
 
int xml_child_nr (cxobj *xn)
 
cxobj * xml_child_i (cxobj *xn, int i)
 
cxobj * xml_child_i_set (cxobj *xt, int i, cxobj *xc)
 
cxobj * xml_child_each (cxobj *xparent, cxobj *xprev, enum cxobj_type type)
 
static int xml_child_append (cxobj *x, cxobj *xc)
 
int xml_childvec_set (cxobj *x, int len)
 
cxobj ** xml_childvec_get (cxobj *x)
 
cxobj * xml_new (char *name, cxobj *xp)
 
cxobj * xml_new_spec (char *name, cxobj *xp, void *spec)
 
void * xml_spec (cxobj *x)
 
cxobj * xml_find (cxobj *x_up, char *name)
 
int xml_addsub (cxobj *xp, cxobj *xc)
 
cxobj * xml_insert (cxobj *xp, char *tag)
 
int xml_purge (cxobj *xc)
 
int xml_child_rm (cxobj *xp, int i)
 
int xml_rm (cxobj *xc)
 
int xml_rootchild (cxobj *xp, int i, cxobj **xcp)
 
char * xml_body (cxobj *xn)
 
char * xml_find_value (cxobj *x_up, char *name)
 
char * xml_find_body (cxobj *xn, char *name)
 
int xml_free (cxobj *x)
 
int clicon_xml2file (FILE *f, cxobj *xn, int level, int prettyprint)
 
int xml_print (FILE *f, cxobj *xn)
 
int clicon_xml2cbuf (cbuf *cb, cxobj *cx, int level, int prettyprint)
 
static int xml_parse (char *str, cxobj *x_up)
 
static int FSM (char *tag, char ch, int state)
 
int clicon_xml_parse_file (int fd, cxobj **cx, char *endtag)
 
int clicon_xml_parse_str (char *str, cxobj **cxtop)
 
int clicon_xml_parse (cxobj **cxtop, char *format,...)
 
static int copy_one (cxobj *xn0, cxobj *xn1)
 
int xml_copy (cxobj *x0, cxobj *x1)
 
cxobj * xml_dup (cxobj *x0)
 
int cxvec_dup (cxobj **vec0, size_t len0, cxobj ***vec1, size_t *len1)
 
int cxvec_append (cxobj *x, cxobj ***vec, size_t *len)
 
int xml_apply (cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg)
 
int xml_apply0 (cxobj *xn, enum cxobj_type type, xml_applyfn_t fn, void *arg)
 
int xml_apply_ancestor (cxobj *xn, xml_applyfn_t fn, void *arg)
 
int xml_body_parse (cxobj *xb, enum cv_type type, cg_var **cvp)
 
int xml_body_int32 (cxobj *xb, int32_t *val)
 
int xml_body_uint32 (cxobj *xb, uint32_t *val)
 
int xml_operation (char *opstr, enum operation_type *op)
 
char * xml_operation2str (enum operation_type op)
 

Macro Definition Documentation

#define BUFLEN   1024 /* Size of xml read buffer */
#define XML_INDENT   3 /* maybe we should set this programmatically? */

Function Documentation

int clicon_xml2cbuf ( cbuf *  cb,
cxobj *  cx,
int  level,
int  prettyprint 
)

Print an XML tree structure to a cligen buffer

Parameters
[in,out]cbCligen buffer to write to
[in]xnclicon xml tree
[in]levelhow many spaces to insert before each line
[in]prettyprintinsert
and spaces tomake the xml more readable.
cbuf *cb;
cb = cbuf_new();
if (clicon_xml2cbuf(cb, xn, 0, 1) < 0)
goto err;
cbuf_free(cb);

See also clicon_xml2file

int clicon_xml2file ( FILE *  f,
cxobj *  xn,
int  level,
int  prettyprint 
)

Print an XML tree structure to an output stream

Uses clicon_xml2cbuf internally

Parameters
[in]fUNIX output stream
[in]xnclicon xml tree
[in]levelhow many spaces to insert before each line
[in]prettyprintinsert
and spaces tomake the xml more readable.
See Also
clicon_xml2cbuf
int clicon_xml_parse ( cxobj **  cxtop,
char *  format,
  ... 
)

Read XML definition from variable argument string and parse it into parse-tree.

Utility function using stdarg instead of static string.

Parameters
[out]xml_topTop of XML parse tree. Will add extra top element called 'top'. you must free it after use, using xml_free()
[in]formatPointer to string containing XML definition.
Return values
0OK
-1Error with clicon_err called
cxobj *cx = NULL;
if (clicon_xml_parse(&cx, "<xml>%d</xml>", 22) < 0)
err;
See Also
clicon_xml_parse_str
Note
you need to free the xml parse tree after use, using xml_free()
int clicon_xml_parse_file ( int  fd,
cxobj **  cx,
char *  endtag 
)

Read an XML definition from file and parse it into a parse-tree.

Parameters
[in]fdA file descriptor containing the XML file (as ASCII characters)
[out]xtPointer to an (on entry empty) pointer to an XML parse tree created by this function.
endtagRead until you encounter "endtag" in the stream
Return values
0OK
-1Error with clicon_err called
cxobj *xt;
clicon_xml_parse_file(0, &xt, "</clicon>");
  • See Also
    clicon_xml_parse_str Note, you need to free the xml parse tree after use, using xml_free() Note, xt will add a top-level symbol called "top" meaning that <tree../> will look as: <top><tree.../></tree> XXX: There is a potential leak here on some return values. May block
int clicon_xml_parse_str ( char *  str,
cxobj **  cxtop 
)

Read an XML definition from string and parse it into a parse-tree.

Parameters
[in]strPointer to string containing XML definition.
[out]xml_topTop of XML parse tree. Will add extra top element called 'top'. you must free it after use, using xml_free()
Return values
0OK
-1Error with clicon_err called
cxobj *cx = NULL;
if (clicon_xml_parse_str(str, &cx) < 0)
err;
See Also
clicon_xml_parse_file
Note
you need to free the xml parse tree after use, using xml_free()
static int copy_one ( cxobj *  xn0,
cxobj *  xn1 
)
static

Copy single xml node without copying children

int cxvec_append ( cxobj *  x,
cxobj ***  vec,
size_t *  len 
)

Append a new xml tree to an existing xml vector

Parameters
[in]xXML tree (append this to vector)
[in,out]vecXML tree vector
[in,out]lenLength of XML tree vector
int cxvec_dup ( cxobj **  vec0,
size_t  len0,
cxobj ***  vec1,
size_t *  len1 
)

Copy XML vector from vec0 to vec1

Parameters
[in]vec0Source XML tree vector
[in]len0Length of source XML tree vector
[out]vec1Destination XML tree vector
[out]len1Length of destination XML tree vector
static int FSM ( char *  tag,
char  ch,
int  state 
)
inlinestatic
int xml_addsub ( cxobj *  xp,
cxobj *  xc 
)

Append xc as child to xp. Remove xc from previous parent.

Parameters
[in]xpParent xml node
[in]xcChild xml node to insert under xp
Return values
0OK
-1Error
See Also
xml_insert
int xml_apply ( cxobj *  xn,
enum cxobj_type  type,
xml_applyfn_t  fn,
void *  arg 
)

Apply a function call recursively on all xml node children recursively Recursively traverse all xml nodes in a parse-tree and apply fn(arg) for each object found. The function is called with the xml node and an argument as args. The tree is traversed depth-first, which at least guarantees that a parent is traversed before a child.

Parameters
[in]xnXML node
[in]typematching type or -1 for any
[in]fnCallback
[in]argArgument
int x_fn(cxobj *x, void *arg)
{
return 0;
}
xml_apply(xn, CX_ELMNT, x_fn, NULL);
Note
do not delete or move around any children during this function
It does not apply fn to the root node,..
See Also
xml_apply0 including top object
int xml_apply0 ( cxobj *  xn,
enum cxobj_type  type,
xml_applyfn_t  fn,
void *  arg 
)

Apply a function call on top object and all xml node children recursively

See Also
xml_apply not including top object
int xml_apply_ancestor ( cxobj *  xn,
xml_applyfn_t  fn,
void *  arg 
)

Apply a function call recursively on all ancestors Recursively traverse upwards to all ancestor nodes in a parse-tree and apply fn(arg) for each object found. The function is called with the xml node and an argument as args.

Parameters
[in]xnXML node
[in]fnCallback
[in]argArgument
int x_fn(cxobj *x, void *arg)
{
return 0;
}
See Also
xml_apply
Note
do not delete or move around any children during this function
It does not apply fn to the root node,..
char* xml_body ( cxobj *  xn)

Get the first sub-node which is an XML body.

Parameters
[in]xnxml tree node
Return values
Thereturned body as a pointer to the name string
NULLif no such node or no body in found node Note, make a copy of the return value to use it properly
See Also
xml_find_body
int xml_body_int32 ( cxobj *  xb,
int32_t *  val 
)

Parse an xml body as int32 The real parsing functions are in the cligen code

Parameters
[in]xbxml tree body node, ie containing a value to be parsed
[out]valValue after parsing
Return values
0OK, parsed value in 'val'
-1Error, one of: body not found, parse error, alloc error.
Note
extend to all other cligen var types and generalize
use yang type info?
int xml_body_parse ( cxobj *  xb,
enum cv_type  type,
cg_var **  cvp 
)

Generic parse function for xml values

Parameters
[in]xbxml tree body node, ie containing a value to be parsed
[in]typeType of value to be parsed in value
[out]cvpCLIgen variable containing the parsed value
Note
free cv with cv_free after use.
See Also
xml_body_int32 etc, for type-specific parse functions
int xml_body_uint32 ( cxobj *  xb,
uint32_t *  val 
)

Parse an xml body as uint32 The real parsing functions are in the cligen code

Parameters
[in]xbxml tree body node, ie containing a value to be parsed
[out]valValue after parsing
Return values
0OK, parsed value in 'val'
-1Error, one of: body not found, parse error, alloc error.
Note
extend to all other cligen var types and generalize
use yang type info?
static int xml_child_append ( cxobj *  x,
cxobj *  xc 
)
static

Extend child vector with one and insert xml node there Note: does not do anything with child, you may need to set its parent, etc

cxobj* xml_child_each ( cxobj *  xparent,
cxobj *  xprev,
enum cxobj_type  type 
)

Iterator over xml children objects

NOTE: Never manipulate the child-list during operation or using the same object recursively, the function uses an internal field to remember the index used. It works as long as the same object is not iterated concurrently.

Parameters
[in]xparentxml tree node whose children should be iterated
[in]xprevprevious child, or NULL on init
[in]typematching type or -1 for any
cxobj *x = NULL;
while ((x = xml_child_each(x_top, x, -1)) != NULL) {
...
}
cxobj* xml_child_i ( cxobj *  xn,
int  i 
)

Get a specific child

Parameters
[in]xnxml node
[in]ithe number of the child, eg order in children vector
Return values
childin XML tree, or NULL if no such child, or empty child
cxobj* xml_child_i_set ( cxobj *  xt,
int  i,
cxobj *  xc 
)

Set specific child

Parameters
[in]xnxml node
[in]ithe number of the child, eg order in children vector
[in]xcThe child to set at position i
Return values
0OK
int xml_child_nr ( cxobj *  xn)

Get number of children

Parameters
[in]xnxml node
Return values
numberof children in XML tree
int xml_child_rm ( cxobj *  xp,
int  i 
)

Remove child xml node from parent xml node. No free and child is root

Parameters
[in]xpxml parent node
[in]iNumber of xml child node (to remove)
Return values
0OK
-1
Note
you should not remove xchild in loop (unless yoy keep track of xprev)
See Also
xml_rootchild
xml_rm Remove the node itself from parent
cxobj** xml_childvec_get ( cxobj *  x)
int xml_childvec_set ( cxobj *  x,
int  len 
)

Set a a childvec to a speciufic size, fill with children after

xml_child_i(x, 0) = xc0;
xml_child_i(x, 1) = xc1;
int xml_copy ( cxobj *  x0,
cxobj *  x1 
)

Copy xml tree x0 to other existing tree x1

x1 should be a created placeholder. If x1 is non-empty, the copied tree is appended to the existing tree.

x1 = xml_new("new", xc);
xml_copy(x0, x1);
cg_var* xml_cv_get ( cxobj *  xn)

Get cligen variable associated with node

Parameters
[in]xnxml node
Return values
cvCligen variable if set
NULLIf not set, or not applicable
int xml_cv_set ( cxobj *  xn,
cg_var *  cv 
)

Set cligen variable associated with node

Parameters
[in]xnxml node
[in]cvCligen variable or NULL
Return values
0if OK
cxobj* xml_dup ( cxobj *  x0)

Create and return a copy of xml tree.

cxobj *x1;
x1 = xml_dup(x0);

Note, returned tree should be freed as: xml_free(x1)

cxobj* xml_find ( cxobj *  x_up,
char *  name 
)

Find an XML node matching name among a parent's children.

Get first XML node directly under x_up in the xml hierarchy with name "name".

Parameters
[in]x_upBase XML object
[in]nameshell wildcard pattern to match with node name
Return values
xmlobjif found.
NULLif no such node found.
char* xml_find_body ( cxobj *  xn,
char *  name 
)

Find and return a body (string) of a sub xml node

Parameters
[in]xnxml tree node
[in]namename of xml tree node
Return values
Thereturned body as a pointer to the name string
NULLif no such node or no body in found node
Note
, make a copy of the return value to use it properly
See Also
xml_find_value
char* xml_find_value ( cxobj *  x_up,
char *  name 
)

Find and return the value of a sub xml node

The value can be of an attribute or body.

Parameters
[in]xnxml tree node
[in]namename of xml tree nod (eg attr name or "body")
Return values
Thereturned value as a pointer to the name string
NULLif no such node or no value in found node

Note, make a copy of the return value to use it properly See also xml_find_body

uint16_t xml_flag ( cxobj *  xn,
uint16_t  flag 
)

Get xml node flags, used for internal algorithms

Parameters
[in]xnxml node
Return values
flagFlags value, see XML_FLAG_*
int xml_flag_reset ( cxobj *  xn,
uint16_t  flag 
)

Reset xml node flags, used for internal algorithms

Parameters
[in]xnxml node
[in]flagFlags value to reset, see XML_FLAG_*
int xml_flag_set ( cxobj *  xn,
uint16_t  flag 
)

Set xml node flags, used for internal algorithms

Parameters
[in]xnxml node
[in]flagFlags value to set, see XML_FLAG_*
int xml_free ( cxobj *  x)

Free an xl sub-tree recursively, but do not remove it from parent

Parameters
[in]xthe xml tree to be freed.
See Also
xml_purge where x is also removed from parent
int xml_index ( cxobj *  xn)

Get index/key of xnode

Parameters
[in]xnxml node
Return values
indexof xml node index/key is used in case of yang list constructs where one element is key
int xml_index_set ( cxobj *  xn,
int  index 
)

Set index of xnode

Parameters
[in]xnxml node
[in]indexnew index
Return values
indexold index index/key is used in case of yang list constructs where one element is key
cxobj* xml_insert ( cxobj *  xp,
char *  tag 
)

Insert a new element (xc) under an xml node (xp), move all children to xc. Before: xp –> xt After: xp –> xc –> xt

Parameters
[in]xpParent xml node
[in]tagName of new xml child
Return values
xcReturn the new child (xc)
See Also
xml_addsub The name of the function is somewhat misleading
char* xml_name ( cxobj *  xn)

Get name of xnode

Parameters
[in]xnxml node
Return values
nameof xml node
int xml_name_set ( cxobj *  xn,
char *  name 
)

Set name of xnode, name is copied

Parameters
[in]xnxml node
[in]namenew name, null-terminated string, copied by function
Return values
-1on error with clicon-err set
0OK
char* xml_namespace ( cxobj *  xn)

Get namespace of xnode

Parameters
[in]xnxml node
Return values
namespaceof xml node
int xml_namespace_set ( cxobj *  xn,
char *  namespace 
)

Set name of xnode, name is copied

Parameters
[in]xnxml node
[in]namespacenew namespace, null-terminated string, copied by function
Return values
-1on error with clicon-err set
0OK
cxobj* xml_new ( char *  name,
cxobj *  xp 
)

Create new xml node given a name and parent. Free it with xml_free().

Parameters
[in]nameName of new
[in]xpThe parent where the new xml node should be inserted
Return values
createdxml object if successful
NULLif error and clicon_err() called
cxobj* xml_new_spec ( char *  name,
cxobj *  xp,
void *  spec 
)

Create new xml node given a name, parent and spec.

Parameters
[in]nameName of new xml node
[in]xpXML parent
[in]specYang spec
Return values
NULLError
xXML tree. Free with xml_free().
int xml_operation ( char *  opstr,
enum operation_type *  op 
)

Map xml operation from string to enumeration

Parameters
[in]xnXML node
[out]op"operation" attribute may change operation
char* xml_operation2str ( enum operation_type  op)
cxobj* xml_parent ( cxobj *  xn)

Get parent of xnode

Parameters
[in]xnxml node
Return values
parentxml node
int xml_parent_set ( cxobj *  xn,
cxobj *  parent 
)

Set parent of xnode, parent is copied.

Parameters
[in]xnxml node
[in]parentpointer to new parent xml node
Return values
0OK
static int xml_parse ( char *  str,
cxobj *  x_up 
)
static

Internal xml parsing function.

See Also
clicon_xml_parse_file clicon_xml_parse_string
int xml_print ( FILE *  f,
cxobj *  xn 
)

Print an XML tree structure to an output stream

Uses clicon_xml2file internally

Parameters
[in]fUNIX output stream
[in]xnclicon xml tree
See Also
clicon_xml2cbuf
clicon_xml2file
int xml_purge ( cxobj *  xc)

Remove and free an xml node child from xml parent

Parameters
[in]xcxml child node (to be removed and freed)
Return values
0OK
-1
Note
you cannot remove xchild in the loop (unless yoy keep track of xprev)
See Also
xml_free Free, dont remove from parent
xml_child_rm Only remove dont free Differs from xml_free it is removed from parent.
int xml_rm ( cxobj *  xc)

Remove this xml node from parent xml node. No freeing and node is new root

Parameters
[in]xcxml child node to be removed
Return values
0OK
-1
Note
you should not remove xchild in loop (unless yoy keep track of xprev)
See Also
xml_child_rm Remove a child of a node
int xml_rootchild ( cxobj *  xp,
int  i,
cxobj **  xcp 
)

Return a child sub-tree, while removing parent and all other children Given a root xml node, and the i:th child, remove the child from its parent and return it, remove the parent and all other children. Before: xp–>[..xc..] After: xc

Parameters
[in]xpxml parent node. Will be deleted
[in]iChild nr in parent child vector
[out]xcpxml child node. New root
Return values
0OK
-1Error
See Also
xml_child_rm
void* xml_spec ( cxobj *  x)
enum cxobj_type xml_type ( cxobj *  xn)

Get type of xnode

Parameters
[in]xnxml node
Return values
typeof xml node
enum cxobj_type xml_type_set ( cxobj *  xn,
enum cxobj_type  type 
)

Set type of xnode

Parameters
[in]xnxml node
[in]typenew type
Return values
typeold type
char* xml_value ( cxobj *  xn)

Get value of xnode

Parameters
[in]xnxml node
Return values
valueof xml node
char* xml_value_append ( cxobj *  xn,
char *  val 
)

Append value of xnode, value is copied

Parameters
[in]xnxml node
[in]valappended value, null-terminated string, copied by function
Return values
NULLon error with clicon-err set, or if value is set to NULL
newvalue
int xml_value_set ( cxobj *  xn,
char *  val 
)

Set value of xml node, value is copied

Parameters
[in]xnxml node
[in]valnew value, null-terminated string, copied by function
Return values
-1on error with clicon-err set
0OK