libyang
3.4.2
libyang is YANG data modelling language parser and toolkit written (and providing API) in C.
|
There are many functions to create or modify an existing data tree. You can add new nodes, reconnect nodes from one tree to another (or e.g. from one list instance to another) or remove nodes. The functions doesn't allow you to put a node to a wrong place (by checking the YANG module structure), but not all validation checks can be made directly (or you have to make a valid change by multiple tree modifications) when the tree is being changed. Therefore, the validation process is expected to be invoked after changing the data tree to make sure that the changed data tree is valid.
When inserting a node into data tree (no matter if the node already exists, via lyd_insert_child() and lyd_insert_sibling(), or a new node is being created), the node is automatically inserted to the place respecting the nodes order from the YANG schema. A leaf-list instances are sorted based on the value and the lyplg_type_sort_clb function defined in the given datatype. A list instances are ordered similarly based on keys. In case the node is opaq (it is not connected with any schema node), it is placed to the end of the sibling node in the order they are inserted in. The only situation when it is possible to influence the order of the nodes is the order of user-ordered list/leaf-list instances. In such a case the lyd_insert_after(), lyd_insert_before() can be used and lyd_insert_child(), lyd_insert_sibling() adds the node after the existing instance of the closest preceding sibling node from the schema.
Creating data is generally possible in two ways, they can be combined. You can add nodes one-by-one based on the node name and/or its parent (lyd_new_inner(), lyd_new_term(), lyd_new_any(), lyd_new_list(), lyd_new_list2() and lyd_new_opaq()) or address the nodes using a simple XPath addressing (lyd_new_path() and lyd_new_path2()). The latter enables to create a whole path of nodes, requires less information about the modified data, and is generally simpler to use. Actually the third way is duplicating the existing data using lyd_dup_single(), lyd_dup_siblings() and lyd_dup_meta_single().
Note, that in case the node is defined in an extension instance, the functions mentioned above do not work until you provide parent where the new node is supposed to be inserted. The reason is that all the functions searches for the top-level nodes directly inside modules. To create a top-level node defined in an extension instance, use lyd_new_ext_inner(), lyd_new_ext_term(), lyd_new_ext_any(), lyd_new_ext_list() and lyd_new_ext_path() functions.
The metadata (and attributes in opaq nodes) can be created with lyd_new_meta() and lyd_new_attr().
Changing value of a terminal node (leaf, leaf-list) is possible with lyd_change_term(). Similarly, the metadata value can be changed with lyd_change_meta(). Before changing the value, it might be useful to compare the node's value with a string value (lyd_value_compare()) or verify that the new string value is correct for the specific data node (lyd_value_validate()).
Working with two existing subtrees can also be performed two ways. Usually, you would use lyd_insert*() functions. They are generally meant for simple inserts of a node into a data tree. For more complicated inserts and when merging 2 trees use lyd_merge_tree() or lyd_merge_siblings(). It offers additional options and is basically a more powerful insert.
Besides merging, libyang is also capable to provide information about differences between two data trees. For this purpose, lyd_diff_tree() and lyd_diff_siblings() generates annotated data trees which can be, in addition, used to change one data tree to another one using lyd_diff_apply_all(), lyd_diff_apply_module() and lyd_diff_reverse_all(). Multiple diff data trees can be also put together for further work using lyd_diff_merge_all(), lyd_diff_merge_module() and lyd_diff_merge_tree() functions. To just check equivalence of the data nodes, lyd_compare_single(), lyd_compare_siblings() and lyd_compare_meta() can be used.
To remove a node or subtree from a data tree, use lyd_unlink_tree() and then free the unwanted data using lyd_free_all() (or other lyd_free_*() functions).
Also remember, that when you are creating/inserting a node, all the objects in that operation must belong to the same context.
Modifying the single data tree in multiple threads is not safe.