Introduction

Parent Previous Next

Introduction


Many users of DOC xPress have expressed an interest in customizing the templates used within DOC xPress to generate documentation. The premises behind this introduction is to provide users a walk-through for creating a simple template that summarizes SQL Server column data at the table level.


Table of Contents

  Step One: Modifying the Document Control

  Step Two: Modifying the Structure Maps

  Step Three: Modifying the Template

  Step Four: Generating Documentation


Important Note:

All files modified within this documentation can be downloaded for review here.


Within the standard templates included in DOC xPress, upon drilling down to a table, DOC xPress displays summary information about the table. Drilling down further will allow users the ability to see individual column information. The goal is to create a new report in which, upon clicking on the table, users are shown all columns as seen in the example below. In addition, the table column named "Description" will contain a DOC xPRess Data Dictionary category.



Throughout this introduction, code snippets will be used as examples. The completed project can be downloaded here.


Important Note:

Before beginning this introduction, modification of the DOC xPress templates are not officially supported by Pragmatic Works and this cannot be stressed enough. While we do provide documentation and guidance within the help documentation, any modification to the DOC xPress templates is taken at the risk of the user.


Because of this, users are encouraged to back up the DOC xPress templates folder before beginning any modification work. At this time, the only assistance Pragmatic Works Support may offer is in the restoration of the template files to their original state.


DOC xPress Template Files

By default, the templates are stored within a folder in the installation directories for Pragmatic Workbench and Workbench Server. Below can be found the two default install locations:


  DOC xPress

o   C:\Program Files (x86)\Pragmatic Works\Pragmatic Workbench\DOC xPress Templates


  DOC xPress Server

o   C:\Program Files (x86)\Pragmatic Works\Workbench Server\DOC xPress Web Services\DefaultTemplates


The files and their uses are identical for both versions of DOC xPress. There are four types of files and two folders used by the DOC xPress document generation engine. More details on these files can be found here.


Step One:

Modifying the Document Control


The defaultTemplate.documentControl file is used to control which components are included within the generated documentation. It is an XML file containing two major sections: OutputTypes and Flag.


OutputTypes Node

The first section of the defaultTemplate.documentControl XML begins in the OutputTypes node and is displayed within the Generate Documentation dialog window.


The name attribute provides a friendly name for each of the output types, while the key attribute is used as a unique identifier that associates the output type with the flags found in the second section of the XML.


<OutputTypes>

<OutputType name="Compact Table" key="compactTable" />

<OutputType name="SQL Developer" key="developer" />

<OutputType name="Business Analyst" key="businessAnalyst" />

</OutputTypes>



Flag Nodes

The remaining section of the defaultTemplate.documentControl file defines the various objects that can be documented. These flags are hierarchical in nature and contain several important attributes. Below can be a small snippet of the SQL.Server flag portion of the defaultTemplate.documentControl file as well as how it is displayed within the Generate Documentation dialog window.


The name attribute is used as a unique identifier that helps each Structure Map and Template associate the flags with the currently active output type. The description attribute provides a friendly name for each of the flags. The showWarning attribute is an optional attribute that details whether or not a performance warning should be displayed within the Generate Documentation dialog window. Each of the output type attributes provide the flag with the default behavior for that particular output type. For example, by default, the SQL.SchemaDiagrams flag is set to True for the developer output type, but is set to False for the businessAnalyst output type.


<Flag name="SQL.Server" description="SQL Server" developer="True" businessAnalyst="True" >

<Flag name="SQL.Configurations" description="Server Configurations" developer="True" businessAnalyst="True" />

<Flag name="SQL.Database" description="Database Details" developer="True" businessAnalyst="True" >

<Flag name="SQL.Tables" description="Table Details" developer="True" businessAnalyst="True" >

<Flag name="SQL.SchemaDiagrams" description="Schema Diagrams" developer="True" businessAnalyst="False" />

<Flag name="SQL.LineageImpact" description="Lineage and Impact" developer="True" businessAnalyst="False" >

<Flag name="SQL.ImpactLists" description="Impact Details" developer="True" businessAnalyst="False" />

<Flag name="SQL.LineageLists description="Lineage Details" developer="True" businessAnalyst="False" />

</Flag>

<Flag name="SQL.TableColumns" description="Column Details" showWarning="True" developer="True" businessAnalyst="False" />

<Flag name="SQL.TableForeignKeys" description="Foreign Key Details" showWarning="True" developer="True" businessAnalyst="False" />

<Flag name="SQL.TableIndexes" description="Index Details" showWarning="True" developer="True" businessAnalyst="False" />

<Flag name="SQL.TableTriggers" description="Trigger Details" developer="True" businessAnalyst="False" />

</Flag>

Snipped for brevity...

</Flag>

</Flag>



Important Note:

The above XML may have wrapped due to restrictions in printed form, but each node should all be on a single line in the XML file.


Each flag corresponds to one of the lines in the dialog and is hierarchical in nature. Note that in the above XML snippet, two of the attributes on each flag corresponds directly to the key attribute of the output type in the OutputTypes section of the XML. Every flag must contain an attribute for each output type, indicating whether it should be included in the documentation (True) or excluded (False).


In this example, the Compact Table output type will essentially be a subset of the SQL Server node. Thus, the compactTable attribute should be set to False within each Flag except for on the SQL Server node. The modifications described above can be seen in the below XML sample.


<Flag name="SQL.Server" description="SQL Server" developer="True" businessAnalyst="True" compactTable="False" >


Next, add two new child flags (named SQL.CompactTable and SQL.Full) to the SQL.Server flag that are mutually exclusive with the developer and businessAnalyst attributes. These flags will be used within the next step to control which elements are included in the structure maps. After completely adding the new compactTable attribute to all flags as well as the two new nodes, the above example should appear as it does below. The bold sections are the new additions to the document control.


<Flag name="SQL.Server" description="SQL Server" developer="True" businessAnalyst="True" compactTable="True" >

<Flag name="SQL.CompactTable" description="Compact Table SQL Server" developer="False" businessAnalyst="False" compactTable="True" />

<Flag name="SQL.Full" description="Compact Table SQL Server" developer="True" businessAnalyst="True" compactTable="False" />

<Flag name="SQL.Configurations" description="Server Configurations" developer="True" businessAnalyst="True" compactTable="False" />

<Flag name="SQL.Database" description="Database Details" developer="True" businessAnalyst="True" compactTable="False" >

<Flag name="SQL.Tables" description="Table Details" developer="True" businessAnalyst="True" compactTable="False" >

<Flag name="SQL.SchemaDiagrams" description="Schema Diagrams" developer="True" businessAnalyst="False" compactTable="False" />

<Flag name="SQL.LineageImpact" description="Lineage and Impact" developer="True" businessAnalyst="False" compactTable="False" >

<Flag name="SQL.ImpactLists" description="Impact Details" developer="True" businessAnalyst="False" compactTable="False" />

<Flag name="SQL.LineageLists description="Lineage Details" developer="True" businessAnalyst="False" compactTable="False" />

</Flag>

<Flag name="SQL.TableColumns" description="Column Details" showWarning="True" developer="True" businessAnalyst="False" compactTable="False" />

<Flag name="SQL.TableForeignKeys" description="Foreign Key Details" showWarning="True" developer="True" businessAnalyst="False" compactTable="False" />

<Flag name="SQL.TableIndexes" description="Index Details" showWarning="True" developer="True" businessAnalyst="False" compactTable="False" />

<Flag name="SQL.TableTriggers" description="Trigger Details" developer="True" businessAnalyst="False" compactTable="False" />

</Flag>

Snipped for brevity...

</Flag>

</Flag>


Important Note:

The above XML may have wrapped due to restrictions in printed form, but each node should all be on a single line in the XML file.


Take note of the two flag names (SQL.CompactTable and SQL.Full) as they will be needed later. The SQL.Full flag will be associated with the original output types included with DOC xPress. The SQL.CompactTable flag will be associated with the new format currently being created.


Note carefully the values of the output type attributes. Within SQL.CompactTable flag, the developer and businessAnalyst attributes are set to False, while the compactTable attribute is set to true. Within SQL.Full flag, the output type attribute values are switched.


Additional information regarding the Document Control can be found here.


Step 2:

Modifying the Structure Maps


The Structure Map files, which all following the naming pattern StructureMap.*.xml, control the layout of the table of contents for the documents as well as which objects are associated with which templates. There are actually multiple structure map files that make up a single documentation. When document generation begins, DOC xPress starts with the root level of the object within the document layout. In this case, that root level is SQL Server. DOC xPress then uses the root object type as a guide to match it to a structure map.


To determine which structure map to initially use, DOC xPress examines each structure map file it finds within the templates folder. DOC xPress looks for the StructureMap node declaration, which is typically the second line within the structure map. Below can be found the StructureMap node for the StructureMap.Sql.Server.xml file:


<StructureMap typeMatch="Microsoft\.SqlServer\.Management\.Smo\.Server" >


The typeMatch attribute is a regular expression used to match the correct structure map to the root object's type. Every object cataloged by DOC xPress has a specific object type, but not every object has a structure map that matches that object type. DOC xPress examines the root object's type and then matches that object type to the Structure Map using its typeMatch attribute. If there DOC xPress finds multiple matches, it will only use the first structure map it finds, which may or may not be the desired result.


In order for users to properly determine the object type of the object they wish to add custom documentation, DOC xPress has a built in tool called the Metadata Viewer.


To use  xPress window will become enabled. Clicking the View button will automatically launch the Metadata Viewer.


Once the Metadata Viewer has loaded, root object of the metadata tree on the far left represents the selected in DOC xPress. Underneath the object's name is the object's type.


In this case, localhost's object type is Microsoft.SqlServer.Managment.Smo.Server. This matches directly to the typeMatch attribute for the StructureMap.Sql.Server.xml file.


In order to accommodate for the Compact Table output type created in Step 1, the StructureMap.Sql.Server.xml file will need to be modified such that only databases and tables are present without adversely affecting the original SQL Developer and Business Analyst output types.


To accomplish this, the SQL.Full and SQL.CompactTable flags that were added will be inserted into the StructureMap.Sql.Server.xml file in order to control which objects are displayed in the Structure Map (and hence the "Table of Contents").


Within the StructureMap.Sql.Server.xml file are two Objects that are child nodes to the Structure node. One object controls the table of contents for non-Azure Servers, while the second controls the table of contents for Azure Servers. Both Object nodes will need to be tagged in such a way that they will only work with the SQL Developer and Business Analyst output types. To do so, the flag attribute "SQL.Full", which was created in Step 1, will need to be added to both nodes. The modifications described above can be seen in the below XML sample.


<Object selector="." templateKey="SqlServer" flag="SQL.Full" condition="./[/Information[@Edition != &quot;SQL Azure&quot;] || !(/Information)]" >


Important Note:

The above XML may have wrapped due to restrictions in printed form, but it should all be on a single line in the XML file.


Case is very important when adding flags. In our modifications, the original flag in the control template file was "SQL.Full" and would not match to the flag "Sql.FULL".


Next, within the StructureMap.Sql.Server.xml file, scroll down to find the second Object declaration and modify it similarly to the first one:


<Object selector="." templateKey="SqlServer" flag="SQL.Full" condition="./[/Information[@Edition == &quot;SQL Azure&quot;]]" >


Finally, we need to add a third Object declaration handle to control the Compact Table output type that was created in Step 1. This new Object will be very simple, containing only the databases and none of the other objects, such as jobs, linked servers, et cetera. The Object node itself will be similar to the other two Objects, its selector will still be "." and its templateKey will also be "SqlServer". However, this object will not contain a condition attribute and will have its flag set to "SQL.CompactTable" instead. The modifications described above can be seen in the below XML sample.


<Object selector="." templateKey="SqlServer" flag="SQL.CompactTable" >

<ChildObjectsSubStructure selector="./Databases" condition="./Databases/" />

</Object>


The ChildObjectsSubStructure tells DOC xPress to search for another Structure Map to fill in the structure for this section, specifically the one for the Databases object. The structure map that controls databases (StructureMap.Sql.DatabaseCollection.xml) drills down into tables using a third structure map (StructureMap.Sql.Database.xml). Since these structure maps reach down into the tables, there is no need to modify them. Even though a database contains many objects, the document control that was modified in Step 1 will exclude all such objects when documenting using the Compact Table output type. Thus, DOC xPress will not attempt to generate documentation for these other, non-table objects. Since DOC xPress never generates the documentation for these items, it won't add an entry in the Table of Contents.


Important Note:

A good analogy for why this occurs would be the 13th floor of many buildings. Many buildings skip over the 13th floor when assigning floor numbers. Since there is no 13th floor, there is no need to put a 13th floor button in the elevator. Even though the elevator technicians may have wired the elevator for floor 13, since there is no button for the 13th floor, the elevator technician merely pushes the wires back and they are safely ignored.


In the standard documents generated by DOC xPress, selecting tables allows for the user to drill down further into individual column details. For the new Compact Table output type, this behavior will need to be altered so that the Table object becomes the lowest level. Thus, the structure map for tables will need to be altered to accommodate this change of behavior.


Find and open the StructureMap.Sql.Table.xml file. Within it, the columns, triggers, and indexes branches will need to be modified so that they are only displayed if the user has selected SQL Developer or Business Analyst and not the new Compact Table output type. These three sub-branches will need to have the flag attribute set to SQL.Full to accomplish this. The modifications described above can be seen in the below XML sample.


<Structure>

<Object selector="." templateKey="SqlTable" flag="SQL.Tables" >

<Object selector="Columns" templateKey="SqlColumnsCollection" flag="SQL.Full" condition="Columns/" >

<ChildObjects selector="$Object(Path:'./',OrderBy: Int(@PropertyValue('ID')))" flag="SQL.TableColumns" />

</Object>

<Object selector="ForeignKeys" templateKey="SqlForeignKeyCollection" flag="SQL.Full" condition="ForeignKeys/" >

<ChildObjects selector="./" flag="SQL.TableForeignKeys" />

</Object>

<Object selector="Indexes" templateKey="SqlIndexCollection" flag="SQL.Full" condition="Indexes/" >

<ChildObjects selector="$Object(Path:'./[@IndexType->&quot;Clustered&quot;]')" templateKey="SqlRelationalIndex" flag="SQL.TableIndexes" />

<ChildObjects selector="$Object(Path:'./[@IndexType->&quot;SpatialIndex&quot;]')" templateKey="SqlSpatialIndex" flag="SQL.TableIndexes" />

<ChildObjects selector="$Object(Path:'./[@IndexType->&quot;XmlIndex$&quot;]')" templateKey="SqlXmlIndex" flag="SQL.TableIndexes" />

</Object>

<Object selector="Triggers" templateKey="SqlTableTriggerCollection" flag="SQL.Full" condition="Triggers/" >

<ChildObjects selector="./" flag="SQL.TableTriggers" />

</Object>

</Object>

</Structure>


With the above modification, Columns, ForeignKeys, Indexes, and Triggers will only be displayed when the SQL.Full flag is set in the original document control file to True. With the structure maps now set, the final step is to modify the templates.


Additional information regarding structure maps can be found here.


Step 3:

Modifying the Template


Unlike the other files, the *.template files are not XML. Rather, they are a special template language used by DOC xPress to control the layout of each individual page within documentation. This introduction will not cover the entire language and only the functions necessary to achieve the original goal of this introduction will be discussed. A more in-depth discussion of the template language can be found here.


For purposes of this exercise, the only modifications that are necessary can be found within the SqlTable.template file. This file controls that visual layout of each SQL Server Table.


As with the structure maps edited in Step 2, SqlTable.template will be used by all output types to generate documentation, not just the new Compact Table output type. Thus, we need to ensure that any modifications made to SqlTable.template will not affect the SQL Developer or Business Analyst output types that are included within DOC xPress.


Fortunately, the template language does support simple programming constructs such as the if-else statement. Using an if-else statement, the document control can switch between two different sets of code depending on the output type used.


Opening up SqlTable.template, just below the DeclareSelector function, an If statement will need to be added that uses the FlagIsSet function to check to see if the SQL.CompactTable flag has been set to true. If the SQL.CompactTable flag has been set to true, the code within the If statement will be run. The modifications described above, as well as the new code can be seen in the below template sample.


01:

02:

03:

04:

05:

06:

07:

08:

09:

10:

11:

12:

13:

14:

15:

16:

17:

18:

19:

20:

21:

22:

23:

24:

If(FlagIsSet('SQL.CompactTable'))

{

If(Any(RunSelector('Columns')))

{

Table(RunSelector('Columns'),

         {'Column Name', 'Description', 'Data Type', 'Length', 'Can Be Empty' },

         {  

         Link($CurrentObject, @ObjectName),

         ParameterRequest('DataDictionaryEntry(Description)') ,

         @PropertyValue('SqlDataType').From($Object(Path:'DataType')),

         @PropertyValue('MaximumLength').From($Object(Path:'DataType')) == '-1' ?

('Maximum') : (@PropertyValue('MaximumLength').From($Object(Path:'DataType'))),

         Image(@PropertyValue('Nullable') == 'True'? ('True.png') : ('False.png'))

});

}

Else

{

Span('No columns are present for this table.');

}

}

Else

{

// Original Template

}


Important Note:

Line numbers have been added for purposes of this discussion and are not a part of the final code.


Line 1 has the already discussed If statement which checks to see if the SQL.CompactTable flag has been set. In line 3, another If statement checks to see if any columns exist. If no columns exist, the Else clause on line 16 triggers and only outputs a string notifying the user that the current table does not have any columns. If this was not done, then no columns would be returned by the Table function one line 5 and a large blank area would be present, leaving the user to wonder what happened.


Line 5 initiates a Table function, line 6 describes how many columns will be within the table as well as their names: Column Name, Description, Data Type, Length, and Can Be Empty, and lines 8 through 13 create a comma separated list for the values used within each column. Of interest is line 9, which contains a ParameterRequest function that retrieves a special value from the DOC xPress repository for the current column. The type of parameter is a DataDictionaryEntry that requires the name of the entry the template creator wishes to retrieve. In the case of line 9, the template creator wishes to retrieve the Description Data Dictionary Entry for each column. Users may add new columns to the Data Dictionary and may explicitly add them to their documentation by replacing Description with the name of the new Data Dictionary Entry they wish to include. The other lines make fairly standard calls to retrieve items from the DOC xPress snapshot.


Line 21 contains an Else statement the encapsulates the original template with two curly brackets (line 22 and 24). This Else statement will run when SQL.CompactTable is False.


Additional information regarding the template language can be found here.


Step 4:

Generating Documentation


After editing the document control, structure map, and templates to handle both the new output types and the original, generating documentation is the last step! Generating a document with the new output types is now as easy as using any of the built in types. After opening a solution in DOC xPress and clicking the Generate Documentation button, ensure that the Output Type is set to the new Compact Table. After selecting the desired output format, click the OK button to begin generating the documentation.



Important Note:

Note how the Structure Maps kicked in, and the Tables no longer drill down into the columns. In addition, the new template pages only show a compact view of the columns and hide the more robust details present within the standard templates.