module module1
{
import module2;
container container1
{
list list1
{
key leaf1
leaf leaf1 {}
container container2
{
container container3 { ... }
container container4 { ... }
} //container2
} //list1
} //container1
list list2
{
key leaf1
leaf leaf1
{
type leafref
{
path "/container1/list1/leaf1";
}
must "(not(/container1/list1[leaf1=current()][(container2/container3)]) or
(.../type = 'module2:type1'))"
{
error-message
"leaf1 with configured container3 is not supported";
}
must "(not(/container1/list1[leaf1=current()][(container2/container4)]))"
{
error-message
"leaf1 with configured container4 is not supported";
}
} //leaf1
} //list2
} //module1
where
container3 and container4 have ellipsis to denote the multiple contained leaves.
leaf1 is just a name (and the list key)
The idea is that
can can commit an element leaf1 in list2
you cannot commit an element leaf1 in list2 if leaf1/container2/container3 has been configured (exception: if the type is indeed type1, then the restriction is not applied)
you cannot commit an element leaf1 in list2 if leaf1/container2/container4 has been configured (without any exceptions)
So I have indeed tested and if I add leaf1 with container4, I get the expected message “leaf1 with configured container4 is not supported”
BUT starting from scratch again, if I now add leaf1 with container3 , I do not get the expected “leaf1 with configured container3 is not supported”, rather I get the same message as before: “leaf1 with configured container4 is not supported”
If I understand your use case correctly, I believe you can, for example, either make container3 and 4 into presence containers or use a wildcard after container3/4 in the XPath with a tailf:dependency statement for each leaf under them.
Presence containers example:
container container1 {
list list1 {
key leaf1;
leaf leaf1 { type string; }
container container2 {
container container3 { presence ""; }
container container4 { presence ""; }
} //container2
} //list1
} //container1
list list2 {
key leaf1;
leaf leaf1 {
type leafref {
path "/container1/list1/leaf1";
}
must "not(/container1/list1[leaf1=current()]/container2/container3)" {
error-message "leaf1 with configured container3 is not supported";
}
must "not(/container1/list1[leaf1=current()]/container2/container4)" {
error-message "leaf1 with configured container4 is not supported";
}
} //leaf1
} //list2
Wildcard example:
container container1 {
list list1 {
key leaf1;
leaf leaf1 { type string; }
container container2 {
container container3 { leaf leaf2 { type string; } }
container container4 { leaf leaf2 { type string; } }
} //container2
} //list1
} //container1
list list2 {
key leaf1;
leaf leaf1 {
type leafref {
path "/container1/list1/leaf1";
}
must "not(/container1/list1[leaf1=current()]/container2/container3/*)" {
tailf:dependency "/container1/list1/container2/container3/leaf2";
error-message "leaf1 with configured container3 is not supported";
}
must "not(/container1/list1[leaf1=current()]/container2/container4/*)" {
tailf:dependency "/container1/list1/container2/container4/leaf2";
error-message "leaf1 with configured container4 is not supported";
}
} //leaf1
} //list2
thank you @cohult that did the trick.
I believe a reason for my confusion is addressing fields in the must statements.
I am not sure how to “read” the syntax:
The parenthesis around container2/container4 is not required.
I believe the /container1/list1[leaf1=current()][container2/container4] expression means “select the list1 entry equal to the current context node of leaf1 if the list entry container2/container4 child presence container is set (present)”.
The above produces the same result as what I provided earlier: /container1/list1[leaf1=current()]/container2/container4
But for example: /container1/list1[leaf1=current()][container2/container3][container2/container4]
…would evaluate to false if none of or either container3 or container4 is set, but true if both containers are set.