commit xpath
This commit is contained in:
parent
554c1cb9de
commit
9bd941ab76
14 changed files with 306 additions and 130 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue