commit xpath

This commit is contained in:
Olof hagsand 2016-02-24 21:16:15 +01:00
parent 554c1cb9de
commit 9bd941ab76
14 changed files with 306 additions and 130 deletions

View file

@ -36,6 +36,7 @@
/* clicon */
#include "clicon_err.h"
#include "clicon_log.h"
#include "clicon_queue.h"
#include "clicon_chunk.h"
#include "clicon_xml.h"
@ -998,7 +999,7 @@ cxvec_append(cxobj *x,
return retval;
}
/*! Apply a function call recursively on all xml node recursively
/*! 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.
@ -1037,3 +1038,40 @@ xml_apply(cxobj *xn,
done:
return retval;
}
/*! 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.
* @param[in] xn XML node
* @param[in] fn Callback
* @param[in] arg Argument
* @code
* int x_fn(cxobj *x, void *arg)
* {
* return 0;
* }
* xml_apply_ancestor(xn, x_fn, NULL);
* @endcode
* @see xml_apply
* @note do not delete or move around any children during this function
* @note It does not apply fn to the root node,..
*/
int
xml_apply_ancestor(cxobj *xn,
xml_applyfn_t fn,
void *arg)
{
int retval = -1;
cxobj *xp = NULL;
while ((xp = xml_parent(xn)) != NULL) {
if (fn(xp, arg) < 0)
goto done;
if (xml_apply_ancestor(xp, fn, arg) < 0)
goto done;
}
retval = 0;
done:
return retval;
}

View file

@ -667,7 +667,7 @@ xmldb_get(char *dbname,
struct db_pair *pairs;
cxobj *xt = NULL;
cxobj **xvec=NULL;
int len;
size_t len;
/* Read in complete database (this can be optimized) */
if ((npairs = db_regexp(dbname, "", __FUNCTION__, &pairs, 0)) < 0)
@ -735,10 +735,10 @@ xmldb_get(char *dbname,
* @code
* cxobj *xt;
* cxobj **xvec;
* int xlen;
* size_t xlen;
* yang_spec *yspec = clicon_dbspec_yang(h);
* if (xmldb_get_xpath(dbname, "/interfaces/interface[name="eth*"]", yspec,
* &xt, &xvec, &xlen) < 0)
* if (xmldb_get_vec(dbname, "/interfaces/interface[name="eth*"]", yspec,
* &xt, &xvec, &xlen) < 0)
* err;
* for (i=0; i<xlen; i++){
* xn = xv[i];
@ -751,12 +751,12 @@ xmldb_get(char *dbname,
* @see xmldb_get
*/
int
xmldb_get_xpath(char *dbname,
char *xpath,
yang_spec *yspec,
cxobj **xtop,
cxobj ***xvec,
int *xlen)
xmldb_get_vec(char *dbname,
char *xpath,
yang_spec *yspec,
cxobj **xtop,
cxobj ***xvec,
size_t *xlen)
{
int retval = -1;
int i;

View file

@ -74,6 +74,7 @@ to the xml standards:
/* clicon */
#include "clicon_err.h"
#include "clicon_log.h"
#include "clicon_xml.h"
#include "clicon_xsl.h"
@ -304,6 +305,7 @@ static int
recursive_find(cxobj *xn,
char *pattern,
int node_type,
uint16_t flags,
cxobj ***vec0,
size_t *vec0len)
{
@ -315,11 +317,13 @@ recursive_find(cxobj *xn,
xsub = NULL;
while ((xsub = xml_child_each(xn, xsub, node_type)) != NULL) {
if (fnmatch(pattern, xml_name(xsub), 0) == 0){
if (cxvec_append(xsub, &vec, &veclen) < 0)
goto done;
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xsub, flags));
if (flags==0x0 || xml_flag(xsub, flags))
if (cxvec_append(xsub, &vec, &veclen) < 0)
goto done;
// continue; /* Dont go deeper */
}
if (recursive_find(xsub, pattern, node_type, &vec, &veclen) < 0)
if (recursive_find(xsub, pattern, node_type, flags, &vec, &veclen) < 0)
goto done;
}
retval = 0;
@ -331,8 +335,9 @@ recursive_find(cxobj *xn,
static int
xpath_expr(char *e,
cxobj ***vec0,
size_t *vec0len)
uint16_t flags,
cxobj ***vec0,
size_t *vec0len)
{
char *e_a;
char *e_v;
@ -359,9 +364,12 @@ xpath_expr(char *e,
xv = (*vec0)[i];
if ((x = xml_find(xv, e_a)) != NULL &&
(xml_type(x) == CX_ATTR)){
if (!e_v || strcmp(xml_value(x), e_v) == 0)
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
if (!e_v || strcmp(xml_value(x), e_v) == 0){
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xv, flags));
if (flags==0x0 || xml_flag(xv, flags))
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
}
}
}
}
@ -371,8 +379,10 @@ xpath_expr(char *e,
if (sscanf(e, "%d", &i) == 1){ /* number */
if (i < *vec0len){
xv = (*vec0)[i]; /* XXX: cant compress: gcc breaks */
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xv, flags));
if (flags==0x0 || xml_flag(xv, flags))
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
}
}
else{
@ -393,8 +403,10 @@ xpath_expr(char *e,
(xml_type(x) == CX_ELMNT)){
if ((val = xml_body(x)) != NULL &&
strcmp(val, e) == 0){
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xv, flags));
if (flags==0x0 || xml_flag(xv, flags))
if (cxvec_append(xv, &vec, &veclen) < 0)
goto done;
}
}
}
@ -428,6 +440,7 @@ xpath_find(struct xpath_element *xe,
int descendants0,
cxobj **vec0,
size_t vec0len,
uint16_t flags,
cxobj ***vec2,
size_t *vec2len
)
@ -442,10 +455,12 @@ xpath_find(struct xpath_element *xe,
size_t vec1len = 0;
if (xe == NULL){
// append
/* append */
for (i=0; i<vec0len; i++){
xv = vec0[i];
cxvec_append(xv, vec2, vec2len);
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(xv, flags));
if (flags==0x0 || xml_flag(xv, flags))
cxvec_append(xv, vec2, vec2len);
}
free(vec0);
return 0;
@ -480,7 +495,7 @@ xpath_find(struct xpath_element *xe,
if (descendants0){
for (i=0; i<vec0len; i++){
xv = vec0[i];
if (recursive_find(xv, xe->xe_str, CX_ELMNT, &vec1, &vec1len) < 0)
if (recursive_find(xv, xe->xe_str, CX_ELMNT, flags, &vec1, &vec1len) < 0)
goto done;
}
}
@ -490,8 +505,10 @@ xpath_find(struct xpath_element *xe,
x = NULL;
while ((x = xml_child_each(xv, x, -1)) != NULL) {
if (fnmatch(xe->xe_str, xml_name(x), 0) == 0){
if (cxvec_append(x, &vec1, &vec1len) < 0)
goto done;
clicon_debug(2, "%s %x %x", __FUNCTION__, flags, xml_flag(x, flags));
if (flags==0x0 || xml_flag(x, flags))
if (cxvec_append(x, &vec1, &vec1len) < 0)
goto done;
}
}
}
@ -517,10 +534,10 @@ xpath_find(struct xpath_element *xe,
}
}
if (xe->xe_predicate)
if (xpath_expr(xe->xe_predicate, &vec0, &vec0len) < 0)
if (xpath_expr(xe->xe_predicate, flags, &vec0, &vec0len) < 0)
goto done;
if (xpath_find(xe->xe_next, descendants,
vec0, vec0len,
vec0, vec0len, flags,
vec2, vec2len) < 0)
goto done;
retval = 0;
@ -574,6 +591,7 @@ static int
xpath_exec(char *xpath,
cxobj **vec0,
size_t vec0len,
uint16_t flags,
cxobj ***vec2,
size_t *vec2len)
{
@ -587,7 +605,7 @@ xpath_exec(char *xpath,
goto done;
if (0)
xpath_print(stderr, xplist);
if (xpath_find(xplist, 0, vec1, vec1len, vec2, vec2len) < 0)
if (xpath_find(xplist, 0, vec1, vec1len, flags, vec2, vec2len) < 0)
goto done;
if (xpath_free(xplist) < 0)
goto done;
@ -607,6 +625,7 @@ xpath_exec(char *xpath,
static int
xpath_choice(cxobj *xtop,
char *xpath0,
uint16_t flags,
cxobj ***vec1,
size_t *vec1len)
{
@ -637,7 +656,7 @@ xpath_choice(cxobj *xtop,
}
xpath = s1;
s1 = s2;
if (xpath_exec(xpath, vec0, vec0len, vec1, vec1len) < 0)
if (xpath_exec(xpath, vec0, vec0len, flags, vec1, vec1len) < 0)
goto done;
}
retval = 0;
@ -667,13 +686,14 @@ xpath_choice(cxobj *xtop,
* @see also xpath_vec.
*/
cxobj *
xpath_first(cxobj *cxtop, char *xpath)
xpath_first(cxobj *cxtop,
char *xpath)
{
cxobj **vec0 = NULL;
size_t vec0len = 0;
cxobj *xn = NULL;
if (xpath_choice(cxtop, xpath, &vec0, &vec0len) < 0)
if (xpath_choice(cxtop, xpath, 0, &vec0, &vec0len) < 0)
goto done;
if (vec0len)
xn = vec0[0];
@ -707,7 +727,9 @@ xpath_first(cxobj *cxtop, char *xpath)
* NOTE: uses a static variable: consider replacing with xpath_vec() instead
*/
cxobj *
xpath_each(cxobj *cxtop, char *xpath, cxobj *xprev)
xpath_each(cxobj *cxtop,
char *xpath,
cxobj *xprev)
{
static cxobj **vec0 = NULL; /* XXX */
static size_t vec0len = 0;
@ -718,7 +740,7 @@ xpath_each(cxobj *cxtop, char *xpath, cxobj *xprev)
if (vec0) // XXX
free(vec0); // XXX
vec0len = 0;
if (xpath_choice(cxtop, xpath, &vec0, &vec0len) < 0)
if (xpath_choice(cxtop, xpath, 0, &vec0, &vec0len) < 0)
goto done;
}
if (vec0len){
@ -765,14 +787,31 @@ xpath_each(cxobj *cxtop, char *xpath, cxobj *xprev)
* @see also xpath_first, xpath_each.
*/
cxobj **
xpath_vec(cxobj *cxtop,
char *xpath,
int *veclen)
xpath_vec(cxobj *cxtop,
char *xpath,
size_t *veclen)
{
cxobj **vec=NULL;
*veclen = 0;
if (xpath_choice(cxtop, xpath, &vec, (size_t*)veclen) < 0)
if (xpath_choice(cxtop, xpath, 0, &vec, (size_t*)veclen) < 0)
return NULL;
return vec;
}
/* A restricted xpath that returns a vector of matches (only nodes marked with flags)
* @param[in] flags Set of flags that return nodes must match (0 if all)
*/
cxobj **
xpath_vec_flag(cxobj *cxtop,
char *xpath,
uint16_t flags,
size_t *veclen)
{
cxobj **vec=NULL;
*veclen = 0;
if (xpath_choice(cxtop, xpath, flags, &vec, (size_t*)veclen) < 0)
return NULL;
return vec;
}