TEMPLATE Procedure: Creating Markup Language Tagsets |
Getting Familiar with Tagsets |
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; run;
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.
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.
To view the contents of a tagset, use the SAS windowing environment or the TEMPLATE procedure.
In the Results window, select the Results folder. Right-click and select Templates to open the Templates window.
Double-click Tagsets to view the contents of that item store or directory.
Double-click the tagset that you wish to view. For example, the CHTML tagset is the template store for CHTML output.
To view the Templates window, submit the following command in the command bar:
odstemplatesThe Templates window contains the item stores Sasuser.Templat and Sashelp.Tmplmst.
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.
To view the tagsets that SAS provides, double-click the Tagset item store.
Right-click the tagset, such as Rtf, and select Open. The tagset is displayed in the Template Browser window.
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.
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.
For the most part, 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 start:2 put '<table>' nl; finish: put '</table>' nl; end;
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>'; end;
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 variable |
a variable that includes 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 variable |
a variable that specifies 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 on style attributes, see TEMPLATE Procedure: Creating a Style Template (Definition). |
dynamic variable |
a variable that is dynamically created within SAS. Because these variables are dynamically created, their names, or how they are used, is 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 variable |
an array that contains 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 variable |
an array that contains 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 variable |
a variable that is 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 and NMVAR Statement for more information. |
memory variables |
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 variable |
an area of memory that contains 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 variable |
a temporary item store that contains 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. |
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; end;
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 |
To create a tagset, use the TEMPLATE procedure to define the tagset. In general, three methods are available to create a custom 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.
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 markup type=event_map file='custom-tagset-filename.xml'; proc print data=sashelp.class; where Height gt 60; run; ods markup close;
Here is the listing output and resulting XML file:
The SAS System 1 Obs Name Sex Age Height Weight 1 Alfred M 14 69.0 112.5 3 Barbara F 13 65.3 98.0 4 Carol F 14 62.8 102.5 5 Henry M 14 63.5 102.5 8 Janet F 15 62.5 112.5 9 Jeffrey M 13 62.5 84.0 12 Judy F 14 64.3 90.0 14 Mary F 15 66.5 112.0 15 Philip M 16 72.0 150.0 16 Robert M 12 64.8 128.0 17 Ronald M 15 67.0 133.0 19 William M 15 66.5 112.0
<?xml version='1.0' encoding='windows-1252'?> <doc operator='user' sasversion='9.1' saslongversion='9.01.01B0D06102003' date='2003-06-11' time='15:55:02' encoding='windows-1252' event_name='doc' trigger_name='attr_out' class='Body' index='IDX' just='c'> <doc_head event_name='doc_head' trigger_name='attr_out' class='Body' index='IDX' just='c'> <doc_meta event_name='doc_meta' trigger_name='attr_out' class='Body' index='IDX' just='c'/> <auth_oper event_name='auth_oper' trigger_name='attr_out' class='Body' index='IDX' just='c'/> <doc_title event_name='doc_title' trigger_name='attr_out' class='Body' index='IDX' just='c'/> <stylesheet_link event_name='stylesheet_link' trigger_name='attr_out' index='IDX' just='c'/> <javascript event_name='javascript' trigger_name='attr_out' class='Body' index='IDX' just='c'> <startup_function event_name='startup_function' trigger_name='attr_out' class='StartUpFunction' index='IDX' just='c'> </startup_function> <shutdown_function event_name='shutdown_function' trigger_name='attr_out' class='ShutDownFunction' index='IDX' just='c'> </shutdown_function> </javascript> </doc_head> <doc_body event_name='doc_body' trigger_name='attr_out' class='Body' index='IDX' just='c'> <proc event_name='proc' trigger_name='attr_out' name='Print' index='IDX' just='c'> <anchor event_name='anchor' trigger_name='attr_out' class='Body' name='IDX' index='IDX' just='c'/> <page_setup event_name='page_setup' trigger_name='attr_out' class='Body' index='IDX' just='c'> <system_title_setup_group event_name='system_title_setup_group' trigger_name='attr_out' class='Body' colcount='1' index='IDX' just='c'> <title_setup_container event_name='title_setup_container' trigger_name='attr_out' class='SysTitleAndFooterContainer' colcount='1' index='IDX' just='c'> <title_setup_container_specs event_name='title_setup_container_specs' trigger_name='attr_out' class='SysTitleAndFooterContainer' colcount='1' index='IDX' just='c'> <title_setup_container_spec event_name='title_setup_container_spec' trigger_name='attr_out' colcount='1' type='string' index='IDX' just='c' width='100%'/> </title_setup_container_specs> <title_setup_container_row event_name='title_setup_container_row' trigger_name='attr_out' colcount='1' index='IDX' just='c'> <system_title_setup event_name='system_title_setup' trigger_name='attr_out' class='SystemTitle' value='The SAS System' colcount='1' index='IDX' just='c'> </system_title_setup> </title_setup_container_row> </title_setup_container> </system_title_setup_group> </page_setup> ...more xml tagged output... </table_body> </table> </output> </leaf> </proc_branch> </proc> </doc_body> </doc>
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 you defined.
Note: When you first run a SAS process and specify TYPE=EVENT_MAP, you can also generate a stylesheet along with the body file. The stylesheet shows which style attributes you are using.
To create other types of output, you can use one of the following tagsets as alternatives:
TEXT_MAP generates output that is similiar to a listing output.
TPL_STYLE_LIST generates HTML and TPL_STYLE_MAP generates XML. However, these tagsets list only a subset of the possible attributes.
STYLE_POPUP generates HTML like HTMLCSS. However Internet Explorer, STYLE_POPUP displays a window that shows the resolved ODS style definition for any item that you click.
STYLE_DISPLAY is like STYLE_POPUP, but it generates a simple page of output for you to click.
NAMEDHTML generates HTML output like STYLE_POPUP, but all of the objects are labeled the same as with ODS TRACE.
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 on DATA step functions and statements, see SAS Language Reference: Dictionary and SAS Language Reference: Concepts.
Copyright © 2008 by SAS Institute Inc., Cary, NC, USA. All rights reserved.