Using Modes

Revision History
Revision 0.12008-05-25Dave Pawson
Initial Issue

Modes allow a finer resolution in dispatching. The outline of an NVDL script when modes are used is shown in Example 3.1

Example 3.1. Outline structure when using modes

  <?xml version="1.0" encoding="UTF-8"?>

<rules xmlns="http://purl.oclc.org/dsdl/nvdl/ns/structure/1.0"
     startMode="start">                       1
   
    <mode name="start" >                   2
      <namespace ns="http://A">
	<validate schema="A.rng" useMode="B"/> 3
      </namespace>
      <anyNamespace>
	<reject/>
      </anyNamespace>
    </mode>

    <mode name="B">
      <namespace ns="http://B" useMode="any">
	<validate schema="B.rng" useMode="any"/>
      </namespace>
      <anyNamespace>                          4
	<reject/>
      </anyNamespace>
    </mode>

    <mode name="any">                         5
      <anyNamespace>
	<reject/>
      </anyNamespace>
    </mode>


</rules>

1

The starting mode is specified by the rules attribute startMode

2

The first mode, with two namespace sections

3

When validated, change mode to mode 'B'

4

This is to remind you of the default action, here made explicit

5

The fallback position, when all else fails, reject it. A strict validation

This is the alternative to a simple unordered dispatching on namespace alone. Note that the rules element now has mode children and the namespace children are confined to the mode element. This is the major difference to be found when using modes.

So the rules (namespace condition and corresponding action(s)) are within mode children.

As with the simpler approach the action (for these examples) is a validate.

[Note]Note

If a validate action does not have a useMode attribute, then the mode remains unchanged - quite often falling back on the default action. Beware!

It is possible though rarely needed, to include a useMode attribute on the reject and accept elements, indicating what the processor should do having rejected(or accepted) a section.

With regard to modes, the interesting part of the standard is § 6.4.7. “The top-level rules element is transformed so that it has mode elements as children. If its child elements are namespace or anyNamespace elements, they are wrapped in a mode element. Then, a name attribute and startMode attribute are added to the mode element and rules element, respectively. These attributes shall have the same value, which shall be different from any other mode name. ” This implies that as far as processing goes, your script will have modes, whether you want them or not. The subtlety is that the modes may not do what you want. I hope this was demonstrated if you tried re-ordering the sections in the previous chapter, as noted here.

The previous examples have simply used namespace elements to partition the input instance for validation. This statement makes it clear that as part of the process, all namespace elements are wrapped in mode elements. So either way, your scripts will use modes.

The simplest exlanation of is to imagine a chain of modes. From the rules element the first mode is specified by the startMode attribute on the rules element. Each mode element can specify the mode to change to next, by means of the useMode attribute on the validate or anyelement, the child of mode. The namespaced based processing follows this chain by looking at the children of the current node in the XML instance, and when a non-matching namespace is found, the next in chain mode is used. This works well for nested elements, less well when two different namespaces are used as siblings? Imagine the head and body elements of XHTML being in different namespaces? For such as this, the two namespaces need to be handled in the same mode. Taking Example 2.9 as a starting point, it can be written as a moded script, see Example 3.2

Example 3.2. A moded version of Example 2.9

<rules 
xmlns="http://purl.oclc.org/dsdl/nvdl/ns/structure/1.0" 
startMode="doc">                                            1

  <mode name="doc">                                      2
    <namespace ns="http://document">                                 
      <validate schema="routing.1.rng" useMode="rest"/> 
    </namespace>
  </mode>

  <mode name="rest">                                      3
    <namespace ns="http://head" >
      <validate schema="routing.1.rng" />  
    </namespace>
    <namespace ns="http://body">                          4
      <validate schema="routing.1.rng" />
    </namespace>
  </mode>
</rules>        

  
1

The first mode chosen is the namespace of the document element

2

The first mode, identified by it's name attribute

3

The next mode in the chain handles two sibling namespaces, 'head' and 'body', each having its own schema (which happens to be the same for this example)

4


I hope this example is clear. Imagine the source XML instance. View it as a tree of namespaces (rather than just elements). For each child in the tree, a new mode is needed in a simple moded ruleset. For each sibling namespace, the dispatcher needs to be told how to validate it within a single mode that handles all sibling namespaces. As you walk the tree, imagine the changing namespaces and the way through the rules via the different modes you specify. Note the lack of a useMode attribute on the two siblings? We don't want to change modes on meeting a foreign namespace, we need to remain in this mode. You could say that after meeting the 'head' namespace, we come across the 'body namespace' in the source instance, the processor tries again in the same mode. The key point is that the processing remains in this mode until a foreign namespace is encountered for which it has no matching condition (a namespace match in this mode).

Yet again we need to mention the default rule. This is there to reject all foreign namespaces for which you have not created a rule.

  
<anyNamespace>
  <reject/>
</anyNamespace>



When a script becomes large it may be useful to repeat rule in more than one place. Since NVDL doesn't have explicit syntax for this, it is useful to utilise xinclude for this purpose. If the xIncluded file has the mode element as its root element this makes for a tidier NVDL script.