relative path of an xpath expression inside a YANG list

1.5k views Asked by At

I have the following YANG model:

list machines {
                key "name";
                leaf "name" {
                    type string;
                }
                leaf link {
                    type leafref {
                            path "../name";
                    }
                }
}

Suppose there are three elements in the list:

"machines" : [
    { "name": "a" },
    { "name": "b" },
    { "name": "c" }
]

If I want to set "link" for element b, the valid values for "link" are "a", "b", "c" or just "b"?

I didn't find answer in RFC7950. And in pyangbind, only "b" can be set. But I'm not sure that is the right behavior.

If ../name here can only reference "b", what is the correct path to reference "a", "b", "c", that is, all names of list elements?

If ../name here can reference "a", "b", "c", what is the correct path to reference only "b"?

Thanks

1

There are 1 answers

3
predi On BEST ANSWER

This is what RFC7950 says for lists:

The "list" statement is used to define an interior data node in the schema tree. A list node may exist in multiple instances in the data tree. Each such instance is known as a list entry.

Despite your JSON encoded instance document seemingly suggesting that only one instance of the machines list exists within it, there are actually three list instances. The name you chose for the list deepens this confusion, as the recommended name for a list definition would be "machine". An enveloping container would take the plural form of the name.

In XML encoding, the above becomes more obvious.

<machines>
  <name>a</name>
</machines>
<machines>
  <name>b</name>
</machines>
<machines>
  <name>c</name>
</machines>

If I want to set "link" for element b, the valid values for "link" are "a", "b", "c" or just "b"?

A leafref path expression is a subset of XPath. The same rules apply, you are just limited in what you can select with the expression - it is intended to select one or more leaf instances. XPath always works on a tree of objects and this tree is (somewhat awkwardly) defined in RFC7950 - the document refers to this tree as the accessible tree and it consists of instantiated data nodes (subset of a data tree). This is described in Section 6.4.1.

In addition to the accessible tree, a context node is also important (relative expressions refer to it implicitly). Here is what RFC7950 says about the context node in your example.

the context node is the node in the data tree for which the "path" statement is defined

This would be the link instance in your case, a sibling to the name instance with value b. Here's a quick pseudo- data tree:

machines[1]
 +-name(a)
machines[2]
 +-name(b)
 +-link
machines[3]
 +-name(c)

The expression first proceeds to select the parent of link. There is always only one parent for any given data node instance and in your case that would be the list instance that has both siblings mentioned before as children (machines[2]). The expression then proceeds to select children that have a name name, which is the instance of name with value b.

This means the only valid value for your link node is b. This only applies to your specific example.

If ../name here can only reference "b", what is the correct path to reference "a", "b", "c", that is, all names of list elements?

Use an absolute expression or go one parent further, then back again:

  • //machines/name (replace the // with an absolute path to machines)
  • ../../machines/name

Both of these will then first select all instantiated machines.

Note: this is just how XPath works. The other alternative would apply if RFC7950 text would say "there is only one list instance with multiple entries" or something along those lines.