What is a YANG Schema Tree?


The YANG schema tree is the conceptual tree made up of all resolved objects:

  • All groupings have been expanded
  • All augment statements have been applied
  • All deviation statements have been applied
  • All if-feature statements have been resolved


YANG statements not visible in the schema tree:

  • uses


YANG statements visible in the schema tree:

  • leaf
  • leaf-list
  • choice
  • case
  • container
  • list
  • anydata
  • anyxml


Note that choice and case nodes only exist in the YANG schema tree.

These nodes are not visible in a YANG datastore.

Only the other nodes listed can be present in a YANG data tree.



What is an Object Template (obj_template_t)?


The C data structure called obj_template_t is used to represent a YANG schema tree.

The API functions for this data structure are located in ncx/obj.h


The netconfd-pro server creates one YANG schema tree for all its supported YANG modules.

The yangcli-pro client creates on YANG schema tree for each session, matching the server's schema tree.



Finding an Object Template with XPath


This API allows a schema node from within the YANG schema tree to be retrieved.

The input is an XPath absolute path expression.

The output is a pointer to the object templete (if NO_ERR is returned).

The path string can contain prefixes. If so, they must be the YANG prefix defined in the module "prefix" statement.


/********************************************************************
* FUNCTION xpath_find_schema_target_int
*
* internal find target, without any error reporting
* Follow the absolute-path expression
* and return the obj_template_t that it indicates
*
* Internal access version
* Error messages are not printed by this function!!
* Do not duplicate error messages upon error return
*
* INPUTS:
*    target == absolute Xpath expression string to evaluate
*    targobj == address of return object  (may be NULL)
*
* OUTPUTS:
*   if non-NULL inputs:
*      *targobj == target object
*
* RETURNS:
*   status
*********************************************************************/
extern status_t
    xpath_find_schema_target_int (const xmlChar *target,
                                  obj_template_t **targobj);



Example: Get the "name" leaf from the interface list:


    const xmlChar *defpath = (const xmlChar *)"/if:interfaces/if:interface/if:name";
    obj_template_t *obj = NULL;
    status_t res = xpath_find_schema_target_int(defpath, &obj);
    if (res != NO_ERR) {
        return res;
    }


Finding a Top Level Object Template in A Specific Module


/********************************************************************
* FUNCTION ncx_find_object
*
* Find a top level module object
*
* INPUTS:
*   mod == ncx_module to check
*   objname == object name
*
* RETURNS:
*   pointer to struct if present, NULL otherwise
*********************************************************************/
extern obj_template_t *
    ncx_find_object (ncx_module_t *mod,
                     const xmlChar *objname);




Example: Find the interfaces object:


const xmlChar *modname = (const xmlChar *)"ietf-interfaces";
const xmlChar *revision = (const xmlChar *)"2014-05-08";
const xmlChar *objname = (const xmlChar *)"interfaces";

ncx_module_t *mod = ncx_find_module(modname, revision);
if (mod) {
   obj_template_t *obj = ncx_find_object(mod, objname);
   ...
}



Finding a Top Level Object Template in Any Module


/********************************************************************
* FUNCTION ncx_find_any_object
*
* Check if an obj_template_t in in any module that
* matches the object name string
*
* INPUTS:
*   objname == object name to match
*
* RETURNS:
*   pointer to struct if present, NULL otherwise
*********************************************************************/
extern obj_template_t *
    ncx_find_any_object (const xmlChar *objname);



Example: Find the object "system" from any module loaded into the server.


const xmlChar *objname = (const xmlChar *)"system";

obj_template_t *obj = ncx_find_any_object(objname);



Checking the Type of an Object


The YANG object type is defined as an enumeration:


/* enumeration for different YANG data def statement types
 * the enum order is significant!!! do not change!!!
 */
typedef enum obj_type_t_ {
    OBJ_TYP_NONE,
    OBJ_TYP_ANYXML,
    OBJ_TYP_CONTAINER,
    OBJ_TYP_LEAF,
    OBJ_TYP_LEAF_LIST,
    OBJ_TYP_LIST,       /* last real database object */
    OBJ_TYP_CHOICE,
    OBJ_TYP_CASE,       /* last named database object */
    OBJ_TYP_USES,
    OBJ_TYP_REFINE,            /* child of uses only */
    OBJ_TYP_AUGMENT,
    OBJ_TYP_RPC,
    OBJ_TYP_RPCIO,
    OBJ_TYP_NOTIF,
    OBJ_TYP_ANYDATA,    /* YANG 1.1 */
    OBJ_TYP_ACTION    /* YANG 1.1 */
} obj_type_t;


There is a macro to access the object type directly:


obj_type_t objtype = OBJ_TYPE(obj);


There are a set of simple APIs that return TRUE if the object type matches

  • obj_is_leaf
  • obj_is_list
  • obj_is_container
  • obj_is_choice
  • obj_is_case
  • obj_is_uses
  • obj_is_leafy  (leaf or leaf-list)
  • obj_is_augment
  • obj_is_refine
  • obj_is_rpc
  • obj_is_rpcio
  • obj_is_action
  • obj_is_notif
  • obj_is_np_container
  • obj_is_p_container
  • obj_is_anyxml
  • obj_is_anydata


Example: check if an object is a container:


if (obj_is_container(obj)) {
   // do something
}



Traversing the Child Nodes of an Object


To traverse all the schema nodes 1 layer at a time:

  • obj_first_child
  • obj_next_child


Example: Traverse the child nodes


obj_template_t *chobj = obj_first_child(obj);
for (; chobj; chobj = obj_next_child(chobj)) {
    if (obj_has_name(chobj)) {
        obj_number_data_object(chobj);
    }
}



To traverse all the schema nodes 1 layer at a time, except traverse through choice and case nodes.

This API will traverse past a choice statement into its sibling node.


  • obj_first_child_deep
  • obj_next_child_deep


Example: Traverse the child nodes


          
obj_template_t *testobj = obj_first_child_deep(obj);
for (; testobj;  testobj = obj_next_child_deep(testobj)) {
         // do something with testobj
}



To traverse all the child schema nodes of a choice statement,1 layer at a time, except traverse through choice and case nodes.

This API will not traverse past a choice statement into its sibling node if the 2nd parameter is "true":


  • obj_first_child_deep
  • obj_next_child_deep_ex


/********************************************************************
* FUNCTION obj_next_child_deep_ex
*
* Get the next child object if the specified object
* has any children.  Look past choice and case nodes
* to the real nodes within them
*
*  !!!! SKIPS OVER AUGMENT AND USES !!!!
*
* INPUTS:
*    obj == obj_template_t to check
*    stopnext == true if the getnext search should stop after
*       all choice cases have been checked.  Do not go on
*       to the next sibling of the starting case
*         == false tpo keep going until all objects checked
*            that are siblings of the choice being checked deep
* RETURNS:
*    pointer to next child obj_template_t or
*    NULL if not found
*********************************************************************/
extern obj_template_t *
    obj_next_child_deep_ex (obj_template_t *obj,
                            boolean stopnext);




Example: Traverse the child nodes


testobj = obj_first_child_deep(choic_obj);
for (; testobj; testobj = obj_next_child_deep_ex(testobj, true)) {
       // do something with testobj
}