7.8. The "list" Statement
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. The "list" statement takes one argument, which is an identifier, followed by a block of substatements that holds detailed list information. A list entry is uniquely identified by the values of the list's keys, if defined.
7.8.1. The list's Substatements
+--------------+---------+-------------+ | 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. The list's "key" Statement
The "key" statement, which MUST be present if the list represents configuration and MAY be present otherwise, takes as an argument a string that specifies a space-separated list of one or more leaf identifiers of this list. A leaf identifier MUST NOT appear more than once in the key. Each such leaf identifier MUST refer to a child leaf of the list. The leafs can be defined directly in substatements to the list or in groupings used in the list. The combined values of all the leafs specified in the key are used to uniquely identify a list entry. All key leafs MUST be given values when a list entry is created. Thus, any default values in the key leafs or their types are ignored. Any "mandatory" statements in the key leafs are ignored.
A leaf that is part of the key can be of any built-in or derived type. All key leafs in a list MUST have the same value for their "config" as the list itself. The key string syntax is formally defined by the rule "key-arg" in Section 14.7.8.3. The list's "unique" Statement
The "unique" statement is used to put constraints on valid list entries. It takes as an argument a string that contains a space- separated list of schema node identifiers, which MUST be given in the descendant form (see the rule "descendant-schema-nodeid" in Section 14). Each such schema node identifier MUST refer to a leaf. If one of the referenced leafs represents configuration data, then all of the referenced leafs MUST represent configuration data. The "unique" constraint specifies that the combined values of all the leaf instances specified in the argument string, including leafs with default values, MUST be unique within all list entry instances in which all referenced leafs exist or have default values. The constraint is enforced according to the rules in Section 8. The unique string syntax is formally defined by the rule "unique-arg" in Section 14.7.8.3.1. Usage Example
With the following list: list server { key "name"; unique "ip port"; leaf name { type string; } leaf ip { type inet:ip-address; } leaf port { type inet:port-number; } }
the following configuration is not valid: <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> The following configuration is valid, since the "http" and "ftp" list entries do not have a value for all referenced leafs and are thus not taken into account when the "unique" constraint is enforced: <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. The list's Child Node Statements
Within a list, the "container", "leaf", "list", "leaf-list", "uses", "choice", "anydata", and "anyxml" statements can be used to define child nodes to the list.
7.8.5. XML Encoding Rules
A list is encoded as a series of XML elements, one for each entry in the list. Each element's local name is the list's identifier, and its namespace is the module's XML namespace (see Section 7.1.3). There is no XML element surrounding the list as a whole. The list's key nodes are encoded as subelements to the list's identifier element, in the same order as they are defined within the "key" statement. The rest of the list's child nodes are encoded as subelements to the list element, after the keys. If the list defines RPC or action input or output parameters, the subelements are encoded in the same order as they are defined within the "list" statement. Otherwise, the subelements are encoded in any order. Any whitespace between the subelements to the list entry is insignificant, i.e., an implementation MAY insert whitespace characters between subelements. The XML elements representing list entries MUST appear in the order specified by the user if the list is "ordered-by user"; otherwise, the order is implementation dependent. The XML elements representing list entries MAY be interleaved with elements for siblings of the list, unless the list defines RPC or action input or output parameters.7.8.6. NETCONF <edit-config> Operations
List entries can be created, deleted, replaced, and modified through <edit-config> by using the "operation" attribute in the list's XML element. In each case, the values of all keys are used to uniquely identify a list entry. If all keys are not specified for a list entry, a "missing-element" error is returned. In an "ordered-by user" list, the attributes "insert" and "key" in the YANG XML namespace (Section 5.3.1) can be used to control where in the list the entry is inserted. These can be used during "create" operations to insert a new list entry, or during "merge" or "replace" operations to insert a new list entry or move an existing one. The "insert" attribute can take the values "first", "last", "before", and "after". If the value is "before" or "after", the "key" attribute MUST also be used, to specify an existing element in the list. The value of the "key" attribute is the key predicates of the full instance identifier (see Section 9.13) for the list entry.
If no "insert" attribute is present in the "create" operation, it defaults to "last". If several entries in an "ordered-by user" list are modified in the same <edit-config> request, the entries are modified one at a time, in the order of the XML elements in the request. In a <copy-config> or in an <edit-config> with a "replace" operation that covers the entire list, the list entry order is the same as the order of the XML elements in the request. When a NETCONF server processes an <edit-config> request, the elements of procedure for a list node are as follows: o If the operation is "merge" or "replace", the list entry is created if it does not exist. If the list entry already exists and the "insert" and "key" attributes are present, the list entry is moved according to the values of the "insert" and "key" attributes. If the list entry exists and the "insert" and "key" attributes are not present, the list entry is not moved. o If the operation is "create", the list entry is created if it does not exist. If the list entry already exists, a "data-exists" error is returned. o If the operation is "delete", the entry is deleted from the list if it exists. If the list entry does not exist, a "data-missing" error is returned.
7.8.7. Usage Example
Given the following list: 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; } } A corresponding XML instance example: <user> <name>fred</name> <type>admin</type> <full-name>Fred Flintstone</full-name> </user>
To create a new 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> To change the type of "fred" to "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>
Given the following ordered-by user list: 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; } } The following would be used to insert a new user "barney rubble" after the user "fred flintstone": <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>
The following would be used to move the user "barney rubble" before the user "fred flintstone": <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>7.9. The "choice" Statement
The "choice" statement defines a set of alternatives, only one of which may be present in any one data tree. The argument is an identifier, followed by a block of substatements that holds detailed choice information. The identifier is used to identify the choice node in the schema tree. A choice node does not exist in the data tree. A choice consists of a number of branches, each defined with a "case" substatement. Each branch contains a number of child nodes. The nodes from at most one of the choice's branches exist at the same time. Since only one of the choice's cases can be valid at any time in the data tree, the creation of a node from one case implicitly deletes all nodes from all other cases. If a request creates a node from a case, the server will delete any existing nodes that are defined in other cases inside the choice.
7.9.1. The choice's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | anydata | 7.10 | 0..n | | anyxml | 7.11 | 0..n | | case | 7.9.2 | 0..n | | choice | 7.9 | 0..n | | config | 7.21.1 | 0..1 | | container | 7.5 | 0..n | | default | 7.9.3 | 0..1 | | description | 7.21.3 | 0..1 | | if-feature | 7.20.2 | 0..n | | leaf | 7.6 | 0..n | | leaf-list | 7.7 | 0..n | | list | 7.8 | 0..n | | mandatory | 7.9.4 | 0..1 | | reference | 7.21.4 | 0..1 | | status | 7.21.2 | 0..1 | | when | 7.21.5 | 0..1 | +--------------+---------+-------------+7.9.2. The choice's "case" Statement
The "case" statement is used to define branches of the choice. It takes as an argument an identifier, followed by a block of substatements that holds detailed case information. The identifier is used to identify the case node in the schema tree. A case node does not exist in the data tree. Within a "case" statement, the "anydata", "anyxml", "choice", "container", "leaf", "list", "leaf-list", and "uses" statements can be used to define child nodes to the case node. The identifiers of all these child nodes MUST be unique within all cases in a choice. For example, the following is illegal: choice interface-type { // This example is illegal YANG case a { leaf ethernet { ... } } case b { container ethernet { ...} } }
As a shorthand, the "case" statement can be omitted if the branch contains a single "anydata", "anyxml", "choice", "container", "leaf", "list", or "leaf-list" statement. In this case, the case node still exists in the schema tree, and its identifier is the same as the identifier of the child node. Schema node identifiers (Section 6.5) MUST always explicitly include case node identifiers. The following example: choice interface-type { container ethernet { ... } } is equivalent to: choice interface-type { case ethernet { container ethernet { ... } } } The case identifier MUST be unique within a choice.7.9.2.1. The case's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | anydata | 7.10 | 0..n | | anyxml | 7.11 | 0..n | | choice | 7.9 | 0..n | | container | 7.5 | 0..n | | description | 7.21.3 | 0..1 | | if-feature | 7.20.2 | 0..n | | leaf | 7.6 | 0..n | | leaf-list | 7.7 | 0..n | | list | 7.8 | 0..n | | reference | 7.21.4 | 0..1 | | status | 7.21.2 | 0..1 | | uses | 7.13 | 0..n | | when | 7.21.5 | 0..1 | +--------------+---------+-------------+
7.9.3. The choice's "default" Statement
The "default" statement indicates if a case should be considered as the default if no child nodes from any of the choice's cases exist. The argument is the identifier of the default "case" statement. If the "default" statement is missing, there is no default case. The "default" statement MUST NOT be present on choices where "mandatory" is "true". The default case is only important when considering the "default" statements of nodes under the cases (i.e., default values of leafs and leaf-lists, and default cases of nested choices). The default values and nested default cases under the default case are used if none of the nodes under any of the cases are present. There MUST NOT be any mandatory nodes (Section 3) directly under the default case. Default values for child nodes under a case are only used if one of the nodes under that case is present or if that case is the default case. If none of the nodes under a case are present and the case is not the default case, the default values of the cases' child nodes are ignored.
In this example, the choice defaults to "interval", and the default value will be used if none of "daily", "time-of-day", or "manual" are present. If "daily" is present, the default value for "time-of-day" will be used. container transfer { choice how { default interval; case interval { leaf interval { type uint16; units minutes; default 30; } } case daily { leaf daily { type empty; } leaf time-of-day { type string; units 24-hour-clock; default "01.00"; } } case manual { leaf manual { type empty; } } } }
7.9.4. The choice's "mandatory" Statement
The "mandatory" statement, which is optional, takes as an argument the string "true" or "false" and puts a constraint on valid data. If "mandatory" is "true", at least one node from exactly one of the choice's case branches MUST exist. If not specified, the default is "false". The behavior of the constraint depends on the type of the choice's closest ancestor node in the schema tree that is not a non-presence container (see Section 7.5.1): o If no such ancestor exists in the schema tree, the constraint is enforced. o Otherwise, if this ancestor is a case node, the constraint is enforced if any other node from the case exists. o Otherwise, it is enforced if the ancestor node exists. The constraint is further enforced according to the rules in Section 8.7.9.5. XML Encoding Rules
The choice and case nodes are not visible in XML. The child nodes of the selected "case" statement MUST be encoded in the same order as they are defined in the "case" statement if they are part of an RPC or action input or output parameter definition. Otherwise, the subelements are encoded in any order.
7.9.6. Usage Example
Given the following choice: container protocol { choice name { case a { leaf udp { type empty; } } case b { leaf tcp { type empty; } } } } A corresponding XML instance example: <protocol> <tcp/> </protocol> To change the protocol from TCP to UDP: <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"> <protocol> <udp nc:operation="create"/> </protocol> </system> </config> </edit-config> </rpc>
7.10. The "anydata" Statement
The "anydata" statement defines an interior node in the schema tree. It takes one argument, which is an identifier, followed by a block of substatements that holds detailed anydata information. The "anydata" statement is used to represent an unknown set of nodes that can be modeled with YANG, except anyxml, but for which the data model is not known at module design time. It is possible, though not required, for the data model for anydata content to become known through protocol signaling or other means that are outside the scope of this document. An example of where anydata can be useful is a list of received notifications where the specific notifications are not known at design time. An anydata node cannot be augmented (see Section 7.17). An anydata node exists in zero or one instance in the data tree. An implementation may or may not know the data model used to model a specific instance of an anydata node. Since the use of anydata limits the manipulation of the content, the "anydata" statement SHOULD NOT be used to define configuration data.7.10.1. The anydata's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | config | 7.21.1 | 0..1 | | description | 7.21.3 | 0..1 | | if-feature | 7.20.2 | 0..n | | mandatory | 7.6.5 | 0..1 | | must | 7.5.3 | 0..n | | reference | 7.21.4 | 0..1 | | status | 7.21.2 | 0..1 | | when | 7.21.5 | 0..1 | +--------------+---------+-------------+
7.10.2. XML Encoding Rules
An anydata node is encoded as an XML element. The element's local name is the anydata's identifier, and its namespace is the module's XML namespace (see Section 7.1.3). The value of the anydata node is a set of nodes, which are encoded as XML subelements to the anydata element.7.10.3. NETCONF <edit-config> Operations
An anydata node is treated as an opaque chunk of data. This data can be modified in its entirety only. Any "operation" attributes present on subelements of an anydata node are ignored by the NETCONF server. When a NETCONF server processes an <edit-config> request, the elements of procedure for the anydata node are as follows: o If the operation is "merge" or "replace", the node is created if it does not exist, and its value is set to the subelements of the anydata node found in the XML RPC data. o If the operation is "create", the node is created if it does not exist, and its value is set to the subelements of the anydata node found in the XML RPC data. If the node already exists, a "data-exists" error is returned. o If the operation is "delete", the node is deleted if it exists. If the node does not exist, a "data-missing" error is returned.7.10.4. Usage Example
Given the following "anydata" statement: list logged-notification { key time; leaf time { type yang:date-and-time; } anydata data; }
The following is a valid encoding of such a list instance: <logged-notification> <time>2014-07-29T13:43:12Z</time> <data> <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"> <eventTime>2014-07-29T13:43:01Z</eventTime> <event xmlns="urn:example:event"> <event-class>fault</event-class> <reporting-entity> <card>Ethernet0</card> </reporting-entity> <severity>major</severity> </event> </notification> </data> </logged-notification>7.11. The "anyxml" Statement
The "anyxml" statement defines an interior node in the schema tree. It takes one argument, which is an identifier, followed by a block of substatements that holds detailed anyxml information. The "anyxml" statement is used to represent an unknown chunk of XML. No restrictions are placed on the XML. This can be useful, for example, in RPC replies. An example is the <filter> parameter in the <get-config> operation in NETCONF. An anyxml node cannot be augmented (see Section 7.17). An anyxml node exists in zero or one instance in the data tree. Since the use of anyxml limits the manipulation of the content, the "anyxml" statement SHOULD NOT be used to define configuration data. It should be noted that in YANG version 1, "anyxml" was the only statement that could model an unknown hierarchy of data. In many cases, this unknown hierarchy of data is actually modeled in YANG, but the specific YANG data model is not known at design time. In these situations, it is RECOMMENDED to use "anydata" (Section 7.10) instead of "anyxml".
7.11.1. The anyxml's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | config | 7.21.1 | 0..1 | | description | 7.21.3 | 0..1 | | if-feature | 7.20.2 | 0..n | | mandatory | 7.6.5 | 0..1 | | must | 7.5.3 | 0..n | | reference | 7.21.4 | 0..1 | | status | 7.21.2 | 0..1 | | when | 7.21.5 | 0..1 | +--------------+---------+-------------+7.11.2. XML Encoding Rules
An anyxml node is encoded as an XML element. The element's local name is the anyxml's identifier, and its namespace is the module's XML namespace (see Section 7.1.3). The value of the anyxml node is encoded as XML content of this element. Note that any XML prefixes used in the encoding are local to each instance encoding. This means that the same XML may be encoded differently by different implementations.7.11.3. NETCONF <edit-config> Operations
An anyxml node is treated as an opaque chunk of data. This data can be modified in its entirety only. Any "operation" attributes present on subelements of an anyxml node are ignored by the NETCONF server. When a NETCONF server processes an <edit-config> request, the elements of procedure for the anyxml node are as follows: o If the operation is "merge" or "replace", the node is created if it does not exist, and its value is set to the XML content of the anyxml node found in the XML RPC data. o If the operation is "create", the node is created if it does not exist, and its value is set to the XML content of the anyxml node found in the XML RPC data. If the node already exists, a "data-exists" error is returned. o If the operation is "delete", the node is deleted if it exists. If the node does not exist, a "data-missing" error is returned.
7.11.4. Usage Example
Given the following "anyxml" statement: anyxml html-info; The following are two valid encodings of the same anyxml value: <html-info> <p xmlns="http://www.w3.org/1999/xhtml"> This is <em>very</em> cool. </p> </html-info> <html-info> <x:p xmlns:x="http://www.w3.org/1999/xhtml"> This is <x:em>very</x:em> cool. </x:p> </html-info>7.12. The "grouping" Statement
The "grouping" statement is used to define a reusable block of nodes, which may be used locally in the module or submodule, and by other modules that import from it, according to the rules in Section 5.5. It takes one argument, which is an identifier, followed by a block of substatements that holds detailed grouping information. The "grouping" statement is not a data definition statement and, as such, does not define any nodes in the schema tree. A grouping is like a "structure" or a "record" in conventional programming languages. Once a grouping is defined, it can be referenced in a "uses" statement (see Section 7.13). A grouping MUST NOT reference itself, neither directly nor indirectly through a chain of other groupings. If the grouping is defined at the top level of a YANG module or submodule, the grouping's identifier MUST be unique within the module. A grouping is more than just a mechanism for textual substitution; it also defines a collection of nodes. Identifiers appearing inside the grouping are resolved relative to the scope in which the grouping is defined, not where it is used. Prefix mappings, type names, grouping names, and extension usage are evaluated in the hierarchy
where the "grouping" statement appears. For extensions, this means that extensions defined as direct children to a "grouping" statement are applied to the grouping itself. Note that if a grouping defines an action or a notification node in its hierarchy, then it cannot be used in all contexts. For example, it cannot be used in an rpc definition. See Sections 7.15 and 7.16.7.12.1. The grouping's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | action | 7.15 | 0..n | | anydata | 7.10 | 0..n | | anyxml | 7.11 | 0..n | | choice | 7.9 | 0..n | | container | 7.5 | 0..n | | description | 7.21.3 | 0..1 | | grouping | 7.12 | 0..n | | leaf | 7.6 | 0..n | | leaf-list | 7.7 | 0..n | | list | 7.8 | 0..n | | notification | 7.16 | 0..n | | reference | 7.21.4 | 0..1 | | status | 7.21.2 | 0..1 | | typedef | 7.3 | 0..n | | uses | 7.13 | 0..n | +--------------+---------+-------------+7.12.2. Usage Example
import ietf-inet-types { prefix "inet"; } grouping endpoint { description "A reusable endpoint group."; leaf ip { type inet:ip-address; } leaf port { type inet:port-number; } }
7.13. The "uses" Statement
The "uses" statement is used to reference a "grouping" definition. It takes one argument, which is the name of the grouping. The effect of a "uses" reference to a grouping is that the nodes defined by the grouping are copied into the current schema tree and are then updated according to the "refine" and "augment" statements. The identifiers defined in the grouping are not bound to a namespace until the contents of the grouping are added to the schema tree via a "uses" statement that does not appear inside a "grouping" statement, at which point they are bound to the namespace of the current module.7.13.1. The uses's Substatements
+--------------+---------+-------------+ | substatement | section | cardinality | +--------------+---------+-------------+ | augment | 7.17 | 0..n | | description | 7.21.3 | 0..1 | | if-feature | 7.20.2 | 0..n | | reference | 7.21.4 | 0..1 | | refine | 7.13.2 | 0..n | | status | 7.21.2 | 0..1 | | when | 7.21.5 | 0..1 | +--------------+---------+-------------+7.13.2. The "refine" Statement
Some of the properties of each node in the grouping can be refined with the "refine" statement. The argument is a string that identifies a node in the grouping. This node is called the refine's target node. If a node in the grouping is not present as a target node of a "refine" statement, it is not refined and thus is used exactly as it was defined in the grouping. The argument string is a descendant schema node identifier (see Section 6.5). The following refinements can be done: o A leaf or choice node may get a default value, or a new default value if it already had one. o A leaf-list node may get a set of default values, or a new set of default values if it already had defaults; i.e., the set of refined default values replaces the defaults already given.
o Any node may get a specialized "description" string. o Any node may get a specialized "reference" string. o Any node may get a different "config" statement. o A leaf, anydata, anyxml, or choice node may get a different "mandatory" statement. o A container node may get a "presence" statement. o A leaf, leaf-list, list, container, anydata, or anyxml node may get additional "must" expressions. o A leaf-list or list node may get a different "min-elements" or "max-elements" statement. o A leaf, leaf-list, list, container, choice, case, anydata, or anyxml node may get additional "if-feature" expressions. o Any node can get refined extensions, if the extension allows refinement. See Section 7.19 for details.7.13.3. XML Encoding Rules
Each node in the grouping is encoded as if it was defined inline, even if it is imported from another module with another XML namespace.7.13.4. Usage Example
To use the "endpoint" grouping defined in Section 7.12.2 in a definition of an HTTP server in some other module, we can do: import example-system { prefix "sys"; } container http-server { leaf name { type string; } uses sys:endpoint; }
A corresponding XML instance example: <http-server> <name>extern-web</name> <ip>192.0.2.1</ip> <port>80</port> </http-server> If port 80 should be the default for the HTTP server, a default can be added: container http-server { leaf name { type string; } uses sys:endpoint { refine port { default 80; } } } If we want to define a list of servers and each server has "ip" and "port" as keys, we can do: list server { key "ip port"; leaf name { type string; } uses sys:endpoint; } The following is an error: container http-server { uses sys:endpoint; leaf ip { // illegal - same identifier "ip" used twice type string; } }