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
}