NRL to Schematron generator tutorial

Created by Adriana Alexandru


  1. Overview - purpose of document
  2. Resources
  3. Setup
  4. NRL to Schematron mapping explained
  5. Step by step example of building a NRL to Schematron generator
    1. Writing the test cases
    2. Writing the fixture
    3. Implementation of test cases
    4. NRL to Schematron generator implementation
  6. Download java source code of this example
  7. Limitations

Overview - purpose of document

This document is a guide to creating a NRL to Schematron generator and presents an end-to-end generator example and the reasoning behind it.


  1. NRL

  2. Resources for NRL can be found on the NRL Sourceforge page.

  3. Schematron

  4. Looking at this very useful overview of how Schematron works might be a good start. Resources for Schematron can be found on the official website of Schematron and a Schematron tutorial is also available.

  5. Concordion

  6. The Concordion official website offers a very comprehensive tutorial about how Concordion works.


  1. Software

  2. The software programs used in this tutorial are Eclipse version 3.6.1 and Oxygen XML Editor.

    The NRL parser and Concordion need to be installed before starting. Dependencies are managed with Maven.

    Since the NRL parser is developed in Java this tutorial uses Java to build a NRL to Schematron generator example.

  3. Files management

  4. Oxygen XML Editor is used in order to visualise the XML schema model when creating the NRL rules examples that are mapped to Schematron rules. It is useful to build the Oxygen XML Editor project in the Eclipse project in order to easily manage all the files. Below two screenshots show how files were organised for this tutorial in Eclipse and Oxygen XML Editor.

    Eclipse screenshot Oxygen XML Editor screenshot
    Eclipse - managing files Oxygen XML Editor - managing files

    Note that the models, rules and test-data folders in the Eclipse navigation screenshot that are the same with the Oxygen XML Editor folders.

    The src/com/m20/absolute/schematron/ast/xpath package contains the classes relevant to translating NRL language constraints to XPath. XPath is relevant because the assert element in Schematron contains an attribute test whose value is expresssed in XPath.

    The src/com/m20/absolute/schematron/ast package contains the classes used to translate NRL rules into Schematron rules.

    For the purpose of easy file management the folder in which Concordion outputs the result html file has been changed to test-output/com/m20/absolute/schematron and the file is called NRLSchematronGenerator.html. This file displays the Concordion test cases and whether they pass or fail and works in the same way as it is explained in the Concordion tutorial.

    The testsrc/com/m20/absolute/schematron/css package contains the file which represents the Concordion fixture which is also explained in the same Concordion tutorial. The NRLSchematronGenerator.html within this package is the file in which the test cases are written.

NRL to Schematron mapping explained

The mapping examples displayed below use the XML Schema model displayed below in a visual manner as a screenshot via Oxygen XML Editor.

NRL works on the basis of types rather than elements. So when referring to Trade for example, Trade is a type, and same with Amount. Because the Trade type is used in this tutorial it is also expanded and displayed visually below. Please ignore the highlights for now.

XML schema model Trade type expanded
Screenshot of XML schema model. Screenshot of Trade type expanded.

The easiest way to learn how NRL is mapped to Schematron is to look at an example. Since NRL rules map to a model, the XML schema is used to create a XML file model on which the NRL rule will be created agaist.

The table displayed below shows how two NRL rules are mapped to Schematron.

Example files NRL Schematron Comments
NRL rule
Schematron rule
Rule Set "Expressions"
Context: Trade
Validation Rule "r1"
numberOfLegs = 6
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="">
  <pattern name="Expressions">
      <rule context="//trade" id="r1">
          <assert test="numberOfLegs = 6" />
  • It is straightforward to observe that:
    • The NRL Rule Set is mapped to a pattern element in Schematron.
    • The NRL Validation Rule is mapped to the rule element.
    • The name of the NRL Rule Set becomes the value of the attribute name of the pattern element in Schematron.
    • The NRL rule ID is becomes the value of the id attribute of the rule element in Schematron.
  • The constraint of the NRL rule is translated in an XPath expression and this expression becomes the value of the test attribute of the assert element in Schematron. This involves mapping the NRL expressions as much as possible to XPath and is probably the most time consuming part of creating the generator depending on the scope of NRL desired to be translated. This tutorial covers some common expressions translations such as arithmetic expressions, boolean operators, binary predicates; this is covered in detail in the next section.
  • In NRL the rule Context refers to the immediate upper type in the model hierarchy. In this example it is straightforward to observe looking at the expanded diagram of the Trade type displayed above that the immediate upper type in the hierarchy for numberOfLegs from the NRL rule constraint is Trade. In Schematron, it is not possible to specify a type as a rule context. To solve this, the model needs to be recursively seached for all nodes that have this type and the paths to these nodes are expressed in XPath format and they represent the value of the context attribute of the rule element in Schematron. In this example, it is easy to observe that in the model that the Trade itself is the only node of type Trade; so in XPath this is //trade. The NRL to Schematron context translation is explained again in the example displayed below in order to make it all clear.
NRL rule
Schematron rule
Context: Amount
Validation Rule "r2"
amount >= 10000
<rule context="//trade/leg/pay | //trade/leg/receive | 
               //trade/leg/netCashFlow | //trade/totalValue" id="r2"> 
  <assert test="amount >= 10000"/>

In this example the NRL rule context is Amount because the rule constraint is evaluating the value of amount and the immediate upper type in the hierarchy for amount is Amount (note that, for example, an immediate upper node of amount in the hierarchy is the pay node in the model diagram which is of type Amount).

It is highlited in the diagram that more nodes of type Amount exist: pay, receive, netCashFlow, totalValue. It is also highlited that a node of type Amount contains the nodes amount and currency. This means that in this example the rule is evaluating the value of amount in 4 places in the model since amount is contained by the type Amount and 4 nodes as highlighted have this type. This explains why the NRL context translated to Schematron context includes the paths to these nodes in XPath format as displayed in the Schematron rule.

(Note: this expansion of types into paths would not be necessary if we were to use Schematron with XPath 2 - we decided to stick to version 1 for this tutorial)

The NRL to Schematron rule translation is probably the most common translation that needs to be done and it suffices for the purpose of this tutorial. A NRL to Schematron generator might attempt to generate Schematron reports as well.

Step by step example of building a NRL to Schematron generator

The diagram displayed below shows the entire generatiom implementation workflow: The input is NRL code. The NRL code is parsed by the NRL parser into a NRL AST. The NRL AST is translated into a Schematron AST. The Schematron AST is serialised by the Serialiser. The Serialiser produces the Schematron code which is the final output.

The beauty of using Concordion to build the generator is that the specifications are tied to the implementation thus and the system is documented and the code is neat.

A preferred way of starting to build the generator is by starting with writing the specifications, more exactly in this case, by writing the test cases. Here is a link to the final Concordion validated test cases, which are also displayed below, which will show exatcly what it is aimed to be obtained. All the implementation sits behind the green colours from these two tables.

Concordion test cases for NRL expressions to XPath expressions. Concordion test cases for NRL rules to Schematron rules.
  1. Writing the test cases

  2. Writing these test cases follow the same procedure described in the Concordion tutorial mentioned above. The test cases are written in a html file which is tied to the fixture as showed in the tutorial. Here is the html code for the NRLSchematronGenerator.html file used to build this generator example. There is no need to write all the possible test cases from the beginning, test cases can always be added later .

    Starting by writing some test cases helps to narrow down implementation focus on the NRL constraints specified to be translated.

    The first column from both tables represents the expression or rule correctly written in NRL. The second column represents the same concept but translated to Schematron and this is what the implementation is expected to produce. The third column is optional for specifying any comments if desired. Obviously, this structure can be changed to add more columns or to not use tables at all. This example uses tables for test cases to maximise the clarity of the translations.

  3. Writing the fixture

  4. The next step is to write the fixture file that will map the test cases to their implementations. The fixture documented java source code for this example of generator is available for download. Writing the fixture class is straightforward and the Concordion tutorial mentioned above explains how to write fixture classes.

  5. Implementation of test cases

  6. Each test case written at Step 1 needs to be implemented correctly in order to be validated by Concordion and coloured in green, otherwise it is coloured in red. The implementation needs to be serialised to generate the same output as the one written in the second column of the html test cases for Schematron as expected generated output.

    The first test case from the first table, for example, says that a number, for example number 6 in NRL is 6 in NRL and in Schematron is 6 too. A class that allows to express numbers needs to be created. The class needs to implement methods to set the value of the number an to retrieve it. Here is the java source code for class which validates the first test case.

    Other test cases may require the use of a serialiser method to format the output as desired. It is recommended to keep the serialiser methods separate in a different class from the implementation. An example of such test case that requires a serialiser is 5 / 4.2 which is translated from NRL to Schematron as 6 div 4.2. The implementation is in the java class and the serialiser method is in the The code is documented and comprehensive. The serialiser method relevant for this test case is the method that takes as parameter an instance of a BinaryPredicate.

    The second table uses a different serialiser class, for clarity.

    All implementation code for the test cases introduced above in the two tables is available for download and is documented and comprehensive.

  7. NRL to Schematron generator implementation

  8. The last step is to write the generator itself. The NRL to Schematron generator class,, makes use of all the classes written for implementing the test cases. This class can be continously expanded as translations as test cases are implemented. This class will run as a JUnit test as described in the Concordion tutorial.

Download java source code of this example

Here is the link to download the entire project including the source code and this tutorial. If you are using eclipse, you can import this as an eclipse project. It requires the NRL parser, which you can find on the sourceforge page.


In conclusion: this document attempts to explain how to translate a part of the NRL language to Schematron. It is not supposed to be a full code generator, and therefore neither implements all of NRL, nor all of Schematron. Nevertheless, we hope this was useful to you as an example of working with the NRL API and what is involved in writing a code generator.

Let us know on the nrl-dev list!.