libyang学习:主要是为了学习如何将yang模型data path 转化为schema path。
背景:最近在做一个yang的gtest配置下发测试工具时,遇到yang模型xpath带choice case时(参见文章后面的yang模型):
data path不带choice case节点,如:/acme-system:system/food/tea
schema path是带的,如:/acme-system:system/food/snack/late-bight/tea
导致业务基于schema path注册回调函数时,基于data path数据注入时找不到回调函数,所以需要做一次转换,以便能够给予path找到回调函数。
思路:从data path获取 lysc_node,再从 lysc_node 获取schema path。
LY_ERR ret = LY_SUCCESS;
struct ly_ctx *ctx = NULL;
const struct lys_module *module;
// 初始化libyang上下文
ret = ly_ctx_new("/home/jungle/code/libyang/tests/modules/yang", 0, &ctx);
if (!ctx) {
fprintf(stderr, "Failed to create context.\n");
return 1;
}
// 加载YANG模块
// 假设YANG模块文件名为 "acme-system.yang"
module = ly_ctx_load_module(ctx, "acme-system", NULL, NULL);
if (!module) {
fprintf(stderr, "Failed to load module.\n");
ly_ctx_destroy(ctx);
return 1;
}
// 打印整个yang模型
char *str = NULL;
lys_print_mem(&str, module, LYS_OUT_TREE, 0);
printf("\r\nyang module:\r\n%s\r\n", str);
free(str);
/* using lysc tree */
ly_ctx_set_options(ctx, LY_CTX_SET_PRIV_PARSED);
// 初始化输出
char *printed;
struct ly_out *out;
ly_out_new_memory(&printed, 0, &out);
// 从data path获取 lysc_node
const struct lysc_node *node_lysc = lys_find_path(ctx, NULL, "/acme-system:system/food/tea", 0);
lys_print_node(out, node_lysc, LYS_OUT_TREE, 0, LYS_PRINT_NO_SUBSTMT);
int len = ly_out_printed(out);
printf("\r\nlys_find_path:\r\n%s\r\n", printed);
// 根据lysc_node 转 schema path
char path[4078] = {0};
lysc_path(node_lysc, LYSC_PATH_LOG, path, 4078);
printf("\r\nschema path=%s\r\n", path);
// 从schema path获取 lysc_node
node_lysc = find_schema_path(ctx, "/acme-system:system/food/snack/late-bight/tea");
if (node_lysc) {
lys_print_node(out, node_lysc, LYS_OUT_TREE, 0, LYS_PRINT_NO_SUBSTMT);
int len = ly_out_printed(out);
printf("\r\nfind_schema_path:\r\n%s\r\n", printed);
}
ly_out_reset(out);
// 创建树
struct lyd_node *data = NULL;
//lyd_new_path(NULL, ctx, "/acme-system:system/host-name", "huawei", 0, &data);
lyd_new_path(NULL, ctx, "/acme-system:system/food/tea", "longjungcha", 0, &data);
LY_ERR _r = lyd_print_mem(&str, data, LYD_JSON, LYS_PRINT_SHRINK);
printf("\r\nLYD_JSON:\r\n%s\r\n", str);
free(str);
// 打印data path
char *path_ = lyd_path(data, LYD_PATH_STD, NULL, 0);
printf("\r\nLYD_PATH_STD:\r\n%s\r\n", path_);
free(path_);
lyd_free_siblings(data);
ly_ctx_destroy(ctx);
运行结果如下:
yang module:
module: acme-system
+--rw system
+--rw host-name? string
+--rw domain-search* string
+--rw login
| +--rw message? string
| +--rw user* [name]
| +--rw name string
+--rw food
+--rw (snack)?
+--:(sport-arena)
| +--rw pretzel? string
+--:(late-bight)
+--rw tea? string
lys_find_path:
module: acme-system
+--rw system
+--rw food
+--rw (snack)?
+--:(late-bight)
+--rw tea? string
schema path=/acme-system:system/food/snack/late-bight/tea
find_schema_path:
module: acme-system
+--rw system
+--rw food
+--rw (snack)?
+--:(late-bight)
+--rw tea? string
module: acme-system
+--rw system
+--rw food
+--rw (snack)?
+--:(late-bight)
+--rw tea? string
LYD_JSON:
{"acme-system:system":{"food":{"tea":"longjungcha"}}}
LYD_PATH_STD:
/acme-system:system
最后附上yang模型:
module acme-system {
namespace "http://acme.example.com/system";
prefix "acme";
organization "ACME Inc.";
contact "joe@acme.example.com";
description
"The module for entities implementing the ACME system.";
revision 2007-06-09 {
description "Initial revision.";
}
container system {
leaf host-name {
type string;
description "Hostname for this system";
}
leaf-list domain-search {
type string;
description "List of domain names to search";
}
container login {
leaf message {
type string;
description
"Message given at start of login session";
}
list user {
key "name";
leaf name {
type string;
}
}
}
container food {
choice snack {
case sport-arena {
leaf pretzel {
type string;
}
}
case late-bight {
leaf tea {
type string;
}
}
}
}
}
}
![]() |
![]() |
2023 |
![]() |
![]() |
1970 |
![]() |
![]() |
1763 |
4 |
![]() |
1718 |
5 |
![]() |
1710 |
6 |
![]() |
1701 |
7 |
![]() |
1684 |
8 |
|
1678 |
9 |
![]() |
1664 |
10 |
![]() |
1653 |