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
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.