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 }