TOC 
NETMODL. Lhotka
Internet-DraftCESNET
Intended status: InformationalJuly 06, 2008
Expires: January 7, 2009 


Mapping of YANG to DSDL
draft-lhotka-yang-dsdl-map-00

Status of this Memo

By submitting this Internet-Draft, each author represents that any applicable patent or other IPR claims of which he or she is aware have been or will be disclosed, and any of which he or she becomes aware will be disclosed, in accordance with Section 6 of BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF), its areas, and its working groups. Note that other groups may also distribute working documents as Internet-Drafts.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as “work in progress.”

The list of current Internet-Drafts can be accessed at http://www.ietf.org/ietf/1id-abstracts.txt.

The list of Internet-Draft Shadow Directories can be accessed at http://www.ietf.org/shadow.html.

This Internet-Draft will expire on January 7, 2009.

Abstract

This draft describes the algorithm and rules for mapping data models expressed in the YANG language to Document Schema Definition Languages (DSDL) with additional annotations.



Table of Contents

1.  Introduction
2.  Overview of the Mapping Algorithm
    2.1.  Optional Content
3.  Schema Languages
4.  Design Considerations
    4.1.  Modularity
    4.2.  Granularity
    4.3.  Mangled Names of RELAX NG Named Patterns
5.  Open Issues
    5.1.  No Root or Multiple Root Nodes
    5.2.  The extension Statement
    5.3.  The rpc and notification statements
    5.4.  The augment Statement
6.  Mapping Rules for YANG Statements
    6.1.  The anyxml Statement
    6.2.  The argument Statement
    6.3.  The augment Statement
    6.4.  The belongs-to Statement
    6.5.  The bit Statement
    6.6.  The case Statement
    6.7.  The choice Statement
    6.8.  The config Statement
    6.9.  The contact Statement
    6.10.  The container Statement
    6.11.  The default Statement
    6.12.  The description Statement
    6.13.  The enum Statement
    6.14.  The error-app-tag Statement
    6.15.  The error-message Statement
    6.16.  The extension Statement
    6.17.  The grouping Statement
    6.18.  The import Statement
    6.19.  The include Statement
    6.20.  The input Statement
    6.21.  The key Statement
    6.22.  The leaf Statement
    6.23.  The leaf-list Statement
    6.24.  The length Statement
    6.25.  The list Statement
    6.26.  The mandatory Statement
    6.27.  The max-elements Statement
    6.28.  The min-elements Statement
    6.29.  The module Statement
    6.30.  The must Statement
    6.31.  The namespace Statement
    6.32.  The notification Statement
    6.33.  The ordered-by Statement
    6.34.  The organization Statement
    6.35.  The output Statement
    6.36.  The path Statement
    6.37.  The pattern Statement
    6.38.  The position Statement
    6.39.  The prefix Statement
    6.40.  The presence Statement
    6.41.  The range Statement
    6.42.  The reference Statement
    6.43.  The revision Statement
    6.44.  The rpc Statement
    6.45.  The status Statement
    6.46.  The submodule Statement
    6.47.  The type Statement
        6.47.1.  The empty Type
        6.47.2.  The boolean and binary Types
        6.47.3.  The instance identifier Type
        6.47.4.  The bits Type
        6.47.5.  The enumeration and union Types
        6.47.6.  The keyref type
        6.47.7.  The numeric Types
        6.47.8.  The string Type
    6.48.  The typedef Statement
    6.49.  The unique Statement
    6.50.  The units Statement
    6.51.  The uses Statement
    6.52.  The value Statement
    6.53.  The when Statement
    6.54.  The yang-version Statement
    6.55.  The yin-element Statement
7.  References
Appendix A.  Translation of the DHCP Data Model
    A.1.  XML Syntax
    A.2.  Compact Syntax
§  Author's Address
§  Intellectual Property and Copyright Statements




 TOC 

1.  Introduction

The NETMOD working group complements the results of the NETCONF WG by addressing the data modeling issues. The major item in the NETMOD charter is a new data modeling language called YANG [YANG] (Bjorklund, M., Ed., “YANG - A data modeling language for NETCONF,” May 2008.). This language, being based on SMIng [RFC3216] (Elliott, C., Harrington, D., Jason, J., Schoenwaelder, J., Strauss, F., and W. Weiss, “SMIng Objectives,” December 2001.), builds on the experience of previous network management systems, most notably SNMP. However, since NETCONF chose eXtensible Markup Language [XML] (Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E., and F. Yergeau, “Extensible Markup Language (XML) 1.0 (Fourth Edition),” August 2006.) as the method for encoding both configuration data and their envelope (RPC layer), this work can and should also benefit from the body of knowledge, standards and software tools that have been established in the XML world. To this end, YANG also provides an alternative syntax called YIN that is able to represent the same information using XML. Despite the syntactic differences, the information models of YANG and YIN are virtually identical and conversion between YANG and YIN is straightforward in both directions.

However, having data models expressed in an XML syntax is not by itself sufficient for leveraging the existing XML know-how and tools. It is also necessary to convey the meaning of YANG models and present it in a way that the existing XML tools can understand. As a matter of fact, YANG/YIN can be viewed as yet another XML schema language. While there are several aspects that make YANG models specific to the NETCONF realm, for the most part the grammatical and semantic constraints that the models express can be equivalently represented in the general-purpose XML schema languages such as W3C XML Schema, RELAX NG, Schematron and others.

Therefore, one of the chartered items of the NETMOD WG is to define a mapping from YANG to the Document Schema Definition Languages (DSDL) that is being standardized as ISO/IEC 19757 [DSDL] (ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 1: Overview,” 11 2004.). The DSDL framework comprises a set of XML schema languages that address grammar rules, semantic constraints and other data modeling aspect but also, and more importantly, can do it in a coordinated and consistent way. While it is true that some DSDL parts have not been standardized yet and are still work in progress, the two crucial parts that the YANG -> DSDL mapping relies upon - RELAX NG and Schematron - already have the status of ISO/IEC Final Draft International Standard and are supported in a number of software tools.

This memo describes the algorithm for translating YANG data models to a schema (or multiple schemas) utilizing a subset of the DSDL schema languages together with a limited number of other annotations. The aim is to map as much structural, datatyping and semantic information as possible from YANG to DSDL with annotations so that the resulting schema(s) can be used with standard XML tools for a relatively comprehensive validation of the contents of configuration datastores. The most important schema language in the DSDL framework is RELAX NG [RNG] (ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 2: Regular-Grammar-Based Validation - RELAX NG,” 2002.). The specification of the mapping algorithm given below assumes that output of RELAX NG uses the XML syntax. However, RELAX NG compact syntax [RNG‑CS] (Clark, J., Ed., “RELAX NG Compact Syntax,” November 2002.) is often the preferred form for perusal by human readers. A secondary goal therefore is to guarantee a reasonable level of readability of the resulting RELAX NG in the compact syntax as well, even if multiple embedded annotation types are used.

In the text, we use the following typographic conventions:



 TOC 

2.  Overview of the Mapping Algorithm

The mapping algorithm assumes input in the form of a tree data structure representing a valid YANG module, henceforth denoted as the "YANG tree". Each node in the YANG tree is a data structure that corresponds to a single YANG statement. The node records the essential parameters of the statement (keyword, argument string) and keeps a pointer to the parent statement and a list of substatements. It is also assumed that the algorithm has access, perhaps on demand, to the parsed form of all YANG modules that the module imports (transitively).

The algorithm recursively traverses the YANG tree in preorder and constructs one or more XML trees for each of the DSDL schema languages that the algorithm generates (see Section 3 (Schema Languages)). In parallel, it keeps a pointer to the current position in each of the schema trees where new XML fragments corresponding to YANG statements get attached.

The resulting schema(s) may be internally represented in the form of a Document Object Model (DOM) or any other framework for creating and manipulating moderately sized XML trees.

An implementation of the mapping algorithm MUST provide the resulting schema(s) in at least one of the following forms:

  1. A set of separate schemas, typically in different disk files, one for each DSDL schema language. Non-DSDL annotations MUST be attached to the RELAX NG schema.
  2. A single RELAX NG schema with elements and attributes of the remaining DSDL schema languages and other annotations.

The first form is essentially what the DSDL standard [DSDL] (ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 1: Overview,” 11 2004.) expects and can be readily used with existing tools. The advantage of the second form is a more concise representation and better comprehensibility.

Note that non-DSDL annotations are always embedded in the RELAX NG schema.

An implementation SHOULD also allow the user to select a subset of schema languages and annotation types that are used for output. For example, a user might want to select pure RELAX NG without any annotations and still obtain a schema that is reasonably usable for validation.



 TOC 

2.1.  Optional Content

In YANG, all leaf nodes are optional unless they contain substatement

mandatory true;

or unless they are declared as list keys.

Lists or leaf-lists are optional unless they contain 'min-elements' substatement with argument value greater than zero.

YANG specification allows non-presence containers to be be omitted if they are empty. Containers with the 'presence' substatement are always optional since their presence or absence carries specific information.

Putting it all together, we get the following recursive rule for containers:

A container is optional if and only if at least one of the following conditions holds:

  1. it is a container with presence;
  2. none of its descendant leaf nodes is mandatory or, if such a leaf exists, it is enclosed in an intervening container with presence;
  3. none of its descendant list or leaf-list nodes has 'min-elements' substatement with argument value greater than zero or, if such a list or leaf-list exists, it is enclosed in an intervening container with presence.

In RELAX NG, all elements that are optional must be explicitly wrapped in the <optional> element.

Therefore, the mapping algorithm MUST be able to determine whether a YANG node is optional and if so, insert the <optional> element in the RELAX NG schema.



 TOC 

3.  Schema Languages

The mapping algorithm uses the following schema languages and annotation types:

If the YANG module contains no schema tree - for example, if it contains only definitions of grouping and typedefs - then the resulting RELAX NG schema SHOULD NOT have a <start> element.

If an implementation generates multiple DSDL schemas (output alternative 1 in Section 2 (Overview of the Mapping Algorithm)), then all such schemas MUST be valid according to the current DSDL standards. However, if the output form is a single annotated RELAX NG schema (output alternative 2 in Section 2 (Overview of the Mapping Algorithm)), certain parts of the annotating DSDL schema rules MAY be omitted, provided that the corresponding information can be unambiguously inferred, typically from the location of the annotating elements within the RELAX NG tree.

For example, consider the following YANG snippet:

module dhcp {
  ...
  container dhcp {
    ...
    leaf max-lease-time { ... };
    leaf default-lease-time {
      ...
      must '$this <= ../max-lease-time' {
        error-message
          "default-lease-time must be less than max-lease-time";
      }
      default 600;
    }
    ...
  }
  ...
}

If multiple schemas are generated, in this case RELAX NG, Schematron and DSRL, the 'must' statement shall be mapped to the following Schematron fragment:

<sch:pattern>
  <sch:rule context="/dhcp/default-lease-time"
    <sch:assert test=". &lt;= ../max-lease-time">
      default-lease-time must be less than max-lease-time
    </sch:assert>
  </sch:rule>
<sch:pattern>

Similarly, the 'default' statement results in the following DSRL fragment:

<dsrl:element-map>
  <dsrl:within>/dhcp</dsrl:within>
  <dsrl:name>default-lease-time</dsrl:name>
  <dsrl:default-content>600</dsrl:default-content>
<dsrl:element-map>

In both the Schematron and DSRL fragments, the context for the rules is explicitly specified by means of an XPath expression. If we insert these rules as annotations into the RELAX NG schema, the context is implicitly defined by the location of the rules with the RELAX NG schema. Therefore, the resulting RELAX NG schema fragment can be only

<element name="default-lease-time">
  ...
  <sch:assert test=". <= ../max-lease-time">
    The default-lease-time must be less than max-lease-time
  </sch:assert>
  <dsrl:default-content>600</dsrl:default-content>
</element>


 TOC 

4.  Design Considerations

This section describes the general principles and conventions used by the mapping algorithm.



 TOC 

4.1.  Modularity

Both YANG and RELAX NG offer means for modularity, i.e., splitting the contents into separate modules (schemas) and combining or reusing them in various ways. However, the approaches taken by YANG and RELAX NG differ. Modularity in RELAX NG is intended more for ad hoc combinations of a small number of schemas whereas YANG assumes a large set of modules similar to SNMP MIBs. In particular, RELAX NG uses a single flat namespace for all named patterns, be they local or imported, while every YANG module has its unique namespace and symbols imported by other modules remain in the namespace of their original module. Consequently, multiple YANG groupings and typedefs defined in different modules can have the same (local) identifier but still be used together in another module, but in RELAX NG this would mean a name conflict.

Therefore, the design decision for the mapping algorithm was to collect all contents in a single DSDL module even if in YANG it is distributed in several modules. Translations of foreign groupings and typedefs are installed in the importing module with appropriately mangled names - but only if they are really used by the importing module.

On the other hand, YANG submodules share the same namespace with the modules they belong to, so their modular structure can be retained in RELAX NG by using the <include> element.



 TOC 

4.2.  Granularity

RELAX NG supports different styles of structuring the schema: One extreme, often called "Russian Doll", specifies the structure of an XML instance document in a single schema. The other extreme, the flat style, is similar to the original Data Type Definition (DTD) schema language - every XML element is introduced inside a new named pattern. In practice, some compromise between the two extremes is usually chosen.

YANG in principle supports both styles, too, but in most cases the modules are organized in a way that's closer to the "Russian Doll" style, which provides a better insight into the structure of the configuration data. Groupings are usually defined only for subtrees that are prepared for reuse via the 'uses' statement. In contrast, RELAX NG schemas tend to be much flatter, because finer granularity is in RELAX NG also needed for extensibility of the schemas - it is only possible to replace or modify schema fragments that are factored out as named patterns. For YANG this is not an issue since its 'augment' statement can delve, by using path expressions, into arbitrary depths of existing structures.

We argue in Section 5.4 (The augment Statement) that is is in general not feasible to map YANG extension mechanisms to those of RELAX NG. For this reason, the mapping keeps the granularity of the original YANG data model: definitions of named patterns in the resulting RELAX NG schema have direct counterparts in YANG groupings and definitions of complex types.



 TOC 

4.3.  Mangled Names of RELAX NG Named Patterns

YANG typedefs and groupings may appear in all levels of the module hierarchy and are subject to lexical scoping. Moreover, top-level symbols from external modules are imported as qualified names consisting of the external module namespace and the name of the symbol. In contrast, named patterns in RELAX NG (both local and imported) share the same namespace and their definitions may only appear at the top level of the RELAX NG schema as children of the <grammar> element. Consequently, whenever YANG groupings and typedefs are translated into RELAX NG named pattern definitions, their MUST be disambiguated in order to avoid naming conflicts. The following name mangling procedure is suggested:

For example, YANG content

import "inet-types" {
  prefix "inet";
}
grouping "grp1" {
  leaf "void" {
    type "empty";
  }
}
container "cont" {
  grouping "grp2" {
    leaf "address" {
      type "inet:ip-address";
    }
  }
  uses "grp1";
  uses "grp2";
}

would result in the following definitions of RELAX NG named patterns:

<define name="__grp1">
  <optional>
    <element name="void">
      <empty/>
    </element>
  </optional>
</define>

<define name="__cont__grp2">
  <element name="address">
    <ref name="inet-types__ip-address"/>
  </element>
</define>

<define name="inet-types__ip-address">
  ...
</define>


 TOC 

5.  Open Issues

This section collects open issues that need further discussion within the NETMOD WG.



 TOC 

5.1.  No Root or Multiple Root Nodes

Well-formed XML documents must have exactly one root element (cf. [XML] (Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E., and F. Yergeau, “Extensible Markup Language (XML) 1.0 (Fourth Edition),” August 2006.), Section 2.1). In contrast, YANG data models may also allow multiple root nodes or no root at all. Consequently, it is impossible to translate such data models to a valid RELAX NG schema.

For multiple roots, the YANG specification [YANG] (Bjorklund, M., Ed., “YANG - A data modeling language for NETCONF,” May 2008.) recommends in Section 5.1.1 to use an extra conceptual root node such as <data> or <config>. While it is possible to include such a conceptual node in the RELAX NG schema, it would likely become an annoyance for data models with a single root. Therefore, a general solution to the problem of multiple roots should be devised.

Section 3 (Schema Languages) specifies that the resulting RELAX NG schema should not have a <start> element if the original YANG model contains no explicit data tree. Strictly speaking, this leads to an invalid RELAX NG schema (cf. [RNG] (ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 2: Regular-Grammar-Based Validation - RELAX NG,” 2002.), Section 7.19) and some RELAX NG parsers indeed do complain about it. However, it is a common practice to prepare such "startless" RELAX NG schemas with definitions of reusable named patterns, see e.g., [Vli04] (van der Vlist, E., “RELAX NG,” 2004.), Chapter 10. It is thus probably no reason for concerns - it has to be understood that such schemas are not supposed to be used as stand-alone.

However, a YANG data model may also allow empty instance documents if all nodes are optional, as discussed in Section 2.1 (Optional Content). This leads to an invalid RELAX NG schema with the following <start> element:

<start>
  <optional>
    ...
  </optional>
</start>

The problems of no root or multiple root nodes can be solved by changing YANG specification in the sense that all instances of data models must be enclosed in a fixed and mandatory container, for example "netmod-data".



 TOC 

5.2.  The extension Statement

The 'extension' statement can be used for declaring new statements for the YANG language itself. Their keywords are qualified names carrying the namespace name of the module that defines them. It is not difficult to insert such extensions into the resulting RELAX NG schema because RELAX NG allows elements and attributes from different namespaces to be freely intermixed with its own elements and attributes. A straightforward option for translating such extensions is to generate the YIN representation of the extension (utilizing the 'argument' substatement of the 'extension' statement) and attach this XML subtree at the corresponding position in the RELAX NG schema tree.

It is not clear though whether it is sensible to blindly copy such extensions without knowing their semantics. For example, if the extension utilizes paths referring to the YANG model tree, this paths may become incorrect when used as XPaths in the RELAX NG tree.



 TOC 

5.3.  The rpc and notification statements

In YANG, the 'rpc' statement declares the signature of a NETCONF RPC operation - method names, input and output parameters. With this information, one can create a pair of schemas for validating protocol data units with NETCONF <rpc> and <rpc-reply> messages, but these schemas would be different from the data model for the entire configuration datastore that the rest of the YANG module is about. It is therefore not very clear whether and how to use the 'rpc' statement in the mapping algorithm.

A completely analogical situation is with the 'notification' statement that defines a NETCONF notification.



 TOC 

5.4.  The augment Statement

For the translation to DSDL schemas, the most difficult YANG concept turns out to be the 'augment' statement. This is partly because it in fact serves several different purposes:

At the top level of the YANG module hierarchy, the 'augment' statement may be used to add new nodes to a foreign schema that is defined in another module, which is imported in the module where the 'augment' statement appears (see the examples in Section 7.5.14 of [YANG] (Bjorklund, M., Ed., “YANG - A data modeling language for NETCONF,” May 2008.)). In the context of the augmenting module, this 'augment' has no effect since the 'import' statement does not actually import any part of the foreign schema tree, just the top-level groupings and typedefs. Consequently, the algorithm that maps a single YANG module to DSDL should probably ignore it.

Probably the most common use of the 'augment' statement is for applying a grouping with additional content that is added at a specified location inside the grouping, for example

grouping "def-coll" {
  container collector {
    leaf address { ... }
    leaf port { ... }
  }
}
...
container export {
  uses "def-coll";
  augment collector {
    leaf protocol { ... }
  }
}

An minor difficulty here is that the relation between the 'augment' statement and the corresponding 'uses' is only implicit. If there are multiple 'uses' statements, one first has to figure out which of them the 'augment' applies to, i.e., by inspecting all the groupings and finding the one that has "collector" as its top node.

In RELAX NG, a similar effect can be achieved by combining pattern definitions, schematically

<define name="def-coll">
  ...original content...
</define>
...
<define name="def-coll" combine="interleave">
  ...added content...
</define>

However, there are three notable differences:

As a result, the only way for translating 'uses' with 'augment' to RELAX NG seems to be to copy the grouping content to the place where it is used and augment it there.

Finally, another practical motivation for using 'augment' may be its 'when' substatement, which allows for conditional content, for example

augment "." {
  when "ifType='wireless'" {
    ...added content...
  }
}

In DSDL schema languages, there is no direct way for specifying conditional content, but it could be simulated by adding Schematron rules that report an error if any part of the conditional content is present and the when condition is not satisfied.

In author's opinion, the problems of the 'augment' statement mentioned above can be mitigated by making the following changes to YANG:



 TOC 

6.  Mapping Rules for YANG Statements

This section describes in each of its subsections the mapping procedure for one YANG statement, as it is currently implemented in the YANG->DSDL translator plug-in for the pyang tool. It is a work in progress and the implementation is open for discussion and changes.

In accord with the description of the mapping algorithm in Section 2 (Overview of the Mapping Algorithm), we assume the following context:

Throughout this section, we use qualified names for all XML elements. The mapping of prefixes to namespace URIs is shown in Table 1.



PrefixNamespace URI
a http://relaxng.org/ns/compatibility/annotations/1.0
dc http://purl.org/dc/terms
dsrl http://purl.oclc.org/dsdl/dsrl
nm urn:ietf:params:xml:ns:netmod:dsdl-attrib:1
sch http://purl.oclc.org/dsdl/schematron

 Table 1 

In order to avoid unnecessary complications, this section describes the mapping algorithm for single-file output, i.e., alternative 2 in Section 2 (Overview of the Mapping Algorithm).



 TOC 

6.1.  The anyxml Statement

At the first occurrence of this statement, the following pattern definition is added to the RELAX NG schema (cf. [Vli04] (van der Vlist, E., “RELAX NG,” 2004.), p. 172):

<define name="__anyxml__">
  <zeroOrMore>
    <choice>
      <attribute>
        <anyName/>
      </attribute>
      <element>
        <anyName/>
        <ref name="__anyxml__"/>
      </element>
      <text/>
    </choice>
  </zeroOrMore>
</define>

Reference to this pattern is then inserted for all 'anyxml' statements.



 TOC 

6.2.  The argument Statement

Not implemented, see Section 5.2 (The extension Statement).



 TOC 

6.3.  The augment Statement

Not implemented, see Section 5.4 (The augment Statement).



 TOC 

6.4.  The belongs-to Statement

Insert Dublin Core metadata term <dc:isPartOf>.



 TOC 

6.5.  The bit Statement

Handled within the "bits" type, see Section 6.47.4 (The bits Type).



 TOC 

6.6.  The case Statement

Insert <rng:group> element and handle all substatements.



 TOC 

6.7.  The choice Statement

Insert <rng:choice> element and handle all substatements.



 TOC 

6.8.  The config Statement

Attach attribute @nm:config to the parent element and use stmt.arg as its value.



 TOC 

6.9.  The contact Statement

Insert Dublin Core metadata term <dc:contributor> and use stmt.arg as its content.



 TOC 

6.10.  The container Statement

Using the procedure outlined in Section 2.1 (Optional Content), determine whether the container is optional, and if so, insert the <rng:optional> element and make it the new parent element.

Then insert <rng:element> element at the current position and use stmt.arg as the value of its @name attribute.

Then handle all substatements.



 TOC 

6.11.  The default Statement

Insert element <dsrl:default-content> with stmt.arg as its content.



 TOC 

6.12.  The description Statement

If the statement is at the module top level, insert Dublin Core metadata term <dc:description> and use stmt.arg as its content.

Otherwise, insert DTD compatibility element <a:documentation>. In order to get properly formatted in the RELAX NG compact syntax, this element must be inserted as the first child of the parent element.



 TOC 

6.13.  The enum Statement

Insert <rng:value> element and use stmt.arg as its content.

Then handle the 'status' substatement. Other substatements ('value', 'description' and 'reference') are ignored because the <rng:value> element cannot contain foreign elements, see [RNG] (ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 2: Regular-Grammar-Based Validation - RELAX NG,” 2002.), Section 6.



 TOC 

6.14.  The error-app-tag Statement

Not implemented.



 TOC 

6.15.  The error-message Statement

Handled only within the 'must' statement, see Section 6.30 (The must Statement). Ignored in other contexts.



 TOC 

6.16.  The extension Statement

Not implemented, see Section 5.2 (The extension Statement).



 TOC 

6.17.  The grouping Statement

Insert <rng:define> element and set the value of its @name attribute to stmt.arg with prepended full path, i.e., names of all ancestor nodes in the YANG schema tree separated by double underlines - see Section 4.3 (Mangled Names of RELAX NG Named Patterns).

Then handle all substatements.



 TOC 

6.18.  The import Statement

Ignored, as it is assumed that all imported modules are processed by the YANG parser and made available to the mapping algorithm.



 TOC 

6.19.  The include Statement

Insert <rng:include> and set the value of its @href attribute to stmt.arg concatenated with the file extension ".rng".



 TOC 

6.20.  The input Statement

Not implemented, see Section 5.3 (The rpc and notification statements).



 TOC 

6.21.  The key Statement

Attach attribute @nm:key to the parent element and use stmt.arg as its value.



 TOC 

6.22.  The leaf Statement

Unless there is the "mandatory true;" substatement or unless an enclosing list declares this leaf among its keys, insert <rng:optional> element and make it the new parent element.

Then insert <rng:element> element and use stmt.arg as the value of its @name attribute.

Then handle all substatements.



 TOC 

6.23.  The leaf-list Statement

If there is a 'min-elements' substatement with argument value greater than zero, insert <rng:oneOrMore> and make it the new parent element. Otherwise insert <rng:zeroOrMore> and make it the new parent element.

Then insert <rng:element> and use stmt.arg as its value. If there is a 'min-elements' substatement with argument value greater than zero, attach attribute @nm:min-elements to the <rng:element> element and use the argument of the 'min-elements' statement as its value. If there is a 'max-elements' substatement, attach attribute @nm:max-elements to the <rng:element> element and use the argument of the 'max-elements' statement as its value. If there is an 'ordered-by' substatement, attach attribute @nm:ordered-by to the <rng:element > element and use the argument of the 'ordered-by' statement as its value.

Then handle all remaining substatements.



 TOC 

6.24.  The length Statement

Handled within the "string" type, see Section 6.47.8 (The string Type).



 TOC 

6.25.  The list Statement

Handled exactly as the 'leaf-list' statement, see Section 6.23 (The leaf-list Statement).



 TOC 

6.26.  The mandatory Statement

Handled within the 'leaf' statement, see Section 6.22 (The leaf Statement).



 TOC 

6.27.  The max-elements Statement

Handled within 'leaf-list' or 'list' statements, see Section 6.23 (The leaf-list Statement).



 TOC 

6.28.  The min-elements Statement

Handled within 'leaf-list' or 'list' statements, see Section 6.23 (The leaf-list Statement).



 TOC 

6.29.  The module Statement

This statement is not specifically handled. The mapping algorithm starts with its substatements.



 TOC 

6.30.  The must Statement

Insert <sch:assert> element. The value of its @test attribute is set to stmt.arg in which all occurrences of the string "$this" are replaced by "." (single dot). If there is an 'error-message' substatement, its argument value is used as the content of <sch:assert>, otherwise the <sch:assert> element is empty.



 TOC 

6.31.  The namespace Statement

Attach @ns attribute to the <rng:grammar> element (the root of the RELAX NG schema) and use stmt.arg as its value.



 TOC 

6.32.  The notification Statement

Not implemented, see Section 5.3 (The rpc and notification statements).



 TOC 

6.33.  The ordered-by Statement

Handled within 'leaf-list' and 'list' statements, see Section 6.23 (The leaf-list Statement).



 TOC 

6.34.  The organization Statement

Insert Dublin Core metadata term <dc:creator> and use stmt.arg as its content.



 TOC 

6.35.  The output Statement

Not implemented, see Section 5.3 (The rpc and notification statements).



 TOC 

6.36.  The path Statement

Handled within "keyref" type, see Section 6.47.6 (The keyref type).



 TOC 

6.37.  The pattern Statement

Handled within "string" type, see Section 6.47.8 (The string Type).



 TOC 

6.38.  The position Statement

Not implemented.



 TOC 

6.39.  The prefix Statement

Not implemented. In RELAX NG, the elements of the target namespace are unprefixed.



 TOC 

6.40.  The presence Statement

Handled within 'container' statement, see Section 6.10 (The container Statement) and also Section 2.1 (Optional Content).



 TOC 

6.41.  The range Statement

Handled within numeric types, see Section 6.47.7 (The numeric Types).



 TOC 

6.42.  The reference Statement

If this statement is at module top level, insert Dublin Core metadata term <dc:BibliographicResource> and use stmt.arg as its content.

Otherwise insert <a:documentation> and use stmt.arg as its content. Within parent element children, insert it as the last of <a:documentation> elements (i.e., after translations of 'description' statements), but before any other subelements.



 TOC 

6.43.  The revision Statement

Insert Dublin Core metadata term <dc:issued> and use stmt.arg as its content.



 TOC 

6.44.  The rpc Statement

Not implemented, see Section 5.3 (The rpc and notification statements).



 TOC 

6.45.  The status Statement

Attach attribute @nm:status to the parent element and use stmt.arg as its value.



 TOC 

6.46.  The submodule Statement

This statement is not specifically handled. The mapping algorithm starts with its substatements.



 TOC 

6.47.  The type Statement

References to derived types are handled in the same way as references to groupings via the 'uses' statement (Section 6.51 (The uses Statement)): <rng:ref> element is inserted with a properly mangled name and definitions of derived types are copied from external modules as necessary.

Most YANG built-in types have an equivalent in the XSD datatype library [XSD‑D] (Biron, P. and A. Malhotra, “XML Schema Part 2: Datatypes Second Edition,” October 2004.) as shown in Table 2 (Selected datatypes from the W3C XML Schema Type Library).



YANG typeXSD typeMeaning
int8 byte 8-bit integer value
int16 short 16-bit integer value
int32 int 32-bit integer value
int64 long 64-bit integer value
uint8 unsignedByte 8-bit unsigned integer value
uint16 unsignedShort 16-bit unsigned integer value
uint32 unsignedInt 32-bit unsigned integer value
uint64 unsignedLong 64-bit unsigned integer value
float32 float 32-bit IEEE floating-point value
float64 double 64-bit IEEE floating-point value
string string character string
boolean boolean "true" or "false"
binary base64Binary binary data in base64 encoding

 Table 2: Selected datatypes from the W3C XML Schema Type Library 

Details about the mapping of individual YANG built-in types are given in the following subsections.



 TOC 

6.47.1.  The empty Type

Insert empty <rng:empty> element.



 TOC 

6.47.2.  The boolean and binary Types

These two built-in types do not allow any restrictions and are mapped simply by inserting <rng:data> element whose @type attribute is set to stmt.arg mapped according to Table 2 (Selected datatypes from the W3C XML Schema Type Library).



 TOC 

6.47.3.  The instance identifier Type

This YANG built-in type has no equivalent in the XSD datatype library and is mapped to the RELAX NG "string" type:

<rng:data type="string"/>


 TOC 

6.47.4.  The bits Type

Insert <rng:list> element and insert under it for each 'bit' substatement the following XML fragment:

<rng:optional>
  <rng:value>bit_name</rng:value>
</rng:optional>

where bit_name is the name of the bit as found in the argument of the corresponding 'bit' statement.



 TOC 

6.47.5.  The enumeration and union Types

Insert <rng:choice> and handle all substatements.



 TOC 

6.47.6.  The keyref type

As there is no suitable counterpart for the YANG built-in "keyref" type in the XSD datatype library, this type is mapped to "string" by inserting <rng:data> element with @type attribute set to "string". In addition, <sch:assert> element is inserted as child of <rng:data,> which checks that a 'list' entry with the corresponding value of the key exists.



 TOC 

6.47.7.  The numeric Types

YANG built-in numeric types are "int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float32" and "float64". They are handled by inserting <rng:data> element with @type attribute set to stmt.arg mapped according to Table 2 (Selected datatypes from the W3C XML Schema Type Library).

All numeric types support the 'range' restriction, which is handled in the following way:

For example, the 'typedef' statement

typedef rt {
  type int32 {
    range "-6378..0|42|100..max";
  }
}

translates to the following RELAX NG fragment:

<rng:define name="__rt">
  <rng:choice>
    <rng:data type="int">
      <rng:param name="minInclusive">-6378</rng:param>
      <rng:param name="maxInclusive">0</rng:param>
    </rng:data>
    <rng:data type="int">
      <rng:param name="minInclusive">42</rng:param>
      <rng:param name="maxInclusive">42</rng:param>
    </rng:data>
    <rng:data type="int">
      <rng:param name="minInclusive">100</rng:param>
    </rng:data>
  </rng:choice>
</rng:define>


 TOC 

6.47.8.  The string Type

This type is mapped by inserting the <rng:data> element with the @type attribute set to "string".

For the 'pattern' restriction, insert <rng:param> element with @name attribute set to "pattern". The argument of the 'pattern' statement (regular expression) becomes the content of this element.

The 'length' restriction is handled in the same way as the 'range' restriction for the numeric types, with the additional twist that if the length expression has multiple parts, the "pattern" facet

<rng:param name="pattern">...</rng:param>

if there is any, must be repeated inside each copy of the <rng:data> element, i.e., for each length part.



 TOC 

6.48.  The typedef Statement

Handled exactly as the 'grouping' statement, see Section 6.17 (The grouping Statement).



 TOC 

6.49.  The unique Statement

Insert <sch:assert> element. Its test checks that no two list items (sibling elements) have the same combination of values of leafs listed in stmt.arg. The content of the <sch:assert> element, i.e., the error message, is formed by a concatenation of "Not unique: " and stmt.arg.



 TOC 

6.50.  The units Statement

Attach attribute @nm:units to the parent element and use stmt.arg as its value.



 TOC 

6.51.  The uses Statement

  1. Check whether the grouping that the statement refers to is defined in the same module that is being translated. If it is so, go to step 4.
  2. [the grouping is defined in another module] If the same grouping has been already used in the module that is being translated, go to step 4.
  3. [first use of an external grouping] Copy the grouping definition from the external module and install its translation according to Section 6.17 (The grouping Statement) with a properly mangled name (see Section 4.3 (Mangled Names of RELAX NG Named Patterns)).
  4. Insert <rng:ref> element and set its @name attribute to stmt.arg after performing the name mangling procedure described in Section 4.3 (Mangled Names of RELAX NG Named Patterns), taking into account whether the grouping is local or external.

Handling of substatements, and in particular the refinement statements, is not implemented yet.



 TOC 

6.52.  The value Statement

Not implemented.



 TOC 

6.53.  The when Statement

Not implemented, see Section 5.4 (The augment Statement).



 TOC 

6.54.  The yang-version Statement

Not implemented. Its stmt.arg may be checked by the mapping algorithm in order to make sure that the module is compatible.



 TOC 

6.55.  The yin-element Statement

Not implemented, see Section 5.2 (The extension Statement).



 TOC 

7. References

[XML] Bray, T., Paoli, J., Sperberg-McQueen, C., Maler, E., and F. Yergeau, “Extensible Markup Language (XML) 1.0 (Fourth Edition),” World Wide Web Consortium Recommendation REC-xml-20060816, August 2006 (HTML).
[XSD-D] Biron, P. and A. Malhotra, “XML Schema Part 2: Datatypes Second Edition,” World Wide Web Consortium Recommendation REC-xmlschema-2-20041028, October 2004 (HTML).
[YANG] Bjorklund, M., Ed., “YANG - A data modeling language for NETCONF,” draft-ietf-netmod-yang-00 (work in progress), May 2008 (TXT).
[RNG-CS] Clark, J., Ed., “RELAX NG Compact Syntax,” OASIS Committee Specification 21 November 2002, November 2002.
[RNG-DTD] Clark, J., Ed. and M. Murata, Ed., “RELAX NG DTD Compatibility,” OASIS Committee Specification 3 December 2001, December 2001.
[DCMT] DCMI, “DCMI Metadata Terms,” January 2008.
[RFC3216] Elliott, C., Harrington, D., Jason, J., Schoenwaelder, J., Strauss, F., and W. Weiss, “SMIng Objectives,” RFC 3216, December 2001 (TXT).
[DSDL] ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 1: Overview,” ISO/IEC 19757-1, 11 2004.
[RNG] ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 2: Regular-Grammar-Based Validation - RELAX NG,” ISO/IEC 19757-2, 2002.
[Schtrn] ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 3: Rule-Based Validation - Schematron,” ISO/IEC 19757-3, 2004.
[DSRL] ISO/IEC, “Document Schema Definition Languages (DSDL) - Part 8: Document Schema Renaming Language - DSRL,” ISO/IEC 19757-8, 2006.
[Vli04] van der Vlist, E., “RELAX NG,” O'Reilly , 2004.


 TOC 

Appendix A.  Translation of the DHCP Data Model

This appendix demonstrates output of the YANG->DSDL mapping algorithm applied to the "canonical" DHCP tutorial data model. It is presented as a single-file annotated RELAX NG schema (output alternative 1 in Section 2 (Overview of the Mapping Algorithm)).

Appendix A.1 (XML Syntax) shows the result of the mapping algorithm in the RELAX NG XML syntax and Appendix A.2 (Compact Syntax) the same in the compact syntax, which was obtained using the Trang tool.

The long regular expressions for IP addresses etc. would exceed the limit of 72 characters per line, so they were replaced by a dummy text. Other than that, the results of the automatic translations were not changed.



 TOC 

A.1.  XML Syntax

<?xml version="1.0" encoding="UTF-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
         xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
         xmlns:dc="http://purl.org/dc/terms"
         xmlns:dsrl="http://purl.oclc.org/dsdl/dsrl"
         xmlns:nm="urn:ietf:params:xml:ns:netmod:dsdl-attrib:1"
         xmlns:sch="http://purl.oclc.org/dsdl/schematron"
         datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
         ns="http://example.com/ns/dhcp">
  <dc:creator>yang-central.org</dc:creator>
  <dc:description>Partial data model for DHCP, based on the config of
  the ISC DHCP reference implementation.</dc:description>
  <dc:source>YANG module 'dhcp' (automatic translation)</dc:source>
  <start>
    <optional>
      <element name="dhcp">
        <a:documentation>configuration and operational parameters for
        a DHCP server.</a:documentation>
        <optional>
          <element name="max-lease-time" nm:units="seconds">
            <data type="unsignedInt"/>
            <dsrl:default-content>7200</dsrl:default-content>
          </element>
        </optional>
        <optional>
          <element name="default-lease-time" nm:units="seconds">
            <data type="unsignedInt"/>
            <sch:assert test=". &lt;= ../max-lease-time">The
            default-lease-time must be less than
            max-lease-time</sch:assert>
            <dsrl:default-content>600</dsrl:default-content>
          </element>
        </optional>
        <ref name="__subnet-list"/>
        <optional>
          <element name="shared-networks">
            <zeroOrMore>
              <element name="shared-network" nm:key="name">
                <element name="name">
                  <data type="string"/>
                </element>
                <ref name="__subnet-list"/>
              </element>
            </zeroOrMore>
          </element>
        </optional>
        <optional>
          <element name="status" nm:config="false">
            <zeroOrMore>
              <element name="leases" nm:key="address">
                <element name="address">
                  <ref name="inet-types__ip-address"/>
                </element>
                <optional>
                  <element name="starts">
                    <ref name="yang-types__date-and-time"/>
                  </element>
                </optional>
                <optional>
                  <element name="ends">
                    <ref name="yang-types__date-and-time"/>
                  </element>
                </optional>
                <optional>
                  <element name="hardware">
                    <optional>
                      <element name="type">
                        <choice>
                          <value>ethernet</value>
                          <value>token-ring</value>
                          <value>fddi</value>
                        </choice>
                      </element>
                    </optional>
                    <optional>
                      <element name="address">
                        <ref name="yang-types__phys-address"/>
                      </element>
                    </optional>
                  </element>
                </optional>
              </element>
            </zeroOrMore>
          </element>
        </optional>
      </element>
    </optional>
  </start>
  <define name="inet-types__ip-address">
    <choice>
      <ref name="inet-types__ipv4-address"/>
      <ref name="inet-types__ipv6-address"/>
    </choice>
  </define>
  <define name="inet-types__ipv4-address">
    <data type="string">
      <param name="pattern">... IPv4 address regexp ...</param>
    </data>
  </define>
  <define name="inet-types__ipv6-address">
    <data type="string">
      <param name="pattern">... IPv6 address regexp ...</param>
    </data>
  </define>
  <define name="yang-types__date-and-time">
    <data type="string">
      <param name="pattern">... date-and-time regexp ...</param>
    </data>
  </define>
  <define name="yang-types__phys-address">
    <data type="string"/>
  </define>
  <define name="__subnet-list">
    <a:documentation>A reusable list of subnets</a:documentation>
    <zeroOrMore>
      <element name="subnet" nm:key="net">
        <element name="net">
          <ref name="inet-types__ip-prefix"/>
        </element>
        <element name="range">
          <optional>
            <element name="dynamic-bootp">
              <a:documentation>Allows BOOTP clients to get addresses
              in this range</a:documentation>
              <empty/>
            </element>
          </optional>
          <element name="low">
            <ref name="inet-types__ip-address"/>
          </element>
          <element name="high">
            <ref name="inet-types__ip-address"/>
          </element>
        </element>
        <optional>
          <element name="dhcp-options">
            <a:documentation>
            Options in the DHCP protocol
            </a:documentation>
            <zeroOrMore nm:ordered-by="user">
              <element name="router">
                <a:documentation>
                See: RFC 2132, sec. 3.8
                </a:documentation>
                <ref name="inet-types__host"/>
              </element>
            </zeroOrMore>
            <optional>
              <element name="domain-name">
                <a:documentation>
                See: RFC 2132, sec. 3.17
                </a:documentation>
                <ref name="inet-types__domain-name"/>
              </element>
            </optional>
          </element>
        </optional>
        <optional>
          <element name="max-lease-time" nm:units="seconds">
            <data type="unsignedInt"/>
            <dsrl:default-content>7200</dsrl:default-content>
          </element>
        </optional>
      </element>
    </zeroOrMore>
  </define>
  <define name="inet-types__ip-prefix">
    <choice>
      <ref name="inet-types__ipv4-prefix"/>
      <ref name="inet-types__ipv6-prefix"/>
    </choice>
  </define>
  <define name="inet-types__ipv4-prefix">
    <data type="string">
      <param name="pattern">... IPv4 prefix regexp ...</param>
    </data>
  </define>
  <define name="inet-types__ipv6-prefix">
    <data type="string">
      <param name="pattern">... IPv6 prefix regexp ...</param>
    </data>
  </define>
  <define name="inet-types__host">
    <choice>
      <ref name="inet-types__ip-address"/>
      <ref name="inet-types__domain-name"/>
    </choice>
  </define>
  <define name="inet-types__domain-name">
    <data type="string">
      <param name="pattern">([\p{L}\p{N}]+\.)*[\p{L}\p{N}]</param>
    </data>
  </define>
</grammar>




 TOC 

A.2.  Compact Syntax

default namespace = "http://example.com/ns/dhcp"
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
namespace dc = "http://purl.org/dc/terms"
namespace dsrl = "http://purl.oclc.org/dsdl/dsrl"
namespace nm = "urn:ietf:params:xml:ns:netmod:dsdl-attrib:1"
namespace sch = "http://purl.oclc.org/dsdl/schematron"

dc:creator [ "yang-central.org" ]
dc:description [
  "Partial data model for DHCP, based on the config of\x{a}" ~
  "the ISC DHCP reference implementation."
]
dc:source [ "YANG module 'dhcp' (automatic translation)" ]
start =

  ## configuration and operational parameters for a DHCP server.
  element dhcp {
    [ nm:units = "seconds" ]
    element max-lease-time {
      xsd:unsignedInt >> dsrl:default-content [ "7200" ]
    }?,
    [ nm:units = "seconds" ]
    element default-lease-time {
      xsd:unsignedInt
      >> sch:assert [
           test = ". <= ../max-lease-time"
           "The default-lease-time must be less than max-lease-time"
         ]
      >> dsrl:default-content [ "600" ]
    }?,
    __subnet-list,
    element shared-networks {
      [ nm:key = "name" ]
      element shared-network {
        element name { xsd:string },
        __subnet-list
      }*
    }?,
    [ nm:config = "false" ]
    element status {
      [ nm:key = "address" ]
      element leases {
        element address { inet-types__ip-address },
        element starts { yang-types__date-and-time }?,
        element ends { yang-types__date-and-time }?,
        element hardware {
          element type { "ethernet" | "token-ring" | "fddi" }?,
          element address { yang-types__phys-address }?
        }?
      }*
    }?
  }?
inet-types__ip-address =
  inet-types__ipv4-address | inet-types__ipv6-address
inet-types__ipv4-address =
  xsd:string {
    pattern =
      "... IPv4 address regexp ..."
  }
inet-types__ipv6-address =
  xsd:string {
    pattern =
      "... IPv6 address regexp ..."
  }
yang-types__date-and-time =
  xsd:string {
    pattern =
      "... date-and-time regexp ..."
  }
yang-types__phys-address = xsd:string

## A reusable list of subnets
__subnet-list =
  [ nm:key = "net" ]
  element subnet {
    element net { inet-types__ip-prefix },
    element range {

      ## Allows BOOTP clients to get addresses in this range
      element dynamic-bootp { empty }?,
      element low { inet-types__ip-address },
      element high { inet-types__ip-address }
    },

    ## Options in the DHCP protocol
    element dhcp-options {
      [ nm:ordered-by = "user" ]
      (
       ## See: RFC 2132, sec. 3.8
       element router { inet-types__host }*),

      ## See: RFC 2132, sec. 3.17
      element domain-name { inet-types__domain-name }?
    }?,
    [ nm:units = "seconds" ]
    element max-lease-time {
      xsd:unsignedInt >> dsrl:default-content [ "7200" ]
    }?
  }*
inet-types__ip-prefix =
  inet-types__ipv4-prefix | inet-types__ipv6-prefix
inet-types__ipv4-prefix =
  xsd:string {
    pattern =
      "... IPv4 prefix regexp ..."
  }
inet-types__ipv6-prefix =
  xsd:string {
    pattern =
      "... IPv6 prefix regexp ..."
  }
inet-types__host = inet-types__ip-address | inet-types__domain-name
inet-types__domain-name =
  xsd:string { pattern = "([\p{L}\p{N}]+\.)*[\p{L}\p{N}]" }




 TOC 

Author's Address

  Ladislav Lhotka
  CESNET
Email:  lhotka@cesnet.cz


 TOC 

Full Copyright Statement

Intellectual Property