diff --git a/src/tree_data.c b/src/tree_data.c
index 142b15db3..7f9c90cd5 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -102,7 +102,6 @@ lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct
LY_ERR r = LY_SUCCESS, rc = LY_SUCCESS;
struct lyd_ctx *lydctx = NULL;
struct ly_set parsed = {0};
- struct lyd_node *first;
uint32_t i, int_opts = 0;
ly_bool subtree_sibling = 0;
@@ -148,11 +147,9 @@ lyd_parse(const struct ly_ctx *ctx, const struct lysc_ext_instance *ext, struct
}
}
- if (parent) {
- /* get first top-level sibling */
- for (first = parent; first->parent; first = lyd_parent(first)) {}
- first = lyd_first_sibling(first);
- first_p = &first;
+ if (parent && parsed.count) {
+ /* use the first parsed node */
+ first_p = &parsed.dnodes[0];
}
if (!(parse_opts & LYD_PARSE_ONLY)) {
diff --git a/src/validation.c b/src/validation.c
index 7e678a265..418f5469a 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -1834,7 +1834,7 @@ lyd_validate(struct lyd_node **tree, const struct lys_module *module, const stru
}
/* validate new top-level nodes of this module, autodelete */
- r = lyd_validate_new(first2, NULL, mod, val_opts, diff);
+ r = lyd_validate_new(first2, *first2 ? lysc_data_parent((*first2)->schema) : NULL, mod, val_opts, diff);
LY_VAL_ERR_GOTO(r, rc = r, val_opts, cleanup);
/* add all top-level defaults for this module, if going to validate subtree, do not add into unres sets
@@ -1846,7 +1846,7 @@ lyd_validate(struct lyd_node **tree, const struct lys_module *module, const stru
if (val_opts & LYD_VALIDATE_NO_DEFAULTS) {
impl_opts |= LYD_IMPLICIT_NO_DEFAULTS;
}
- r = lyd_new_implicit_r(NULL, first2, NULL, mod, validate_subtree ? NULL : node_when_p,
+ r = lyd_new_implicit_r(lyd_parent(*first2), first2, NULL, mod, validate_subtree ? NULL : node_when_p,
validate_subtree ? NULL : node_types_p, validate_subtree ? NULL : ext_node_p, impl_opts, diff);
LY_CHECK_ERR_GOTO(r, rc = r, cleanup);
diff --git a/tests/utests/data/test_parser_xml.c b/tests/utests/data/test_parser_xml.c
index d651253bf..4f33f0035 100644
--- a/tests/utests/data/test_parser_xml.c
+++ b/tests/utests/data/test_parser_xml.c
@@ -977,6 +977,38 @@ test_metadata(void **state)
CHECK_LOG_CTX("Invalid enumeration value \"value\".", "Path \"/a:c/x/@a:attr\", line number 1.");
}
+static void
+test_subtree(void **state)
+{
+ const char *data;
+ struct ly_in *in;
+ struct lyd_node *tree;
+
+ /* prepare data with the parent */
+ data = "\n"
+ " val_a\n"
+ " val_b\n"
+ " 1\n"
+ "\n";
+ assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
+
+ /* parse a subtree of it */
+ data = "\n"
+ " true\n"
+ "\n";
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_SUCCESS, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL));
+ ly_in_free(in, 0);
+
+ /* parse another container, fails */
+ assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
+ assert_int_equal(LY_EVALID, lyd_parse_data(UTEST_LYCTX, tree, in, LYD_XML, 0, LYD_VALIDATE_PRESENT, NULL));
+ ly_in_free(in, 0);
+ CHECK_LOG_CTX("Duplicate instance of \"cont\".", "Data location \"/a:l1[a='val_a'][b='val_b'][c='1']/cont\".");
+
+ lyd_free_all(tree);
+}
+
int
main(void)
{
@@ -999,6 +1031,7 @@ main(void)
UTEST(test_filter_attributes, setup),
UTEST(test_data_skip, setup),
UTEST(test_metadata, setup),
+ UTEST(test_subtree, setup),
};
return cmocka_run_group_tests(tests, NULL, NULL);
diff --git a/tests/utests/data/test_validation.c b/tests/utests/data/test_validation.c
index a953330c9..d02dcc4e1 100644
--- a/tests/utests/data/test_validation.c
+++ b/tests/utests/data/test_validation.c
@@ -1203,6 +1203,7 @@ test_multi_error(void **state)
CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 7.", NULL);
+ CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 7.", NULL);
CHECK_LOG_CTX_APPTAG("Invalid type uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 6.", NULL);
/* json */
@@ -1220,6 +1221,7 @@ test_multi_error(void **state)
CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 9.", NULL);
+ CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\", line number 9.", NULL);
CHECK_LOG_CTX_APPTAG("Invalid non-number-encoded uint32 value \"ahoy\".", "Data location \"/ii:cont/ll\", line number 7.", NULL);
/* validation */
@@ -1239,6 +1241,7 @@ test_multi_error(void **state)
CHECK_LOG_CTX_APPTAG("l leaf is not left", "Data location \"/ii:cont/l3\".", "not-left");
CHECK_LOG_CTX_APPTAG("Must condition \"../l = 'right'\" not satisfied.", "Data location \"/ii:cont/l2\".", "must-violation");
CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
+ CHECK_LOG_CTX_APPTAG("Duplicate instance of \"l\".", "Data location \"/ii:cont/l\".", NULL);
}
const char *schema_j =