XML Encoding of Data Modeled with YANG
Kent Watsen
Watsen Networks
kent+ietf@watsen.net
Operations
NETMOD Working Group
data modeling
This document defines encoding rules for representing YANG modeled configuration data, state data, parameters of Remote Procedure Call (RPC) operations or actions, and notifications defined using XML.

GitHub Information (to be removed by RFC Editor)
This document is developed on GitHub (https://github.com/netmod-wg/rfc7950bis-and-friends). If you wish to contribute, please consider opening a pull request (PR). Please see the README file for details.

Introduction
This document defines encoding rules for representing YANG [RFC7950] modeled configuration data, state data, parameters of Remote Procedure Call (RPC) operations or actions, and notifications defined using the Extensible Markup Language (XML) [XML].

Terminology and Notation
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
The following terms are defined in [RFC7950]:
- action
- anydata
- anyxml
- augment
- container
- data node
- data tree
- identity
- instance identifier
- leaf
- leaf-list
- list
- module
- RPC operation
- submodule
The following terms are defined in [RFC6241]:
- configuration data
- notification
- state data

Properties of the XML Encoding
This document defines XML encoding for YANG data trees and their subtrees. It is always assumed that there may be one or more top-level elements in XML-encoded configuration data and state data. RPC operations and notifications contain a single top-level element.
Instances of YANG data nodes (leafs, containers, leaf-lists, lists, anydata nodes, and anyxml nodes) are encoded as XML elements having the name of the YANG data node. Section 4) defines how the name is qualified with a namespace, and the following sections deal with the value part. The encoding rules are identical for all types of data trees, i.e., configuration data, state data, parameters of RPC operations, actions, and notifications.
With the exception of "anydata" encoding (Section 5.5), all rules in this document are also applicable to YANG 1.0 [RFC6020].
With the exception of anyxml and schema-less anydata nodes, it is possible to map an XML-encoded data tree to other encodings, such as the JSON encoding as defined in [RFC7951], and vice versa. However, such conversions require the YANG data model to be available.

Names and Namespaces
An XML element name is always identical to the identifier of the corresponding YANG data node.
All XML elements encoding YANG data are namespace qualified. The XML default namespace is never used in YANG encoded data.
The namespace of an XML element is either inherited from its ancestor or set using the "xmlns" attribute in the element.
The "xmlns" attribute may either set the XML default namespace or define and use a prefix for the namespace. Note that the same XML may be encoded differently by different implementations. For instance, the following two XML documents are the same.
Document 1:

<foo xmlns="https://example.com/foo"/>

Document 2:

<my-prefix:foo xmlns:my-prefix="https://example.com/foo"/>

The "namespace" statement of a module determines the namespace of all data node names defined in that module. If a data node is defined in a submodule, then the namespace of the main module is used.
A namespace MUST be set for all top-level XML elements and then also whenever the namespaces of the data node and its parent node are different.
For example, consider the following YANG module:

module example-foomod {

  namespace "https://example.com/foomod";

  prefix "foomod";

  container top {
    leaf foo {
      type uint8;
    }
  }
}

If the data model consists only of this module, then the following is valid XML-encoded configuration data:

<top xmlns="https://example.com/foomod">
  <foo>54</foo>
</top>

Note that the top-level element sets the default namespace which "foo" leaf inherits its parent container "top".
Now, assume that the container "top" is augmented from another module, "example-barmod":

module example-barmod {

  namespace "https://example.com/barmod";

  prefix "barmod";

  import example-foomod {
    prefix "foomod";
  }

  augment "/foomod:top" {
    leaf bar {
      type boolean;
    }
  }
}

Valid XML-encoded configuration data containing both leafs may then look like this:

<top xmlns="https://example.com/foomod">
  <foo>54</foo>
  <bar xmlns="https://example.com/barmod">true</bar>
</top>

The "bar" leaf's element sets a new default namespace because its parent is defined in a different module.
Prefixed namespace identifiers are sometimes needed when encoding values of the "identityref" and "instance-identifier" types. See Section 6.8 and Section 6.11 for details.

Encoding of YANG Data Node Instances

The "leaf" Data Node
A leaf node is encoded as an XML element. The element's local name is the leaf's identifier, and its namespace is the module's XML namespace (see Section 4).
The value of the leaf node is encoded to XML according to the type (see Section 6 for type encoding rules) and is sent as character data in the element.
Example: For the leaf node definition

leaf foo {
  type uint8;
}

the following is a valid XML-encoded instance:

<foo>123</foo>

The "container" Data Node
A container node is encoded as an XML element. The element's local name is the container's identifier, and its namespace is the module's XML namespace (see Section 4).
The container's child nodes are encoded as subelements to the container element. If the container defines RPC or action input or output parameters, these subelements are encoded in the same order as they are defined within the "container" statement. Otherwise, the subelements are encoded in any order.
Any whitespace between the subelements to the container is insignificant, i.e., an implementation MAY insert whitespace characters between subelements.
If a non-presence container does not have any child nodes, the container may or may not be present in the XML encoding.
Example: For the container definition

container bar {
  leaf foo {
    type uint8;
  }
}

container baz {
  presence "Indicates baz is configured";
}

the following is valid XML-encoded instance data:

<bar>
    <foo>123</foo>
</bar>

<baz/>

Note that, the example above sets presence container "baz", which is encoded as an empty XML element, since it has no descendants.

The "leaf-list" Data Node
A leaf-list node is encoded as a series of XML elements. Each element's local name is the leaf-list's identifier, and its namespace is the module's XML namespace (see Section 4). There is no XML element surrounding the leaf-list as a whole.
The value of each leaf-list entry is encoded to XML according to the type and is sent as character data in the element (see Section 6 for type encoding rules).
The XML elements representing leaf-list entries MUST appear in the order specified by the user if the leaf-list is "ordered-by user"; otherwise, the order is implementation dependent. The XML elements representing leaf-list entries MAY be interleaved with elements for siblings of the leaf-list, unless the leaf-list defines RPC or action input or output parameters.
Example: For the leaf-list definition

leaf-list foo {
  type uint8;
}

the following is a valid XML-encoded instance:

<foo>123</foo>
<foo>0</foo>

The "list" Data Node
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 4). 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.
Example: For the list definition

list bar {
  key "foo baz";
  leaf foo {
    type uint8;
  }
  leaf baz {
    type string;
  }
}

the following is a valid XML-encoded instance:

<bar>
    <foo>123</foo>
    <baz>zig</baz>
</bar>
<bar>
    <foo>456</foo>
    <baz>zag</baz>
</bar>

The "anydata" Data Node
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 4). The value of the anydata node is a set of nodes, which are encoded as XML subelements to the anydata element.
The anydata data node serves as a container for an arbitrary set of nodes that otherwise appear as normal YANG-modeled data. A data model for anydata content may or may not be known at runtime. In the latter case, converting XML-encoded instances to other encodings, such as JSON [RFC7951] may be impossible.
Example: For the anydata definition

anydata data;

the following is a valid XML-encoded instance:

<data>
    <notification xmlns="urn:ietf:params:xml:ns:netmod:notification">
        <eventTime>2014-07-29T13:43:01Z</eventTime>
        <event xmlns="https://example.com/example-event">
            <event-class>fault</event-class>
            <reporting-entity>
                <card>Ethernet0</card>
            </reporting-entity>
            <severity>major</severity>
        </event>
    </notification>
</data>

The "anyxml" Data Node
An anyxml node is encoded the same as an anydata node. Please see Section 5.5 for how the anydata node is encoded.

Metadata Objects
Apart from instances of YANG data nodes, XML elements MAY contain XML attributes for special purposes, such as encoding metadata [RFC7952]. The exact syntax and semantics of such members are outside the scope of this document.

Representing YANG Data Types in XML Values
The type of the XML value in an instance of the leaf or leaf-list data node depends on the type of that data node, as specified in the following subsections.

Numeric Types
All numeric types (int8, int16, int32, uint8, uint16, uint32, int64, uint64, and decimal64) are represented as a text value conforming the to lexical representation for the type described in Section 9.2.1 of [RFC7950] and Section 9.3.1 of [RFC7950] .
Example: For the "int16" type

leaf-list foo {
  type int16;
}

the following is a valid XML-encoded instance:

<foo>4711</foo>    <!-- positive decimal value -->
<foo>-123</foo>    <!-- negative decimal value -->
<foo>0xf00f</foo>  <!-- positive hexadecimal value -->
<foo>-0xf</foo>    <!-- negative hexadecimal value -->
<foo>052</foo>     <!-- positive octal value -->
<foo>-052</foo>    <!-- negative octal value -->

The "string" Type
A "string" value is represented as character data conforming the to lexical representation for the type described in Section 9.4.1 of [RFC7950].
Example: For the "string" type

leaf-list foo {
  type string;
}

the following is a valid XML-encoded instance:

<foo>This string is all on one line.</foo>
<foo>This string is:
  - on more than one line.
  - contains tab characters.
</foo>

The "boolean" Type
A "boolean" value is represented as the corresponding literal name "true" or "false".
Example: For the "boolean" type

leaf-list foo {
  type boolean;
}

the following is a valid XML-encoded instance:

<foo>true</foo>
<foo>false</foo>

The "enumeration" Type
An "enumeration" value is represented as character data conforming the to lexical representation for the type described in Section 9.6.1 of [RFC7950].
Example: For the "enumeration" type

leaf-list foo {
  type enumeration {
    enum one;
    enum two;
    enum three;
  }
}

the following is a valid XML-encoded instance:

<foo>one</foo>
<foo>two</foo>
<foo>three</foo>

The "bits" Type
A "bits" value is represented as character data conforming the to lexical representation for the type described in Section 9.7.2 of [RFC7950].
Example: For the "bits" type

leaf-list foo {
  type bits {
     bit zero;
     bit one;
     bit two;
  }
}

the following is a valid XML-encoded instance:

<foo>zero</foo>
<foo>zero one</foo>
<foo>zero one two</foo>

The "binary" Type
A "binary" value is represented as character data conforming the to lexical representation for the type described in Section 9.8.2 of [RFC7950].
Example: For the "binary" type

leaf-list foo {
  type binary;
}

the following is a valid XML-encoded instance:

<foo>SGVsbG8gQm9iCg==</foo>  <!-- Hello Bob -->
<foo>SGVsbG8gQWxpY2UK</foo>  <!-- Hello Alice -->

The "leafref" Type
A "leafref" value is represented as character data conforming the to lexical representation for the type described in Section 9.9.4 of [RFC7950].
Example: For the "leafref" type

leaf-list status {
  type leafref {
    path "/my-leaf";      // assume current value is "up"
  }
}

leaf-list ifname {
  type leafref {
    path "/my-list/key";  // assume current key values are
  }                       // "eth0", "eth1", and "eth2"
}

leaf-list color {
  type leafref {
    path "/my-leaf-list";  // assume current list values are
  }                        // "red", "green", and "blue"
}

the following is valid XML-encoded instance data:

<status>up</status>

<ifname>eth0</ifname>
<ifname>eth1</ifname>
<ifname>eth2</ifname>

<color>red</color>
<color>green</color>
<color>blue</color>

The "identityref" Type
A "identityref" value is represented as character data conforming the to lexical representation for the type described in Section 9.10.3 of [RFC7950].
Example: For the "identityref" type

identity symmetric-key-algs {
  description
    "Base identity used to identify symmetric-key crypto
     algorithms.";
  }

identity blowfish {
  base symmetric-key;
  description
    "Identity used to identify the 'blowfish' algorithm.";
  }
}

identity aes {
  base symmetric-key;
  description
    "Identity used to identify the 'aes' algorithm.";
  }
}

leaf-list foo {
  type identityref {
    base symmetric-key-algs;
  }
}

the following is a valid XML-encoded instance:

<foo>aes</foo>
<foo>blowfish</foo>

Note that, the example above uses the default namespace, and hence the identities are not prefixed.

The "empty" Type
An "empty" value is represented as an empty XML element.
Example: For the "empty" type

leaf foo {
  type empty;
}

the following is a valid XML-encoded instance:

<foo/>

The "union" Type
A "union" value is represented as character data conforming the to lexical representation for the type described in Section 9.12.2 of [RFC7950].
Example: For the "union" type

leaf-list foo {
  type union {
    type int32;
    type enumeration {
      enum "unbounded";
    }
  }
}

the following is a valid XML-encoded instance:

<foo>16</foo>
<foo>32</foo>
<foo>64</foo>
<foo>unbounded</foo>

The "instance-identifier" Type
A "instance-identifier" value is represented as character data conforming the to lexical representation for the type described in Section 9.13.2 of [RFC7950].
Example: For the "instance-identifier" type

leaf-list foo {
  type instance-identifier;
}

the following is a valid XML-encoded instance:

<foo>/ex:system/ex:services/ex:ssh</foo>
<foo>/ex:system/ex:services/ex:ssh/ex:port</foo>
<foo>/ex:system/ex:user[ex:name='fred']</foo>
<foo>/ex:system/ex:user[ex:name='fred']/ex:type</foo>
<foo>/ex:system/ex:server[ex:ip='192.0.2.1'][ex:port='80']</foo>
<foo>/ex:system/ex:service[ex:name='foo'][ex:enabled='']</foo>
<foo>/ex:system/ex:services/ex:ssh/ex:cipher[.='blowfish-cbc']</foo>
<foo>/ex:stats/ex:port[3]</foo>

IANA Considerations
None.

Security Considerations
This document defines an encoding for data modeled in the YANG data modeling language. As such, it doesn't contribute any new security issues beyond those discussed in Section 17 of [RFC7950].
This document defines no mechanisms for signing and encrypting data modeled with YANG. Under normal circumstances, data security and integrity are guaranteed by the management protocol in use, such as NETCONF [RFC6241] or RESTCONF [RFC8040]. If this is not the case, external mechanisms, such as Public-Key Cryptography Standards (PKCS) #7 [RFC2315], need to be considered.
XML processing is rather different from JSON, and XML parsers may thus suffer from different types of vulnerabilities than their JSON counterparts. To minimize these new security risks, software on the receiving side SHOULD reject all messages that do not comply with the rules of this document and reply with an appropriate error message to the sender.

Normative References
[XML]

Extensible Markup Language (XML) 1.0 (Fifth Edition)
Tim Bray
Jean Paoli
Michael Sperberg-McQueen
Eve Maler
Francois Yergeau
26 November 2008
W3C Recommendation REC-xml-20081126

Informative References
[RFC7950]
[RFC2119]
[RFC8174]
[RFC6020]
[RFC7951]
[RFC7952]
[RFC6241]
[RFC8040]
[RFC2315]

Acknowledgements
Substantial amounts of text in this document was copied from [RFC7950] and [RFC7951]. The authors wish to thank Martin Björklund and Ladislav Lhotka for authoring RFC 7950 and RFC 7951, respectively.