Must statement xpath confusion

please consider the following yang model

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”

why is that?

Thank you in advance for your help

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
1 Like

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:

/container1/list1[leaf1=current()][(container2/container4)]

especially the 2nd set of square brackets eludes me. I understand this is yang syntax but I could not find examples anywhere. could you provide any?

For example, list1[key-leaf1=1][key-leaf2=2] can be used for lists with two keys.

1 Like

what if there is no 2nd key (in container2) as is the case above?

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.