TEMPLATE Procedure: Creating Markup Language Tagsets

Concepts: Markup Languages and the TEMPLATE Procedure

Getting Familiar with Tagsets

Listing Tagset Names

SAS provides a set of tagsets. To get a list of the tagsets that SAS supplies and any tagsets that you have created and stored in the Sashelp.Tmplmst template store, submit the following SAS statements:
proc template;
   list tagsets;
By default, PROC TEMPLATE lists the tagsets in Sashelp.Tmplmst and Sasuser.Templat. Typically, you have Read-Only permissions to the Sashelp.Tmplmst item store where the SAS tagset directory is located. The Sasuser.Templat is the item store where the tagsets that you create or customize are stored by default.

Specifying Tagset Names

To specify a SAS tagset stored in Sashelp.Tmplmst or a tagset that you have created and stored in Sasuser.Templat or any other item store, use a two-level name: Tagsets.tagset-name. For example, Tagsets.Chtml or Tagsets.Mytagset are valid two-level tagset names. By default, SAS knows that the specified tagset is stored in either Sashelp.Tmplmst or Sasuser.Templat.
To specify a tagset that you have created and stored in an item store other than Sasuser.Templat, assign the item store to the ODS search path with the ODS PATH statement. For information about the ODS PATH statement, see ODS PATH Statement.

Viewing the Contents of a Tagset

To view the contents of a tagset, use the SAS windowing environment or the TEMPLATE procedure.
  • SAS Windowing Environment
    1. From the menu, select Viewthen selectResults.
    2. In the Results window, select the Results folder. Right-click and select Templates to open the Templates window.
    3. Double-click Tagsets to view the contents of that item store or directory.
    4. Double-click the tagset that you want to view. For example, the CHTML tagset is the template store for CHTML output.
  • SAS Windowing Command
    1. To view the Templates window, submit the following command in the command bar:
      The Templates window contains the item stores Sasuser.Templat and Sashelp.Tmplmst.
    2. When you double-click an item store, such as Sashelp.Tmplmst, that item store expands to list the directories where ODS templates are stored. The templates that SAS provides are in the item store Sashelp.Tmplmst.
    3. To view the tagsets that SAS provides, double-click the Tagset item store.
    4. Right-click the tagset, such as Rtf, and select Open. The tagset is displayed in the Template Browser window.
  • TEMPLATE Procedure
    To see the source for a tagset, use PROC TEMPLATE and specify the two-level name of the tagset. For example, to see the source of a SAS tagset that generates CHTML output, submit these SAS statements:
    proc template;
          source tagsets.chtml;
    The source for Tagsets.Chtml consists of the following:
    • a DEFINE TAGSET statement that names the tagset
    • events that define what is written to the output file
    • tagset attributes, such as output type and the character to use for line breaks

Understanding Events

A tagset controls output generation through a series of events and variables. An event defines what is written to the output file. Here are some key points about events:
  • Events have unique names. SAS procedures that generate ODS output use a standard set of events, which you can customize by redefining them in the customized tagset. In addition, you can define custom events.
  • The DEFINE EVENT statement assigns a name to an event.
  • An event can include start sections, finish sections, or both. These sections specify different actions. If the event does not include either a start or finish section, then the event is stateless: no matter how the event is called, all of the actions in the event are executed. If an event has a finish section, then a start section is assumed if there are statements above the finish section.
  • An event can execute another event using the TRIGGER statement. From the start section of an event, any event triggered also runs its start section. From the finish section, the triggered event runs its finish section. If a triggered event does not have start or finish sections, then the event runs the statements that it does have. A trigger can also explicitly ask for an event's specific section. See Executing Events Using the TRIGGER= Statement.
  • Events can perform actions based on conditions.
  • An event consists of PUT statements, text, and event variables.
For example, here is a simple event for an HTML table output:
define event table;1
      put '<table>' nl;
      put '</table>' nl;
In the event:
1 The DEFINE EVENT statement begins the event and assigns it the name TABLE.
2 The START section defines the beginning portion of the event, and the FINISH section defines the ending portion of the event. An event for a table needs START and FINISH sections because ODS needs to know how to define the beginning and the ending. ODS also expects other events to define how to format the table's rows and columns. The PUT statements specify to write the tags <table> and </table> to the output file, and to add a new line after each tag.
The following event does not include a start and finish section. The PUT statements specify to write the tags <TD> and </TD> to the output file. In addition, the event variable VALUE is used so that the data value from the SAS procedure or data set is written to the output file. The data value is enclosed with the <TD> and </TD> tags.
define event data;
      put '<TD>';
      put VALUE;
      put '</TD>';

Understanding Variables

A variable is a programming structure that is used to hold data. A variable holds the data that is assigned to it until you assign a new value or end the program. Each variable has a unique name and holds information that is either internal information to handle the requested output (metadata that is used by ODS or the XML LIBNAME engine) or is information that is directly related to the output itself. For example, the variable COLCOUNT holds the value for the number of columns in the output, and the variable DATE holds the date.
Variables that are used by tagsets are divided into two groups: internally generated and user-created.
There are three logical divisions of internally generated variables:
event variables
are variables that include text, formatting, and data values. These variables can originate in many places, such as the table template, the procedure, the title, or byline processing.
style variables
are variables that specify a value for one aspect of the presentation. Style variables are specified by the ODS style attributes that are currently in use. The style variables are only differentiated from other event variables in that you know exactly where they originate.For more information about style attributes, see TEMPLATE Procedure: Creating a Style Template.
dynamic variables
are variables that are dynamically created within SAS. Because these variables are dynamically created, their names, or how they are used, are unknown. These variables are dynamic because they are not defined by ODS, but by applications such as SAS/GRAPH and the XML LIBNAME engine. Dynamic variables are designated by a preceding @ symbol. Dynamic variables are listed with the DYNAMIC statement. For more information about SAS/GRAPH, see SAS/GRAPH: Reference.
There are five types of user-created variables:
dictionary variables
are arrays that contain a list of numbers or text strings that are identified by a key. A dictionary variable has, as part of its name, a preceding '$' symbol and a subscript that contains a text string or a variable that has a character value. The text string or variable within the subscript is called a key. Keys are case preserving and case sensitive. After dictionary variables are created, they are globally available in all events and persist until you unset them with the UNSET statement.
For example, the following dictionary variable is identifying the entry in the $MyDictionary variable that contains the text 'dog': $MyDictionary['dog']. In this example, the key is 'dog'. Dictionary variables are accessed sequentially by using the ITERATE and NEXT statements.
list variables
are arrays that contain a list of numbers or text strings that are indexed. A list variable has, as part of its name, a preceding '$' symbol and a subscript that is empty or contains a number or numeric variable. The number within the subscript is called an index. After they are created, list variables are globally available in all events and persist until you unset them with the UNSET statement.
List entries are accessed by positive or negative indexes. Positive indexes start at the beginning of a list. Negative indexes start at the end of a list. For example, the list variable $Mylist[2] identifies the second entry in the list variable $Mylist. In this case, the index is 2. The list variable $Mylist[-2] identifies the second entry from the end of the list variable $Mylist. In this case, the index is [-2]. List variables are accessed sequentially by using the ITERATE and NEXT statements.
macro variables
are variables that are part of the SAS macro programming language. Macro variables must be specified with the MVAR or NMVAR statements. After they are declared, macro variables can be used anywhere within an event. See the MVAR Statement for more information. Also see NMVAR Statement.
memory variables
are areas of memory that contain numeric data, character data, or lists of numeric or character data. A memory variable is classified as a dictionary variable if it is created with a subscript that contains a key. A memory variable is classified as a list variable if it is created with a subscript that is empty or contains an index. If you omit a key or an index, then the memory variable is a numeric or character scalar variable, depending on the variable's value.
scalar variables
are areas of memory that contain numeric or character data. Scalar variables must be preceded by the '$' symbol. After scalar variables are created, they are globally available in all events and persist until you unset them with the UNSET statement.
stream variables
are temporary item stores that contain output. All output from PUT statements is directed to the open stream variable until it is closed. Stream variables must be preceded by the '$$' symbol except when used with the OPEN or PUTSTREAM statements. Stream variables are created with the SET, EVAL, or OPEN statements, within the DEFINE EVENT statement. Stream variables are different from other variables in that they can hold very large amounts of data. They can hold very large amounts of data because as they increase in size, they are written to disk as needed.

Displaying Event Variables and Their Values

Because variables represent data, their values might or might not be present, depending on the SAS procedure and the job. For example, some variables have values only if they are specified with procedure options or style options. Other variables have values because the internal information, such as how many columns are in the output, is needed. For example, Tagsets.Chtml contains the event COLSPECS, which uses the event variable COLCOUNT so that ODS knows how many columns are in the output:
define event colspecs;
      put '<p>' nl '<table';
      putq ' columns=' COLCOUNT;
      put ' cellpadding=2 border=1>' nl;
To determine which variables have values and what the values are, use the EVENT_MAP statement to submit the SAS program. For more information, see Defining a Tagset Using the Event_Map Tagset. For a list of event variables and their descriptions, see Event Variables.

Creating Custom Tagsets

Methods for Creating Custom Tagsets

To create a tagset, use the TEMPLATE procedure to define the tagset. In general, three methods are available to create a custom tagset:
  • Define a tagset through inheritance.
  • Copy an existing tagset, and then modify it.
  • Define a custom tagset.

Inheriting Events in a Tagset

Tagsets can inherit events from each other. For example, the SAS tagset Tagsets.Wmlolist inherits most of its events from Tagsets.Wml, and Tagsets.Imode gets most of its events from Tagsets.Chtml. Inheriting events from an existing tagset is the easiest way to define a new tagset.
To inherit events, a tagset uses the PARENT= attribute in the DEFINE TAGSET statement to specify the name of a tagset from which to inherit. When a parent is specified for a tagset, all of the tagset options, attributes, and statements that are specified in the parent's template are used in the new template, unless the new template overrides them. That is, in the new tagset, an event can override the operation of the same-named event that is defined in the parent tagset. For example, if the parent tagset defines an event named TABLE, then you can change the operation in the new tagset by redefining the event named TABLE.
For an example of inheriting events in a tagset, see Creating a Tagset through Inheritance.

Defining a Tagset Using the Event_Map Tagset

SAS procedures that generate ODS output use a standard set of events and variables. To generate customized output, create a customized tagset with customized events. However, in order to customize the events, you need to know the names of the events that ODS uses.
A good way to start defining the customized tagset is to use the Event_Map tagset that SAS supplies. This enables you to determine which events are triggered and which variables are used by an event to send output from a SAS process to an output file. When you run a SAS process with Tagsets.Event_Map, ODS writes XML markup to an output file that shows all event names and variable names as tags. In the output, tag names are the event names. Tag attributes are the variables that have values for those events.
For example, the following statements run ODS MARKUP with TYPE=Event_Map to see which events and variables ODS uses for various parts of the PROC PRINT output:
ods listing;
ods markup type=event_map file='custom-tagset-filename.xml';

proc print data=sashelp.class;
   where Height gt 60;

ods markup close;
ods listing close;
Here is the listing output and resulting XML file:
XML Output
XML Output
In the XML output that is generated by Event_Map, PROC PRINT uses events named DOC_HEAD, PROC, TABLE, and so on. The TABLE event uses data from event variables such as STATE, CLASS, and TYPE. After you know the events and variables that generate the output, define the tagset and customize your events. For example, you could redefine the TABLE event to produce customized output.
To define a tagset with which to customize your output, start by specifying Tagsets.Event_Map as the parent tagset. As you redefine events to customize output, these events replace the default events that are defined in the Event_Map tagset. In addition, you can remove the operation of a default event by redefining it as an empty event in the tagset. When you are satisfied with the customized output, remove the Event_Map inheritance and the empty events. Then the output will reflect only the events that you defined.
Note: When you first run a SAS process and specify TYPE=Event_Map, you can also generate a style sheet along with the body file. The style sheet shows which style attributes you are using.

Alternatives to Event_Map

To create other types of output, you can use one of the following tagsets as alternatives:
  • The Text_Map tagset generates output that is similar to a LISTING output.
  • The Tpl_Style_List tagset generates HTML, and the Tpl_Style_Map tagset generates XML. However, these tagsets list only a subset of the possible attributes.
  • The Style_Popup tagset generates HTML like HTMLCSS. However, in Internet Explorer, Style_Popup displays a window that shows the resolved ODS style definition for any item that you click.
  • The Style_Display tagset is similar to the Style_Popup tagset, but it generates a simple page of output for you to click.
  • The NamedHtml tagset generates HTML output similar to the Style_Popup, tagset but all of the objects are labeled the same as with ODS TRACE.

Defining a Tagset Using SAS DATA Step Functions

A SAS DATA step function performs a computation or system manipulation on arguments and returns a value. In Base SAS software, you can use SAS functions in DATA step programming statements, WHERE expressions, macro language statements, the REPORT procedure, Structured Query Language (SQL), and in statements that are used when creating custom tagsets. Functions can be used on any statement within the tagset language. For information about DATA step functions and statements, see SAS Functions and CALL Routines: Reference, SAS Statements: Reference, and SAS Language Reference: Concepts.