Context-based Tag Selection
Introduction
Arbortext Styler provides a simple mechanism to specify XML context hierarchies. A parallel in the PTC Arbortext Layout Developer template ensures that a single chunk of PTC Arbortext Layout Developer code is processed per context.
A context is the hierarchical position of an element node in the XML structure being formatted. The role of a single element can vary within a document. For example, one element can be the child of multiple parents or ancestors, or appear as the first element within another element. The context of the element can be described using XSL location paths.
In PTC Arbortext Layout Developer, the tags to be processed for each context in a document are identified in a context control stream. This tag is a list of contexts with onEnter and onExit event handlers for each one. The handlers provide instructions for PTC Arbortext Layout Developer when it enters and leaves a matched context.
Context-based tag selection can only be used when working with an XML content stream. An XML stream can be associated with a single context control stream. Context control streams can also be used inline to add further contexts and processing to the XML hierarchy.
In the Formatting Object Model (FOM) the fStream object has a contextsCtrl property, which associates a single context control stream with the content. The content must be XML for matching to occur. Note that XML content is usually held in .xm or .xd tags but other text streams can be considered as XML. Context matching occurs before any tag matching on entry into a context and after tag matching when exiting a context.
Context Control Streams
Context control streams (tag type .cx) provide a list of contexts. PTC Arbortext Layout Developer uses this list of contexts while it is formatting through XML content. When it encounters a context in content, it checks the context control stream. If there are events specified in the control stream for the context, they are processed.
The contexts to match are specified using a match keyword and a value. The value is a location path equivalent to that used when defining the match attribute of an XSLT template, for example <xsl:template match=”xxx”/> where xxx is the location path. The values of the match context control keyword follow the same rules as the XSLT template match. Context control streams allow users to create processing rules for processing instructions and comments as well as elements. Entity references are not matched.
This is a sample match in the control stream:
match "chapter/title"
This entry will match the <title> element in a <chapter>.
When PTC Arbortext Layout Developer processes the context control stream, it builds a list of applicable contexts. It applies the same applicability rules as XSLT. The most specific location paths in the match have a higher priority over more general paths. If two matches are equal, PTC Arbortext Layout Developer chooses the first one it encounters, unless a priority value is specified on the match keyword. For example:
match "chapter/title", 20
PTC Arbortext Layout Developer selects the entry with the highest priority.
onEnter and onExit keywords follow the match keyword and value in an entry. These specify the actions that PTC Arbortext Layout Developer should take when it enters and exits the declared context. There are two types of instruction: process an PTC Arbortext Layout Developer tag or execute some JavaScript code.
To process a tag, use the following:
match "chapter/title"
onEnter "startChapterTitle"
where startChapterTitle is the name of the PTC Arbortext Layout Developer tag that PTC Arbortext Layout Developer should process when it encounters the beginning of the title in chapter context.
To process JavaScript code, use the following as applied to the onExit event:
match "chapter/title"
onEnter "startChapterTitle"
onExit {
formatting.blockEnd();
}
In this example, the onExit event ends a block by executing the fragment of JavaScript declared between braces. All JavaScript to be executed must be contained in a pair of curly braces.
If your XML instance contains namespaces, these must be declared in the context control stream. The namespace keyword allows you to declare that namespace for the control stream. The keyword takes two parameters — the first is the namespace prefix used in the element names in the match location paths in the control stream. The second is the URI mapped to that prefix. The URI must match the URI in the content to enable the context matching to select the correct context. The prefix can be different from that used in the content.
This is a sample namespace declaration:
namespace "st","http://www.ptc.com/simon"
If a namespace is declared midway through the context control stream, any contexts declared after that point have that namespace in scope.
If you have many namespaces and multiple context control streams, you can separate the namespace declarations into a smaller context control stream fragment. The fragment is then called in a context control stream using the namespaces keyword. For example:
namespaces "myNamespaces"
where myNamespaces is the name of the context control stream fragment that declares all the namespaces.
It is possible to include other context control streams in the current one. Other control streams are declared with the include keyword and a value. The value is the name of the context control stream tag to be included. For example:
include "myOtherContexts"
where myOtherContexts is the name of the context control stream to include in the current one. Contexts declared in an included context control stream are of a lower default priority than those in the main control stream. Included control streams can call other control streams and those additional contexts are again of a lower default priority.
Other keywords such as
addBefore and
addAfter can be associated with a
match entry. These are related to DOM augmentation rather than matching markup. Refer to
DOM Augmentation for information.
Using Inline Context Control Streams
The context control stream associated with an XML content stream provides a single group of contexts that is referred to as group 0. Once formatting of the content stream has started, it is possible to add more contexts to the list using inline commands. Contexts can also be removed later in the formatting process. Adding contexts inline provides access to a further four groups of contexts. PTC Arbortext Layout Developer potentially has five groups to process when entering and exiting contexts.
The fFormatting object provides the contextAdd() method for adding more contexts. For example, to add a new set of contexts to group 0:
formatting.contextAdd("myNewContexts");
This adds the contexts defined in the myNewContexts context control stream to the group 0 list. These contexts have a higher default priority than those that already exist in that group.
For example, to add contexts to a different group:
formatting.contextAdd("myNewContexts",1);
where 1 is the number of the group to which the contexts are added. There are five groups in total, numbered 0 to 4. Contexts in each group are processed separately. On entering a context, groups 4 to 0 are processed in that order. On exiting a context, the groups are processed in the order 0 to 4. Template designers can instruct PTC Arbortext Layout Developer to process five separate tags or JavaScript fragments when entering and exiting contexts.
It is possible to control how the adding of new contexts affects the pre-existing contexts in a group. The third parameter of the fFormatting.contextAdd() method, after the included context control stream and the target group number, provides this control. The parameter provides three options:
• Add new contexts to the group — fFormatting.LIMIT_NONE
• Add new contexts to the group but prevent PTC Arbortext Layout Developer from searching any pre-existing contexts in any other group — fFormatting.LIMIT_ALL
• Add new contexts to the group but prevent PTC Arbortext Layout Developer from searching any pre-existing contexts in the same group — fFormatting.LIMIT_GROUP
These options are listed on the fFormatting.ContextLimits constant.
For example, to override the existing group 0 contexts with a new set:
formatting.contextAdd("myNewContexts",0,fFormatting.LIMIT_ALL);
For example, to add new contexts to a specific group to the exclusion of all pre-existing contexts in that group only:
formatting.contextAdd("myNewContexts",2,fFormatting.LIMIT_GROUP);
where 2 is the group to which to add contexts.
It is also possible to remove contexts from list. The contextRemove() method for the fFormatting object is used to remove the most recently added contexts from the list. For example, following the instruction formatting.contextAdd("myNewContexts",1), you can remove those contexts using:
formatting.contextRemove(1);
where 1 is the group from which to remove the recently added contexts.
An additional boolean parameter for contextRemove() instructs PTC Arbortext Layout Developer to remove all contexts added in any preceding contextAdd() command. For example:
formatting.contextRemove(1, true);
removes all contexts added to group 1.
Using Javascript to Build Context Control Streams
As well as hand editing a context control stream tag, it is possible to create context control streams using JavaScript.
The fContent object has a createContexts() method for creating a new context control stream. For example:
var context;
context = template.content.getContexts("myContextControl");
if (!context) context = template.content.createContexts("myContextControl");
This example tests for the existence of a context control stream called myContextControl using the getContexts() method. If it does not exist, the createContexts() method creates a new one with the given name. The getContexts() and createContexts() methods both return an fContexts object.
Once the context control stream exists, its contents can be managed using the methods of the fContexts object:
• addMatch(), removeMatch(), clearMatches() — add, remove, or clear matches represented by the fContextMatch object
• addInclude(), removeInclude(), clearIncludes() — add, remove, or clear included contexts
The fContextMatch object has a number of properties, which reflect those keywords already described:
• match — specifies the location path selector for the context
• priority — represents the priority for this context match
• onEnter and onExit — point to either an PTC Arbortext Layout Developer tag (fStream) or a JavaScript function to be executed for the onEnter and onExit events
• namespaces — provides an array of prefix–URI pairs to use for this match