clicon / clixon

YANG-based toolchain including NETCONF and RESTCONF interfaces and an interactive CLI
http://www.clicon.org/
Other
206 stars 69 forks source link

Method to dereference a leafref node to its target needed #490

Closed pprindeville closed 3 months ago

pprindeville commented 5 months ago

If I have a leafref type node, I could embed the logic in C to xpath_first() format it with a hardcoded path, etc. but all of that should be captured into the state of the parsed YANG, and changing the YANG would require changing the C... having a method that indirects the current cxobj to its target would be very handy and save much effort.

olofhagsand commented 5 months ago

Here is such a function. Unfortunately, it was not possible to use it in other lib functions (such as expand or validation code) due to a more complex context, especially typing, and also more specific error handling. As such it is a utility function, you should be able to use it, but for now I will not add it in the lib.

 /*! Given an xml leafref node, return the original node it references
 *
 * @param[in]  xt    XML node (LEAF or LEAF-lIST) of type leafref
 * @param[out] xref  Node that xt references, if any
 * @tretval    0     OK, with xref set or not
 * @tretval   -1     Error
 */
int
xml_get_leafref(cxobj     *xt,
                yang_stmt *yt,
                yang_stmt *ytype,
                cxobj    **xref)
{
    int        retval = -1;
    char      *xt_body;
    char      *xref_body;
    yang_stmt *ypath;
    char      *path_arg;
    cxobj    **xvec = NULL;
    size_t     xlen = 0;
    cxobj     *x;
    int        i;
    cvec      *nsc = NULL;
    yang_stmt *yt;
    yang_stmt *ytype = NULL;

    if ((yt = xml_spec(xt)) == NULL)
        goto ok;
    if (yang_keyword_get(yt) != Y_LEAF && yang_keyword_get(yt) != Y_LEAF_LIST)
        goto ok;
    if (yang_type_get(yt, NULL, &ytype, NULL, NULL, NULL, NULL, NULL) < 0)
        goto done;
    if (ytype == NULL || strcmp(yang_argument_get(ytype), "leafref") != 0)
        goto ok;
    if (xt == NULL || yt == NULL || ytype == NULL || xref == NULL){
        clixon_err(OE_XML, EINVAL, "input parameter is NULL");
        goto done;
    }
    if ((ypath = yang_find(ytype, Y_PATH, NULL)) == NULL)
        goto ok;
    if ((path_arg = yang_argument_get(ypath)) == NULL)
        goto ok;
    if (xml_nsctx_yang(yt, &nsc) < 0)
        goto done;
    if ((xt_body = xml_body(xt)) == NULL)
        goto ok;
    if (xpath_vec(xt, nsc, "%s", &xvec, &xlen, path_arg) < 0)
        goto done;
    for (i = 0; i < xlen; i++) {
        x = xvec[i];
        if ((xref_body = xml_body(x)) == NULL)
            continue;
        if (strcmp(xt_body, xref_body) == 0){
            *xref = x;
            break;
        }
    }
 ok:
    retval = 0;
 done:
    if (xvec)
        free(xvec);
    return retval;
}