# RelaxNGCC Tutorial 2

Let's see a little more complicated example.

## Explanation of Grammar

In this tutorial, we use the following grammar, which describes a structure of files and directories. The special mark-ups peculiar to RelaxNGCC are red.

    <?xml version="1.0" encoding="utf-8"?>
    <grammar xmlns="http://relaxng.org/ns/structure/1.0"
      datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
      xmlns:c="http://www.xml.gr.jp/xmlns/relaxngcc">

    [1]
    <c:java-import>
    import java.util.Set;
    import java.util.HashSet;
    </c:java-import>

    <start c:class="sample2">
      [2]
      <c:java-body>
      public Set hiddenfiles;
      </c:java-body>
      <element name="files">
        <ref name="file-or-dir" c:alias="child"/>
        [3]
        <c:java>hiddenFiles = new HashSet(child.hiddenFiles);</c:java>
      </element>
    </start>

    [4]
    <define name="file-or-dir" c:class="FileOrDir">
      <c:java-body>
      public Set hiddenFiles;
      </c:java-body>
      <c:java>hiddenFiles = new HashSet();</c:java>
      <oneOrMore>
        <choice>
          <element name="file">
            <attribute name="name">
              <text c:alias="filename"/>
              [5]
              <c:java>if(filename.startsWith(".")) hiddenFiles.add(filename);</c:java>
            </attribute>
          </element>
          <element name="directory">
            <attribute name="name"><text/></attribute>
            <ref name="file-or-dir" c:alias="content"/>
            [6]
            <c:java>hiddenFiles.add(content.hiddenFiles);</c:java>
          </element>
        </choice>
      </oneOrMore>
    </define>

    </grammar>

This grammar allows `files` element as the root and arbitrary number of `directory` and `file` elements under the `files` element. Also it allows `directory` element under `directory` element.

## RelaxNGCC Mark-ups

Now, let's suppose that we want to collect files that begin with a period (in Unix convention, it means "hidden" attribute). Additionaly, suppose that our interest is not directory tree but file names.

Then, explanations of each part are following.

[1] The content of `java-import` element is copied besides the main class definition of Java. If your code within `java` element or `java-body` element[5] requires classes in external packages, you should write `import` declarations using `java-import` element. Note that `java-import` elements under the root grammar element affect all generated code and they under a `start` or `define` element affect only the corresponding class to the element.

[2] The content of `java-body` element is copied into the class definition of Java. By using this, you can add bodyary methods and data members to the generated class. In this sample, the `java-body` element declares a data member `hiddenFiles` for storing the file names.

[3] The `java` element defines an action to be executed when a corresponding part of the input XML instance comes. In this example, initialize `hiddenFiles` when the `files` element ends.

[4] Since RelaxNGCC generates one Java class per a start block or a define block, RelaxNGCC generates 2 files from this grammar. The names of the classes are specified with `c:class` attribute for each `start` and `define` element. Especially the `c:class` attribute for the define element is mandatory because the name `"file-or-dir"` is not valid for a name of Java class.

[5] At this location, the file name is added if it begins with a period to the `hiddenFiles` collection.

[6] This is also `java` element, but be careful that the code fragment of Java refers to the previous `define` block with an `alias` attribute. If you add an `alias` attribute to a `ref` element, the Java object accessed by the given alias is a object corrsponding to the `define` block. In this example, the instance `content` refers to `FileOrDir` object.

After you compile and execute the generated code, the `hiddenFiles` member will contain all file names that begins with a period in the input XML instance. The `main()` method generated by RelaxNGCC may be helpful for understanding test procedure.

## Comparison to Relaxer

Relaxer and RelaxNGCC is same at the point of generating Java source code from a given grammar. But, if you use Relaxer for the case of this tutorial, you may have to traverse the object model includes a directory tree and collect file names that begins with a period. On the other hand, RelaxNGCC is more efficient for this purpose because it obtains the collection through one path via SAX interface.

However, there are some features supported by only Relaxer such as a conversion from Java object into XML instance. It is important to select more suitable tool according to your purpose.

RelaxNGCC home