7.8. “列表”声明
“list
”语句用于定义架构树中的内部数据节点。 列表节点可能存在于数据树中的多个实例中。 每个这样的实例被称为列表条目。 “list
”语句带有一个参数,这个参数是一个标识符,后跟一个包含详细列表信息的子语句块。
如果定义了列表条目,列表条目的唯一标识就是列表的键值。
7.8.1. list
子语句
+--------------+---------+-------------+
| substatement | section | cardinality |
+--------------+---------+-------------+
| action | 7.15 | 0..n |
| anydata | 7.10 | 0..n |
| anyxml | 7.11 | 0..n |
| choice | 7.9 | 0..n |
| config | 7.21.1 | 0..1 |
| container | 7.5 | 0..n |
| description | 7.21.3 | 0..1 |
| grouping | 7.12 | 0..n |
| if-feature | 7.20.2 | 0..n |
| key | 7.8.2 | 0..1 |
| leaf | 7.6 | 0..n |
| leaf-list | 7.7 | 0..n |
| list | 7.8 | 0..n |
| max-elements | 7.7.6 | 0..1 |
| min-elements | 7.7.5 | 0..1 |
| must | 7.5.3 | 0..n |
| notification | 7.16 | 0..n |
| ordered-by | 7.7.7 | 0..1 |
| reference | 7.21.4 | 0..1 |
| status | 7.21.2 | 0..1 |
| typedef | 7.3 | 0..n |
| unique | 7.8.3 | 0..n |
| uses | 7.13 | 0..n |
| when | 7.21.5 | 0..1 |
+--------------+---------+-------------+
7.8.2. 列表的“key
”声明
“key
”语句,如果列表表示配置,并且可能存在,则必须显示它,作为参数,该语句指定了该列表中的一个或多个叶标识符的空格分隔的列表。叶子标识符不能在key
中出现一次以上。 每个这样的叶子标识符必须引用列表的子叶子。 叶子可以直接在子列表中定义,也可以在列表中使用分组。
key
中指定的所有叶子的组合值用于唯一标识列表条目。 在创建列表条目时,所有关键叶子必须被给定值。 因此,关键叶子或其类型中的任何默认值都将被忽略。 关键叶子中的任何“强制性”陈述都将被忽略。
作为key
一部分的叶子可以是任何内置或派生类型。
列表中的所有关键字必须与列表本身具有相同的“配置”值。
key
字符串语法由第14节中的“key-arg”
规则正式定义。
7.8.3. 列表的“唯一”声明
“unique
”语句用于对有效的列表条目进行约束。 它以一个字符串作为参数,该字符串包含空间分隔的模式节点标识符列表,必须以后代形式给出(参见第14节中的“descendant-schema-nodeid
”规则)。 每个这样的模式节点标识符必须指向一个叶子。
如果其中一个引用的叶子代表配置数据,那么所有引用的叶子必须代表配置数据。
“unique
”约束指定参数字符串中指定的所有叶子实例的组合值,包括具有默认值的叶子,在所有引用叶子存在或具有默认值的所有列表项实例中必须是唯一的。 约束条件按照第8节的规定执行。
唯一的字符串语法由第14节中的“unique-arg
”规则正式定义。
7.8.3.1. 使用示例
用下面的列表:
list server {
key "name";
unique "ip port";
leaf name {
type string;
}
leaf ip {
type inet:ip-address;
}
leaf port {
type inet:port-number;
}
}
以下配置无效:
<server>
<name>smtp</name>
<ip>192.0.2.1</ip>
<port>25</port>
</server>
<server>
<name>http</name>
<ip>192.0.2.1</ip>
<port>25</port>
</server>
以下配置是有效的,因为“http
”和“ftp
”列表项不具有所有引用叶子的值,因此当“唯一”约束被强制执行时不被考虑:
<server>
<name>smtp</name>
<ip>192.0.2.1</ip>
<port>25</port>
</server>
<server>
<name>http</name>
<ip>192.0.2.1</ip>
</server>
<server>
<name>ftp</name>
<ip>192.0.2.1</ip>
</server>
7.8.4. 列表的子节点语句
在列表中,可以使用“container
”,“leaf
”,“list
”,“leaf-list
”,“uses
”,“choice
”,“anydata
”和“anyxml
”语句来将子节点定义到列表。
7.8.5. XML
编码规则
列表被编码为一系列XML
元素,列表中的每个条目都有一个。每个元素的本地名称是列表的标识符,其名称空间是模块的XML
名称空间(参见第7.1.3节)。整个列表中没有XML
元素。
列表的关键节点被编码为列表的标识符元素的子元素,其顺序与“key
”语句中定义的顺序相同。
列表的其余部分的子节点被编码为列表元素的子元素。如果列表定义了RPC
或操作输入或输出参数,则子元素将按照“list
”语句中定义的顺序进行编码。否则,子元素按任何顺序编码。
列表条目的子元素之间的任何空格是不重要的,即实现可以在子元素之间插入空白字符。
如果列表是“ordered-by user
”,则表示列表条目的XML
元素必须按用户指定的顺序出现;否则,顺序依赖于实现。表示列表条目的XML
元素可以与列表的同级元素交错,除非列表定义了RPC
或动作输入或输出参数。
7.8.6. NETCONF
<edit-config>
操作
列表条目可以通过使用列表XML
元素中的“operation
”属性通过<edit-config>
创建,删除,替换和修改。在每种情况下,所有key
的值都用于唯一标识列表条目。如果没有为列表项指定所有键,则返回“missing-element
”错误。
在“ordered-by user
”列表中,YANG
XML
名称空间(第5.3.1节)中的属性“insert
”和“key
”可用于控制列表中插入条目的位置。这些可以在“create
”操作期间用于插入新的列表条目,或在“merge
”或“replace
”操作期间插入新的列表条目或移动现有条目。
“insert
”属性可以取值“first
”,“last
”,“before
”和“after
”。如果值是“before
”或“after
”,则还必须使用“key
”属性来指定列表中的现有元素。 “key
”属性的值是列表条目的完整实例标识符(见第9.13节)的关键谓词。
如果在“create
”操作中没有“insert
”属性,则默认为“last
”。
如果“ordered-by user
”列表中的多个条目在同一个<edit-config>
请求中被修改,则按请求中XML
元素的顺序一次修改一个条目。
在具有覆盖整个列表的“replace
”操作的<copy-config>
或<edit-config>
中,列表输入顺序与请求中XML
元素的顺序相同。
当NETCONF
服务器处理<edit-config>
请求时,列表节点的过程元素如下所示:
如果操作是“
merge
”或“replace
”,则列表条目如果不存在则创建。如果列表条目已经存在,并且存在“insert
”和“key
”属性,则根据“insert
”和“key
”属性的值移动列表条目。如果列表条目存在并且“insert
”和“key
”属性不存在,则列表条目不会移动。如果操作是“
create
”,则列表条目如果不存在则创建。如果列表项已经存在,则返回“data-exists
”错误。如果操作是“
delete
”,则条目从列表中删除(如果存在)。如果列表条目不存在,则返回“data-missing
”错误。
7.8.7. 使用示例
鉴于以下列表:
list user {
key "name";
config true;
description
"This is a list of users in the system.";
leaf name {
type string;
}
leaf type {
type string;
}
leaf full-name {
type string;
}
}
相应的XML
实例示例:
<user>
<name>fred</name>
<type>admin</type>
<full-name>Fred Flintstone</full-name>
</user>
要创建一个新的用户“barney
”:
<rpc message-id="101"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<running/>
</target>
<config>
<system xmlns="urn:example:config">
<user nc:operation="create">
<name>barney</name>
<type>admin</type>
<full-name>Barney Rubble</full-name>
</user>
</system>
</config>
</edit-config>
</rpc>
要将“fred
”的类型更改为“superuser
”:
<rpc message-id="102"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
<edit-config>
<target>
<running/>
</target>
<config>
<system xmlns="urn:example:config">
<user>
<name>fred</name>
<type>superuser</type>
</user>
</system>
</config>
</edit-config>
</rpc>
给出以下按用户列表:
list user {
description
"This is a list of users in the system.";
ordered-by user;
config true;
key "first-name surname";
leaf first-name {
type string;
}
leaf surname {
type string;
}
leaf type {
type string;
}
}
以下将用于在用户“fred flintstone
”之后插入新用户“barney rubble
”:
<rpc message-id="101"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:yang="urn:ietf:params:xml:ns:yang:1">
<edit-config>
<target>
<running/>
</target>
<config>
<system xmlns="urn:example:config"
xmlns:ex="urn:example:config">
<user nc:operation="create"
yang:insert="after"
yang:key="[ex:first-name='fred']
[ex:surname='flintstone']">
<first-name>barney</first-name>
<surname>rubble</surname>
<type>admin</type>
</user>
</system>
</config>
</edit-config>
</rpc>
以下将用于在用户“fred flintstone
”之前移动用户“barney rubble
”:
<rpc message-id="102"
xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
xmlns:yang="urn:ietf:params:xml:ns:yang:1">
<edit-config>
<target>
<running/>
</target>
<config>
<system xmlns="urn:example:config"
xmlns:ex="urn:example:config">
<user nc:operation="merge"
yang:insert="before"
yang:key="[ex:name='fred']
[ex:surname='flintstone']">
<first-name>barney</first-name>
<surname>rubble</surname>
</user>
</system>
</config>
</edit-config>
</rpc>