<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
  xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" 
  xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" 
  xmlns:rs="urn:schemas-microsoft-com:rowset" 
  xmlns:z="RowsetSchema">
<xsl:output method="html"/>

<!-- global variables -->
<xsl:variable name="lowerabc">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="upperabc">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<xsl:variable name="breakalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate(/SPRTReportInstance/SPRTReport/Break/@breakcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable>
<xsl:variable name="breakdata"><xsl:value-of select="/SPRTReportInstance/SPRTReport/Break"/></xsl:variable>
<xsl:variable name="groupalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate(/SPRTReportInstance/SPRTReport/SubTotal/@groupcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable>
<xsl:key name="subtotal_key" match="rs:data/z:row" use="@*[name(.)=/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[@rs:name=/SPRTReportInstance/SPRTReport/SubTotal/@groupcol]/@aliasname]"/>
<xsl:variable name="countalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate(/SPRTReportInstance/SPRTReport/SubTotal/@countcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable>

<xsl:template match="/">
  <xsl:apply-templates select="SPRTReportInstance//SPRTReportOutput" />
</xsl:template>

<xsl:template match="SPRTReportInstance//SPRTReportOutput">
  <xsl:variable name="instanceguid"><xsl:value-of select="/SPRTReportInstance/SPRTReportInstanceInfo/InstanceGuid"/></xsl:variable>
  <html>
  <head>
  <STYLE>
BODY
{
  color:#000000;
  font:500 9pt Verdana, Arial, Helvetica, sans-serif;
  margin: 8px 8px 8px 16px;
  background-color: #FFFFFF;
}

TD
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
}

B
{
  FONT-FAMILY: Verdana, Arial, helvetica, sans-serif;
  FONT-WEIGHT: bold
}
P
{
  COLOR: black;
  FONT-FAMILY: Verdana,Arial, helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500;
  TEXT-INDENT: 0pt
}
P.rm
{
  COLOR: black;
  FONT-FAMILY: Arial, helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500;
  TEXT-ALIGN: right;
  TEXT-INDENT: 0pt
}
P.lm
{
  COLOR: black;
  FONT-FAMILY: Arial, helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500;
  TEXT-ALIGN: left;
  TEXT-INDENT: 0pt
}
P.intro
{
  COLOR: black;
  FONT-FAMILY: Verdana, Arial, helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500;
  TEXT-ALIGN: justify;
  TEXT-INDENT: 0pt
}
H3
{
  BACKGROUND: none transparent scroll repeat 0% 0%;
  COLOR: #993333;
  FONT: bold 15pt Helvetica,Arial,sans-serif;
  MARGIN-LEFT: 0px
}
H4
{
  BACKGROUND: none transparent scroll repeat 0% 0%;
  COLOR: #000000;
  FONT: bold 11pt Arial,Helvetica,sans-serif;
  MARGIN-LEFT: 0px
}
OPTGROUP
{
  color: #ffffff;
  background: #336699;
}
.white
{
  COLOR: #ffffff
}
.red
{
  COLOR: #990000
}
BLOCKQUOTE
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}
LI
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}
UL
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}
OL
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}
.sansmedblack
{
  COLOR: #000000;
  FONT-FAMILY:  Arial, Helvetica, sans-serif;
  FONT-SIZE: 12pt;
  FONT-WEIGHT: 700
}
.sansmedred
{
  COLOR: #cc0033;
  FONT-FAMILY:  Arial, Helvetica, sans-serif;
  FONT-SIZE: 12pt;
  FONT-WEIGHT: 700
}
.sansmedwhite
{
  COLOR: #ffffff;
  FONT-FAMILY:  Arial, Helvetica, sans-serif;
  FONT-SIZE: 12pt;
  FONT-WEIGHT: 700
}
.sansmedblack2
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 10px;
  FONT-WEIGHT: 500
}
.sanssmallblack
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}

.sanssmallred
{
  COLOR: #cc0033;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}

.sanssmallblue
{
  COLOR: #00309c;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 500
}

.sanssmallwhite
{
  COLOR: #ffffff;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 700;
 text-decoration: none;
}

.sanssmallbluebold
{
  COLOR: #00309c;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 900
}

.sanssmallblackbold
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 900
}
.sanssmallwhitebold
{
  COLOR: #ffffff;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 900
}
.sansxxsmallblack
{
  COLOR: #000000;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 8pt;
  FONT-WEIGHT: normal
}
.sansxsmallwhite
{
  COLOR: #ffffff;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 8pt;
  FONT-WEIGHT: 500
}
.serifsmallblack
{
  COLOR: #000000;
  FONT-FAMILY: Times, serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 400
}
.serifxsmallblack
{
  COLOR: #000000;
  FONT-FAMILY: Times, serif;
  FONT-SIZE: 7pt;
  FONT-WEIGHT: 400
}
.sanssmallwhite A
{
  COLOR: #ffffff;
  FONT-FAMILY: Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: 700;
  text-decoration: none;
}
.clsAnchor
{
  color: Blue;
  cursor: hand;
  cursor: pointer;
  text-decoration:underline;
}
.clsAnchor:hover
{
  color: Red;
  cursor: hand;
  cursor: pointer;
  text-decoration:underline;
}  
.tableheader{
  padding:1pt;
  padding-left:2pt;
  border-bottom:1px solid #DCDCDC;
  background:transparent url("/sdcadmin/images/crlist_texture.gif");
  color:#000000;
  font:700 9pt Arial,Helvetica,sans-serif;
  height:14px;
}
.tablecell
{
  border-right-width:1px;
  border-left-width:0px;
  border-top-width:1px;
  border-bottom-width:0px;
  border-style:solid;
  border-color:#000000;
}
.tableoutside
{
  border-right-width:0px;
  border-left-width:1px;
  border-top-width:0px;
  border-bottom-width:1px;
  border-style:solid;
  border-color:#000000;
}
.backnav
{
  COLOR: #dddddd;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 7.5pt;
  FONT-WEIGHT: 600;
  text-decoration: none;
}

.backnav A
{
  COLOR: #dddddd;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 7.5px;
  FONT-WEIGHT: 600;
  text-decoration: none;
}

.backnav  A:hover {
  COLOR: #ffffff;
  FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif;
  FONT-SIZE: 7.5pt;
  FONT-WEIGHT: 600;
  text-decoration: none;
}


.submenu A
{
  COLOR: #d3d3d3;
  FONT: 7.5pt Verdana, Arial, Helvetica, sans-serif;
  TEXT-DECORATION: none
}
.submenu A:hover
{
  COLOR: #ffcc00;
  FONT: 7.5pt Verdana, Arial, Helvetica, sans-serif;
  TEXT-DECORATION: none
}
.submenu
{
  FONT: 7.5px Verdana, Arial, Helvetica, sans-serif;
}
.actions A
{
  COLOR: #000080;
  FONT: 9pt Verdana, Arial;
  TEXT-DECORATION: none
}
.actions A:hover
{
  FONT: 9pt Verdana, Arial;
  BACKGROUND: #dadada;
  COLOR: #800000;
  FONT-WEIGHT: normal;
  TEXT-DECORATION: none
}
.actions
{
  FONT: 9pt Arial, Helvetica, sans-serif;
}
.divtab
{
  BACKGROUND-COLOR: darkolivegreen;
  BORDER-BOTTOM: thin;
  BORDER-LEFT: thin;
  BORDER-RIGHT: thin;
  BORDER-TOP: thin;
  COLOR: white;
  FONT-SIZE: 100px;
  FONT-VARIANT: small-caps;
  FONT-WEIGHT: bolder;
  HEIGHT: 30px;
  PADDING-TOP: 5pt;
  TEXT-ALIGN: center;
  TEXT-DECORATION: none;
  TEXT-TRANSFORM: capitalize;
  WIDTH: 100px
}
.swnu
{
  BACKGROUND-COLOR: transparent;
  COLOR: white;
  FONT-FAMILY: Arial;
  FONT-SIZE: 12px;
  FONT-WEIGHT: lighter;
  TEXT-DECORATION: none;
  TEXT-TRANSFORM: none
}
.swnu1
{
  COLOR: white;
  FONT-FAMILY: Arial;
  FONT-SIZE: 12px;
  FONT-WEIGHT: lighter;
  TEXT-TRANSFORM: none
}
.swnu2
{
  BACKGROUND-COLOR: transparent;
  COLOR: gold;
  FONT-FAMILY: Arial;
  FONT-SIZE: 12px;
  FONT-WEIGHT: lighter;
  TEXT-DECORATION: none;
  TEXT-TRANSFORM: none
}
.header {
 font-family: Arial,helvetica,sans-serif;
 font-size: 15pt;
 font-weight: bold;
 color: #000000;
}

.pageheader {
 font-family: Arial,helvetica,sans-serif;
 font-size: 16pt;
 color: #003366;
 line-height: 16px;
 font-weight: bold;
 white-space: nowrap;
}

.clsSubHeader {
 font-family: Arial,helvetica,sans-serif;
 font-size: 13pt;
 color: #003366;
 line-height: 13px;
 font-weight: bolder;
}

dl 
{
  margin-left:15px;
  margin-top:0px;
  font:500 10pt Verdana, Arial,Helvetica,sans-serif;
  text-indent:0px;
}

.entry{
  border:thin groove #DCDCDC;
  padding:1pt;
  float:none;
  margin:1px 1px 1px 1px;
  color:#191970;
  background:#FAFAFA;
  font:500 9pt Verdana, Arial,Helvetica,sans-serif;
  letter-spacing:0px;
  vertical-align: middle;
}

.entrynumeric{
  border:thin groove #DCDCDC;
  padding:1pt;
  float:none;
  margin:1px 1px 1px 1px;
  color:#191970;
  background:#FAFAFA;
  font:500 9pt Verdana, Arial,Helvetica,sans-serif;
  letter-spacing:0px;
  text-align:right;
}

.entrydisable{
  border:thin groove #DCDCDC;
  padding:1pt;
  float:none;
  margin:1px 1px 1px 1px;
  color:#191970;
  background:#eeeeee;
  font:500 9pt Verdana, Arial,Helvetica,sans-serif;
  letter-spacing:0px;
}

.crlist{
  padding:1pt;
  padding-left:2pt;
  border-bottom:1px solid #DCDCDC;
  background:transparent url("/sdcadmin/images/crlist_texture.gif");
  color:#000000;
  font:700 9pt Verdana,Arial,Helvetica,sans-serif;
  width:100%;
  height:14px;
}

.copyright  {
  COLOR : #999999;
  FONT-FAMILY : Verdana, Arial, Helvetica;
  FONT-SIZE : 7pt;
  FONT-WEIGHT : normal;
  text-decoration: none;
}

.copyright A   {
  COLOR : #999999;
  FONT-FAMILY : Verdana, Arial, Helvetica;
  FONT-SIZE : 7pt;
  FONT-WEIGHT : normal;
  text-decoration: none;
}

.tabs{
  height:16px;
  border:thin groove;
  color:#666666;
  font:bold 9pt Verdana, Arial, Helvetica;
  padding:1,2,3,2;
  text-decoration:none;
  background:#dddddd;
}
.tabs a{
  border:thin groove;
  color:#666666;
  font:bold 9pt Verdana, Arial,Helvetica,sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#dddddd;
}
.tabs a:hover{
  border:thin groove;
  color:#666666;
  font:bold 9pt Verdana, Arial, Helvetica, sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#cccccc;
}

.curtabs{
  height:16px;
  border:thin groove;
  color:#ffffff;
  font:bold 9pt Verdana, Arial, Helvetica, sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#003366;
}
.curtabs a{
  border:thin groove;
  color:#ffffff;
  font:bold 9pt Verdana, Arial, Helvetica, sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#003366;
}
.curtabs a:hover{
  border:thin groove;
  color:#ffffff;
  font:bold 9pt Verdana, Arial, Helvetica, sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#003366;
}

.dimtabs{
  height:16px;
  border:thin groove;
  color:#666666;
  font:bold 9pt Verdana, Arial, Helvetica, sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#dddddd;
}
.dimtabs a{
  border:thin groove;
  color:#666666;
  font:bold 9pt Verdana, Arial,Helvetica,sans-serif;
  padding:1,2,3,2;
  text-decoration:none;
  background:#dddddd;
}
.dimtabs a:hover{
	border: thin groove;
	color:#666666;
	font:bold 9pt Verdana, Arial,Helvetica,sans-serif;
	padding:1,2,3,2;
	text-decoration:none;
	background:#cccccc;
}

.navy {
  font-weight: bold; 
  color: navy;
}

.noscroll {
  scrollbar-3dlight-color:#FAFAFA; 
  scrollbar-arrow-color:#FAFAFA;
  scrollbar-base-color:#FAFAFA;
  scrollbar-darkshadow-color:#FAFAFA;
  scrollbar-face-color:#FAFAFA;
  scrollbar-highlight-color:#FAFAFA;
  scrollbar-shadow-color:#FAFAFA;
  border:thin groove #DCDCDC;
  padding:1pt;
  float:none;
  margin:1px 1px 1px 1px;
  color:#191970;
  background:#FAFAFA;
  font:500 9pt Arial,Helvetica,sans-serif;
  letter-spacing:0px;
}
.clsTreeNode
{
  cursor: hand;
  cursor: pointer;
  font-family :  verdana,helvetica,arial;
  font-size: 12px;
  font-weight: bolder;
  color: #505050;
}
.clsTreeNodeOver
{
  cursor: hand;
  cursor: pointer;
  font-family: verdana, helvetica, arial;
  font-size: 12px;
  font-weight: bold;
  background-color: #99bbee;
  color: #333333;
}
.clsTreeNodeText
{
  cursor: hand;
  cursor: pointer;
  font-family :  verdana,helvetica,arial;
  font-size: 12px;
  font-weight: bolder;
}
.clsTreeContainerNode
{
  cursor: hand;
  cursor: pointer;  
  border-top: 1px solid #eeeeee;
  border-left: 1px solid #eeeeee;
  border-bottom: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color : #dddddd;
  font-family : Verdana, sans-serif;
  font-size : 12px;
  font-weight: bolder;
  color: #666666;
  line-height: 12px;
  padding-left: 2px;
}
.clsTreeContainerNodeClicked
{
  cursor: hand;
  cursor: pointer;
  border-top: 1px solid #bbbbbb;
  border-left: 1px solid #bbbbbb;
  border-bottom: 1px solid #eeeeee;
  border-right: 1px solid #eeeeee;
  background-color : #dddddd;
  font-family : Verdana, sans-serif;
  font-size : 12px;
  font-weight: bolder;
  color: #666666;
  line-height: 12px;
  padding-left: 2px;
}
.clsTreeContainerNodeSelected
{
  cursor: hand;
  cursor: pointer;
  border-top: 1px solid #eeeeee;
  border-left: 1px solid #eeeeee;
  border-bottom: 1px solid #bbbbbb;
  border-right: 1px solid #bbbbbb;
  background-color : #cccccc;
  font-family: Verdana, sans-serif;
  font-size : 12px;
  font-weight: bold;
  color: #666666;
  line-height: 12px;
  padding-left: 2px;
}
.clsSpan
{
  margin-left: 12px;
}
.clsTreeLeaf
{
  cursor: hand;
  cursor: pointer;
  font-family: helvetica,verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #003399;
}
.clsTreeLeafMouseOver
{
  cursor: hand;
  cursor: pointer;
  font-family : helvetica,verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #003399;
  background-color: #99bbee;
}
.clsTreeLeafSelected
{
  cursor: hand;
  cursor: pointer;
  font-family: helvetica,verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #ffffff;
  background-color: #003377;
}
.clsTreeLeafDiv
{
  cursor: hand;
  cursor: pointer;
  font-family :  helvetica,verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #003399;
}
.clsTreeLeafDivMouseOver
{
  cursor: hand;
  cursor: pointer;
  font-family: verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #6699bb;
  background-color: #99bbee;
}
.clsTreeLeafDivSelected
{
  cursor: hand;
  cursor: pointer;
  font-family: verdana,arial;
  font-size: 12px;
  text-decoration: none;
  color: #ffffff;
  background-color: #003377;
}
.clsSubmit
{
  font-family: Arial, Helvetica, sans-serif;
  font-size: 12px;
  font-weight: bold;
  color: white;
  background-color: blue;
  border-style: outset;
  border: #ffffff;
  border-top-width: 3px;
  border-right-width: 3px;
  border-bottom-width: 3px;
  border-left-width: 3px;
}
.clsDataTable
{
  border-top-width: 3px;
  border-right-width: 3px;
  border-bottom-width: 3px;
  border-left-width: 3px;
}
.clsHeaderRow
{
  padding:1pt;
  padding-left:2pt;
  border-bottom:1px solid #DCDCDC;
  background-color: blue;
  color: white;
  font:700 9pt Arial,Helvetica,sans-serif;
  height:14px;
}
.clsHeaderCell
{
  padding:1pt;
  padding-left:2pt;
  border-bottom:1px solid #DCDCDC;
  background-color: #666666;
  color: white;
  font:700 9pt Arial,Helvetica,sans-serif;
  height:14px;
}
.clsDataOdd
{
  background-color: #FFFFCC;
}
.clsDataEven
{
  background-color: #DCDCDC;
}
.expandomatic
{
  border:thin groove #DCDCDC;
  padding:1pt;
  float:none;
  margin:1px 1px 1px 1px;
  color:#191970;
  background:#FAFAFA;
  font:500 8pt Verdana,Arial,Helvetica,sans-serif;
  scrollbar-base-color:#FAFAFA;
  scrollbar-darkshadow-color:#EEEEEE;
  scrollbar-face-color:#f5f5f5;
  scrollbar-track-color:#F8F8F8;
  scrollbar-shadow-color:#000000;
  scrollbar-highlight-color:#C0C0C0;
  scrollbar-arrow-color:#660033;
  letter-spacing:0px;
  height :250px;
  width : 100%;
  top : auto;
}
.clsReportAttrHeading
{
  COLOR: #000000;
  FONT-FAMILY: Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: bold
}
.clsReportAttrValue
{
  COLOR: #000000;
  FONT-FAMILY: Arial, Helvetica, sans-serif;
  FONT-SIZE: 9pt;
  FONT-WEIGHT: normal
}

.display
{
  border: thin solid #eeeeee;
  padding: 1px;
  float: none;
  margin: 1px 1px 1px 1px;
  color: #191970;
  background: #ffffff;
  font: 500 8pt Verdana, Arial, Helvetica, sans-serif;
  scrollbar-base-color: #ffffff;
  scrollbar-darkshadow-color: #ffffff;
  scrollbar-face-color: #ffffff;
  scrollbar-track-color: #ffffff;
  scrollbar-shadow-color: #ffffff;
  scrollbar-highlight-color: #ffffff;
  scrollbar-arrow-color: #ffffff;
  letter-spacing: 0px;
  height: 80px;
  width: 100%;
  top: auto;
}

/***** Table ListView Classes *******************************************************/
.clsTable1 /* Use in a TABLE tag of a gridview table */
{
	border: solid 1px #003366;
	background-color: #ffffff;
}

.clsTableHeader /* Use in the first row TD tag for a gridview table title row */
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 10pt;
  color: #ffffff;
  font: bold;
  letter-spacing: 1px;
  padding: 2px 8px 2px 8px;
  background-color: #336699;
  border: solid 1px;
  border-color: #99ccff #000033 #000033 #99ccff;
}

.clsTableSubHeader A /* Used for sortable column headers */
{
  color: #000000;
  text-decoration: none;
}

.clsTableSubHeader A:hover /* Used for sortable column headers */
{
  color: #cc3333;
  text-decoration: none;
}

.clsTableSubHeader /* Use in every TD tag of a gridview table column header row */
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8pt;
  color: #000000;
  font-weight: bold;
  background: #dddddd;
  padding: 3px;
  border: solid 1px;
  border-color: #ffffff #999999 #999999 #ffffff;
}

/* provide some interactivity on reports by providing the "pointer" to the user 
   on the table column headers */ 
table.sortable thead th, table.sortable thead td { cursor: hand; }
table.sortable thead th, table.sortable thead td { cursor: pointer; padding-left: 8px; }
table.sortable .updownarrow { padding: 2px; }


.clsTableRow1 /* Use in every TD tag of an even row (0,2,4...) of a gridview table */
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8pt;
  color: #000000;
  background-color: #ffffff;
  padding: 3px 4px 4px 4px;
  border-bottom: solid 1px #bbbbbb;
  vertical-align: middle;
}

.clsTableRow2 /* Use in every TD tag of an odd row (1,3,5...) of a gridview table */
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8pt;
  color: #000000;
  background-color: #eeeeee;
  padding: 3px 4px 4px 4px;
  border-bottom: solid 1px #bbbbbb;
  vertical-align: middle;
}


.clsTableGroupRowHeader 
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8pt;
  color: #000000;
  background-color: #ABBEDB;
  padding: 3px 4px 4px 4px;
  vertical-align: middle;
}

.clsTableCell
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8pt;
  color: #000000;
  padding: 3px 4px 4px 4px;
  border-bottom: solid 1px #bbbbbb;
}

.clsRowHasInput /* DEPRECATED: see .clsCellHasInput */
{
  padding: 0px;
  border-right: solid 1px #bbbbbb;
  background-color: #dddddd;
}

.clsTableRowMaster1
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 11px;
  color: #000000;
  background-color: #d9d9d9;
  border-bottom: solid 1px #bbbbbb;
  padding: 3px 4px 4px 4px;
}

.clsTextStandard12
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 12px;
  line-height: 18px;
  font-style: normal; 
}

.clsTextStandard11
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 11px;
  line-height: 16px;
  font-style: normal; 
}

.clsTextStandard10
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 10px;
  line-height: 14px;
  font-style: normal; 
}

.clsSubTable
{
  border-width: 1px 1px 0px 1px;
  border-style: solid;
  border-color: #cccccc;
}

.clsSubTableHeader
{
  background-color: #C0D0F0;
  border-style: solid;
  border-width: 1px;
  border-color: #EFF0FF #A0B0D0 #A0B0D0 #EFF0FF;
  margin: 0px;
  padding: 3px 4px 4px 4px;
  font-family: Verdana, Arial, sans-serif;
  font-size: 10px;
  font-weight: bold;
}

.clsSubTableRow1
{
  background-color: #F6F6FC;
  border-bottom: 1px solid #aaaaaa;
  margin: 0px;
  padding: 3px 4px 4px 4px;
  font-family: Verdana, Arial, sans-serif;
  font-size: 10px;
  font-weight: normal;
}

.clsSubTableRow2
{
  background-color: #DCE3F8;
  border-bottom: 1px solid #aaaaaa;
  margin: 0px;
  padding: 3px 4px 4px 4px;
  font-family: Verdana, Arial, sans-serif;
  font-size: 10px;
  font-weight: normal;
}

.clsTextButton2
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  color: #000000;
  background-image: url(/sdccommon/images/crs_button_tile.gif);
  border-bottom-width: 2px;   
}

.clsTextButton1 /* Use in an INPUT:SUBMIT or BUTTON for page-level buttons near the bottom or the page */
{ 
  background: #e0e1e5 url(/sdccommon/images/crs_button_tile.gif); 
  border: solid 1px;
  border-color: #3366ff #003366 #003366 #3366ff;
  color: #000000;
  cursor: hand; 
  cursor: pointer;
  font-weight: bold;
  margin: 8px 8px 0px 0px;
  filter: progid:DXImageTransform.Microsoft.dropShadow(Color=#cccccc, offX=1, offY=1);
}

.clsTextSmallButton1
{
  background: #cccccc url(/sdccommon/images/crs_button_tile.gif); 
  border: solid 1px;
  border-color: #3366ff #003366 #003366 #3366ff;
  color: #000000;
  padding: 0px;
  vertical-align: middle;
  cursor: hand;
  cursor: pointer;
  text-align: center;
  font: bold 9px Verdana, Arial, Helvetica, sans-serif;
  filter: progid:DXImageTransform.Microsoft.dropShadow(Color=#cccccc, offX=1, offY=1);
}

.clsLinkButton1
{
  color: #666666;
  font: bold 7pt Verdana, Arial, Helvetica, sans-serif;
  text-decoration: none;
}

.clsLinkButton1:hover
{
  color: #003366;
  font: bold 7pt Verdana, Arial, Helvetica, sans-serif;
  text-decoration: none;
}

.clsLinkButton1 A
{
  color: #666666;
  font: bold 7pt Verdana, Arial, Helvetica, sans-serif;
  text-decoration: none;
}

.clsLinkButton1 A:hover
{
  color: #003366;
  font: bold 7pt Verdana, Arial, Helvetica, sans-serif;
  text-decoration: none;
}

.clsCalendarButton
{
  vertical-align: middle;
}

.clsCellHasButton /* Use in a TD that contains either an ImageAction or TextAction button */
{
  padding: 1px;
  height: 21px;
  vertical-align: middle;
  width: 20px;
  background-color: #dddddd;
}

.clsCellHasInput /* Use in a TD that contains the left checkbox for a table */
{
  border-left: solid 1px #ffffff;
  border-right: solid 1px #999999;
  border-bottom: solid 1px #999999;
  background-color: #dddddd;
  padding: 0px 1px 0px 0px;
  width: 1px;
}

.clsImageAction1 /* Use in an A that contains an ImageAction button */
{
  vertical-align: middle;
  background-color: #ffffff;
  border: outset 1px white;
  padding: 1px;
}

.clsImageAction1:hover /* Hover state for above class */
{
  vertical-align: middle;
  border: solid 1px #003366;
  padding: 1px;
}

.clsTextAction1 /* Use in an A that contains a TextAction button */
{
  text-decoration: none;
  font: 7pt Verdana;
  color: #000099;
  vertical-align: top;
  background-color: #ffffff;
  border: outset 1px white;
  padding: 2px;
  height: 18px;  
}

.clsTextAction1:hover /* Hover state for above class */
{
  text-decoration: none;
  font: 7pt Verdana;
  vertical-align: top;
  color: #0000ff;
  border: solid 1px #003366;
  padding: 2px;
  height: 18px;
}

.clsScrollbar /* Use in a DIV or other object that needs to have custom scrollbar colors */
{
  scrollbar-3dlight-color: #cccccc;
  scrollbar-highlight-color: #ffffff;
  scrollbar-face-color: #eeeeee;
  scrollbar-shadow-color: #eeeeee;
  scrollbar-darkshadow-color: #999999;
  scrollbar-arrow-color: #000000;
  scrollbar-track-color: #99aabb;
}

/***** Agent Preview Content Classes *******************************************************/
.pvcItem
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8.5pt;
  text-decoration: none;
}

.pvcTCBX
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8.5pt;
  text-decoration: none;
  color: #000000;
  width: 20px;
}

.pvcCheckbox
{
  font-family: Helvetica, Verdana, Arial;
  font-size: 8pt;
  text-decoration: none;
}

.pvcContent
{
  font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
  font-size: 8.5pt;
  text-decoration: none;
  color: #000000;
  width: 50%;
}

.pvcTreeNode
{
  cursor: hand;
  cursor: pointer;
  font-family: Verdana, Helvetica, Arial;
  font-size: 9pt;
  font-weight: normal;
  padding: 0px;
  height: 12pt;
  border-top: solid 1px #ffffff;
}

.pvcTList
{
  padding: 0px;
  background: #fafafa;
  font: normal 8pt Arial, Helvetica, sans-serif;
}

.rule
{
  width: 500px;
  height: 1px;
  text-align: left;
  color: #000000;
}

.paragraph
{
  width: 500px;
}

#entrybox
{
	border: solid 1px #000000;
	padding: 2px 2px 2px 2px;
	background-color: #eeeeee;
	margin: 0px;
}

/***** SprtUI TabStrip Classes *******************************************************/
.tabStrip
{
  font:bold 9pt Verdana, Arial, Helvetica;
  color: #e6e6e6;
  background: url(/sdccommon/images/ctb_unselected_tile.gif);
  padding: 2px 4px 0px 4px;
}

.tabStrip A
{
  font:bold 9pt Verdana, Arial, Helvetica;
  color: #e6e6e6;
  text-decoration: none;
}

.tabStrip A:hover
{
  font:bold 9pt Verdana, Arial, Helvetica;
  color: #51595f;
  text-decoration: none;
}

.tabStripSel
{
  font:bold 9pt Verdana, Arial, Helvetica;
  color: #000000;
  background: url(/sdccommon/images/ctb_selected_tile.gif);
  padding-top: 3px;
  padding: 0px 4px 0px 4px;
}

.tabStripSel A
{
  font:bold 9pt Verdana, Arial, Helvetica;
  color: #000000;
  text-decoration: none;
}

.tabStripTop
{
  font: 9pt Verdana, Arial, Helvetica;
  background: url(/sdccommon/images/ctb_frame_t.gif);
}

.tabStripTop2
{
  border-left: solid 1px #003366;
  background: url(/sdccommon/images/ctb_frame_tile.gif);
}

.tabStripBottom
{
  background: url(/sdccommon/images/ctb_frame_b.gif);
}

.tabStripMain
{
  font: 9pt Verdana, Arial, Helvetica;
  color: #000000;
  background: url(/sdccommon/images/ctb_frame_tile.gif);
  border-left: solid 1px #003366;
  border-right: solid 1px #003366;
  padding: 4px 8px 4px 8px;
  vertical-align: top;
}

.tabStripBody
{
  display: none;
  font: 9pt Verdana, Arial, Helvetica;
  color: #000000;
}

/***** SprtUI EditableDropDown Classes *******************************************************/
.clsPullDown 
{
  border:thin groove #eeeeee;
  background: #fafafa;
	padding: 0px;
  position: absolute;
  overflow: auto;
}

.clsPullDownText
{
  height: 22px;
}

.clsSelectOptions
{
  border: thin groove #eeeeee; 
  background: #fafafa; 
  padding: 0pt;
  position: absolute;
  overflow: auto;
}

.clsPullDownSelected
{
  color: #ffffff;
  background: #003399;
}

.clsPullDownHover
{
   background: #ccddff;
}

.clsPullDownUnSelected
{
   background: #ffffff;
}


  </STYLE>
  <script type="text/javascript">
<![CDATA[
var ssTableSort = new ssTableSortType();

function ssTableSortType () {
  //
  //  These are the configurable values for the page, where we can define
  //  the className which determines a table is sortable, what the asc and and desc
  //  sorting arrows look like, and what classNames to use for alternating row colors.
  //
  var gDEBUG = false;

  var gSortableTableClass      = "sortable";
  var gShowOnLoad              = "showonload";
  var gNonSortableColumnClass  = "notsortable";
  var gUpDownArrowClassName    = "updownarrow";
  var gSortAscHTML             = "&uarr;";
  var gSortDescHTML            = "&darr;";
  var gEvenRow                 = "clsTableRow2";
  var gOddRow                  = "clsTableRow1";
  var gWaitDivID               = "SortBusyWaitDiv";
  var gWaitDivText             = "SortingSorting Table...Table...";
  var gWaitDivTRCountThreshold = 55;
  var gCastStringToLowerCase   = true;

  // readable constants
  var WAIT_START    = true;
  var WAIT_COMPLETE = false;

  var HIDE_WAIT_MSG = false;
  var SHOW_WAIT_MSG = true;

  //
  //  data containers
  //
  var gSortTypes           = {};
  var gSortValFns          = {};
  var gSortKey             = {};
  var gTableCopies         = {};
  var gTableDataCached_Raw       = {};
  var gTableDataCached_Converted = {};
  var gWaitStates          = {};
  var gTableToSort         = {};
  var gStoredSortData      = {};
  var gDelayedSortTimer;


  //
  //  how many columns can be considereed when sorting?
  //  leaving this at 0, or setting it too high can have a negative
  //  impact on the sorting performance after sorting by many different columns.
  //
  var gMaxSortColumns = 2; // >=1 to enable limiting

  //
  //  uniqueID generator
  //
  var gInstanceKey    = (new Date()).valueOf();

  //
  //  these maximum values are used when sorting anomolies or blanks, relative to
  //  other data of the same data type.
  //
  var MAX_NUMBER      = Number.MAX_VALUE;
  var MAX_NUMBER_2    = MAX_NUMBER * .99;
  var MAX_STRING      = "MAX_STRINGMAX_STRING";
  var MAX_DATE        = (new Date ("5/27/9999")).valueOf();


  //
  //  Entry Point -- Attach to the page after the page has loaded.
  //
  sstsAttachEvent(window,'load',sstsSetupTableForSorting);

  //
  // Expose a refresh Method which allows us to attach to tables that
  // may have been created after the onload event fired.
  //
  this.refresh = function () {
    sstsSetupTableForSorting(null,true);
  }

  //
  // Expose a SortByColumn method
  //  Mostly used for performance testing, but can be used
  //  to programmatically sort a table column iColumn.
  this.SortByColumn = function (oTable,iColumn,bUseClickHandler) {
    var HeaderRow   = sstsGetLastOrAddEmptyElementRow(oTable,"THEAD");
    var HeaderCells = sstsGetRowCells(HeaderRow);
    if (HeaderCells.length > iColumn) {
      var SortColumn  = HeaderCells[iColumn];
      try {
        SortColumn.fireEvent("onclick");
      } catch (e) {
        var Event = new Object();
        Event.target = SortColumn;
        window.event = Event;
        return sstsElementClickHandler(Event);
      }
    }
    return false;
  }


  function sstsAttachEvent(oElm,sEvent,fnHandler) {
    try {
      if (sEvent.indexOf("on")==0)
        sEvent = sEvent.substring(2);
      if (typeof oElm.addEventListener != 'undefined')
        oElm.addEventListener(sEvent,fnHandler,true);
      else if (typeof oElm.attachEvent != 'undefined')
        oElm.attachEvent('on'+sEvent,fnHandler);
      else
        oElm[sEvent]=fnHandler;
    } catch (e) {
      return false;
    }
    return true;
  }

  //
  // Attach to any table with a className of "sortable" (specified through gSortableTableClass)
  //
  function sstsSetupTableForSorting(oTable,bRefresh)
  {
    var oTables,sTableClass,oTableHead,cTableHeaderRows,cTableDataRows;
    var oTableFoot,oTableBody;
    //
    // if oTable is a single table, make an array with only that table.
    // otherwise we'll work on every table in the page.
    //
    if (typeof(oTable)!='undefined'&&oTable!=null&&oTable.tagName=='TABLE') {
      oTables = [oTable];
    } else {
      oTables = document.getElementsByTagName("TABLE");
    }

    for (var i=0; i<oTables.length; i++)
    {
      oTable = oTables[i];
      sTableClass = oTable.className.toLowerCase();

      if (sTableClass.indexOf(gSortableTableClass) != -1) {
        oTableHead = sstsGetOrAddTableElement(oTable,"THEAD");
        oTableFoot = sstsGetOrAddTableElement(oTable,"TFOOT");
        oTableBody = sstsGetOrAddTableElement(oTable,"TBODY");

        cTableHeaderRows = oTableHead.getElementsByTagName("TR");
        oTableDataRows   = sstsGetTableDataRows(oTable);

        if ( oTableDataRows.length > 0 ) { // don't attach to tables without data.

          // Add a header row for Directional Arrows
          oTableSortRow = sstsGetLastOrAddEmptyElementRow(oTable,"THEAD");

          // Add Directional Arrows
          sstsAddSortArrowsToCells(oTableSortRow);

          // Reload the table sorting state from the table's parent form's tablesort_data element.
          if (sstsSetupDefaultSortParametersForTable(oTable,bRefresh) == true) {

            if (oTable.TableDataIsSorted != "true") {
              if (oTableDataRows.length > gWaitDivTRCountThreshold) {
                sstsSetWaitState(WAIT_START,SHOW_WAIT_MSG);
                setTimeout(function () { sstsSortTableDelayed(oTable,true) } , 0);
              } else {
                sstsSetWaitState(WAIT_START,HIDE_WAIT_MSG);
                sstsSortTableDelayed(oTable,true);
              }
            }
            else {
              // only respect TableSortDataIsStored the first time.
              oTable.TableSortDataIsStored = "";
            }
          }
          else if (sTableClass.indexOf(gShowOnLoad)>-1) {
            // if gShowOnLoad then set the display attribute of the
            // table to "" (allowing classes to take over)
            // allows sorting "behind the scenes" -- used in patch+ patch listings.
            oTable.style.display = "";
          }
        }
      }
    }
  }

  //
  //  Main Sorting Function
  //
  function sstsSortTable(oTable) {
    //  generate a unique id for tables without them, to cache information for that table.
    //
    if (!oTable.id) {
      oTable.id = "key"+(++gInstanceKey);
      oTable.persistSort = false; // cannot persist the sort of an unnamed table.
    }

    // assign default sorts if missing
    //
    // re-read the form value 'tablesort_data' in the form containing this table
    // or the first form in the page if this table is not contained in a form
    //
    sstsSetupDefaultSortParametersForTable(oTable);

    // setup sort key
    //
    gSortKey[oTable.id] = sstsGetSortKeyForTable(oTable);

    //  cast and cache the data in the table into a data structure we can re-use.
    //
    sstsCacheTableData(oTable);

    //  build sortable array
    //
    var aSortingArray = [];
    sstsPopulateSortingArray(oTable,aSortingArray);

    //  Sort the aSortingArray using sstsDataComparer and his helpers
    //
    aSortingArray.sort(sstsDataComparer);

    //  correct the sort direction, hopefully simplifying the sort function
    //
    if (oTable.getAttribute("sortDirection")*1==1)
      aSortingArray.reverse();

    //
    // add totals per grouping rules which should be applied to oTable
    //
    sstsAddTotals(oTable,aSortingArray);

    //  iterate the sorted bin, copy the row from the original table to our temp table
    //
    sstsReplaceTableWithSortedCopy(oTable,aSortingArray);

    // show which direction its sorting the PRIMARY column
    //
    sstsUpdateDirectionalArrows(oTable);

    //  color alternating rows
    //
    sstsResetAlternatingRowClassNames(oTable);

    // store the sorting array
    //
    sstsPersistSortState(oTable)
  }

  function sstsSortTableDelayed(oTable, bShowTable) {
    oTable = oTable || gTableToSort;
    if (typeof(oTable) != 'undefined' && oTable.tagName == "TABLE") {
      sstsSortTable(oTable);
      sstsSetWaitState(WAIT_COMPLETE);
      if (bShowTable && oTable.className.toLowerCase().indexOf(gShowOnLoad)>-1) {
        oTable.style.display="";
      }
    }
  }

  //
  //  event handler for the TH items, attached to the first row within the table.
  //
  function sstsElementClickHandler(evt) {
    evt=evt||event;
    var src  = evt.target||evt.srcElement;
    var src2 = sstsGetParentNodeByTagName(src,'TH');
    if (! src2 ) src2 = sstsGetParentNodeByTagName(src,'TD');
    src = src2;
    if (src && src.parentNode && src.className.indexOf(gNonSortableColumnClass)==-1) {
      var parentTable,parentRow;
      parentRow = sstsGetParentNodeByTagName(src,'TR');
      var cCells = sstsGetRowCells(parentRow);
      for (var i=0; i<cCells.length; i++) {
        if (cCells[i] === src) {
          parentTable = sstsGetParentNodeByTagName(parentRow, 'TABLE');
          if (parentTable.className.indexOf(gSortableTableClass)>-1) {
            if (parentTable.getAttribute("sortColumn")*1 == i) {
              parentTable.setAttribute("sortDirection", parentTable.getAttribute("sortDirection")*1==0?1:0);
            } else {
              parentTable.getAttribute("sortDirection", 0);
              parentTable.setAttribute("sortColumn", i);
            }
           //try {
              evt.cancelBubble = true;
              evt.returnValue  = false;

              if (parentTable.getElementsByTagName("TR").length > gWaitDivTRCountThreshold) {
                ShowWaitMsg = SHOW_WAIT_MSG;
                sstsSetWaitState(WAIT_START,SHOW_WAIT_MSG);
                if (gDelayedSortTimer)
                  clearTimeout(gDelayedSortTimer);
                gDelayedSortTimer = setTimeout(function () { sstsSortTableDelayed(parentTable) } , 0);
              }
              else {
                sstsSetWaitState(WAIT_START,HIDE_WAIT_MSG);
                sstsSortTableDelayed(parentTable);
              }

              return false;
            /*} catch (e) {
              alert(
                "Problem Encountered When Sorting By Column " +
                (parentTable.getAttribute("sortColumn")*1+1) + "\n\nError: " + e.message
              );
            }*/
          }
        }
      }
    }
    return false;
  }

  function sstsGetSortKeyForTable(oTable) {
    //
    // start an array with the primary sort column
    var mySortKey = [oTable.getAttribute("sortColumn")*1];

    if (typeof(gSortKey[oTable.id])=='undefined')
      gSortKey[oTable.id] = [];

    //
    // append to it the previous sort columns, exluding this one.
    for (var i=0; i<gSortKey[oTable.id].length; i++) {
      if (gSortKey[oTable.id][i] != oTable.getAttribute("sortColumn")*1)
        mySortKey.push(gSortKey[oTable.id][i]);
    }

    if (gMaxSortColumns>0 && gMaxSortColumns<mySortKey.length)
      mySortKey.length=gMaxSortColumns;

    Debugger.Debug("TableRef Sort Key ", mySortKey.join('-'));
    return mySortKey;
  }

  function sstsSetupDefaultSortParametersForTable(oTable,bRefresh) {
    if (oTable.sstsFormIndexed != "true" && oTable.sstsFormIndexed != true ) {

      oTable.sstsFormIndexed = true;

      var bTableHasSortData = oTable.getAttribute("sortColumn") != undefined || oTable.getAttribute("sortDirection") != undefined;

      if (oTable.getAttribute("sortColumn") == undefined) {
        oTable.setAttribute("sortColumn", 0);
      } else {
        var iSortColumn = oTable.getAttribute("sortColumn")*1*1;
        var cDataCells  = sstsGetRowCells(sstsGetTableDataRows(oTable)[0]);
        if (iSortColumn > cDataCells.length-1) {
          oTable.setAttribute("sortColumn", cDataCells.length-1);
        }
      }

      if (oTable.getAttribute("sortDirection") == undefined) {
        oTable.setAttribute("sortDirection", 0);
      } else {
        oTable.setAttribute("sortDirection", oTable.getAttribute("sortDirection")*1);
        if (oTable.getAttribute("sortDirection")*1 < 0 || oTable.getAttribute("sortDirection")*1 > 1) {
          oTable.setAttribute("sortDirection", 1);
        }
      }

      var oTableParentForm = sstsGetParentNodeByTagName(oTable,'form');

      var i;

      if ( oTableParentForm != null ) {
        if (oTableParentForm.elements['tablesort_data'] != undefined) {
          var storedDataRaw   = oTableParentForm.elements['tablesort_data'].value;
          var storedDataPairs = storedDataRaw.split("&");
          var storedDataChunks,storedDataTableID;
          for (i=0; i<storedDataPairs.length; i++) {
            if (storedDataPairs[i]) {
              storedDataChunks = unescape(storedDataPairs[i]).split("=");
              storedDataTableID = storedDataChunks[0];
              gStoredSortData[storedDataTableID] = storedDataChunks[1];
            }
          }
          if (gStoredSortData[oTable.id] != undefined) {
            var storedData  = gStoredSortData[oTable.id];
            var storedDir   = storedData.split("|")[0]*1;
            var storedKeys  = storedData.split("|")[1].split(":");
            gSortKey[oTable.id] = [];
            for (i=0; i<storedKeys.length; i++) {
              gSortKey[oTable.id].push(storedKeys[i]*1);
            }
            oTable.setAttribute("sortColumn", 1*gSortKey[oTable.id][0]);
            oTable.setAttribute("sortDirection",storedDir);
          }
          bTableHasSortData = true;
        }
        return bTableHasSortData;
      }
    }
    return false;
  }

  function sstsPersistSortState(oTable)
  {
    if (oTable.persistSort != false && oTable.persistSort != "false") {
      var oTableParentForm = sstsGetParentNodeByTagName(oTable,'form');
      if (oTableParentForm != null) {
        if (oTableParentForm.elements['tablesort_data'] != undefined) {
          var SortCols = gSortKey[oTable.id];
          if (SortCols != undefined) {
            SortCols = SortCols.join(':');

            var SortDir = oTable.getAttribute("sortDirection")*1;
            if (SortDir != undefined) {

              var sStoredSortData = SortDir + '|' + SortCols;
              gStoredSortData[oTable.id] = sStoredSortData;

              var aStoredSortData = [];

              for (var i in gStoredSortData) {
                aStoredSortData.push(escape([i,gStoredSortData[i]].join('=')));
              }

              oTableParentForm.elements['tablesort_data'].value = aStoredSortData.join('&');
              return true;
            }
          }
        }
      }
    }
  }

  function sstsCacheTableData(oTable) {
    try {
      if (typeof(gTableDataCached_Raw[oTable.id]) == 'undefined') {

        sstsCacheTableDataTypesFromSample(oTable);
        
        var iRowsPerRecord = (oTable.getAttribute("RowsPerRecord")||"1")*1 || 1;

        gTableDataCached_Raw[oTable.id]       = [];
        gTableDataCached_Converted[oTable.id] = [];
        gTableCopies[oTable.id]         = oTable.cloneNode(true);

        var cTableDataRows_Raw       = gTableDataCached_Raw[oTable.id];
        var cTableDataRows_Converted = gTableDataCached_Converted[oTable.id];

        var oTableDataRows = sstsGetTableDataRows(oTable);

        var oCurrentRowCells,oCurrentCell,oCurrentCellHTML,oCurrentRow;
        
        for (var i=0; i<oTableDataRows.length; i+=iRowsPerRecord) {
          oCurrentRow = oTableDataRows[i];
          oCurrentRowCells = sstsGetRowCells(oCurrentRow);
          cTableDataRows_Raw[i]       = [];
          cTableDataRows_Converted[i] = [];
          oCurrentRowOfDataCells  = cTableDataRows_Raw[i];
          oCurrentRowOfDataCellsConverted = cTableDataRows_Converted[i];
          //Debugger.Debug("Processing Row " , i);
          for (var i2=0; i2<oCurrentRowCells.length; i2++) {
            oCurrentCell = oCurrentRowCells[i2];
            if (oCurrentCell.getAttribute("sortvalue") != undefined) {
              oCurrentCellHTML = oCurrentCell.getAttribute("sortvalue");
            } else {
              if (typeof(oCurrentCell.innerText) != 'undefined')
                oCurrentCellHTML = oCurrentCell.innerText;
              else
                oCurrentCellHTML = oCurrentCell.innerHTML;
            }
            oCurrentRowOfDataCells.push(oCurrentCellHTML);
            oCurrentRowOfDataCellsConverted.push(gSortValFns[oTable.id][i2](oCurrentCellHTML));
            //Debugger.Debug("Cell Data", oCurrentCellHTML);
            //Debugger.Debug("Cell DataC", gSortValFns[oTable.id][i2](oCurrentCellHTML));
            //Debugger.Debug("Conv Fn ", gSortValFns[oTable.id][i2].toString() );
          }
        }
      }
      return true;
    } catch (sstsCacheTableDataERROR) {
      return false;
    }
  }

  function sstsCacheTableDataTypesFromSample(oTable) {
    Debugger.Debug("sstsCacheTableDataTypesFromSample");
    gSortTypes[oTable.id]  = {};
    gSortValFns[oTable.id] = {};
    var oTableDataHeaderCells    = sstsGetRowCells(sstsGetLastOrAddEmptyElementRow(oTable,"THEAD"));
    var oTableDataRowSampleCells = sstsGetRowCells(sstsGetFirstDataRow(oTable));
    var sSortType;
    for (var iColumn=0; iColumn<oTableDataRowSampleCells.length; iColumn++) {
      sSortType = sstsGetSortTypeFromSample(oTableDataHeaderCells[iColumn],oTableDataRowSampleCells[iColumn]);
      gSortTypes[oTable.id][iColumn]  = sSortType;
      gSortValFns[oTable.id][iColumn] = sstsDataTypeFunctionMap[sSortType];
    }
    Debugger.Debug("gSortTypes[oTable.id][oTable.getAttribute('sortColumn')*1]",gSortTypes[oTable.id][oTable.getAttribute("sortColumn")*1]);
  }

  function sstsPopulateSortingArray(oTable,aSortingArray) {
    var Cells,valFn,itemSortKey,sortData;
    var iRowsPerRecord = (oTable.getAttribute("RowsPerRecord")||"1")*1 || 1;
    var cConvertedDataRows = gTableDataCached_Converted[oTable.id];
    for (var i=0; i<cConvertedDataRows.length; i+=iRowsPerRecord) {
      itemSortKey = [];
      Cells = cConvertedDataRows[i];
      for (var i2=0; i2<gSortKey[oTable.id].length; i2++) {
        //sortData = Cells[gSortKey[oTable.id][i2]];
        itemSortKey.push(Cells[gSortKey[oTable.id][i2]]);
      }
      aSortingArray.push([itemSortKey,i]);
    }
    Debugger.Debug('Sorting Array: ' + aSortingArray.join('<br>'));
  }

  function sstsUpdateDirectionalArrows(oTable) {
    var oArrow,cArrows;
    var oTableSortingRow = sstsGetLastOrAddEmptyElementRow(oTable,"THEAD")
    var cRowCells = sstsGetRowCells(oTableSortingRow)
    for (var i=0; i<cRowCells.length; i++) {
      cArrows = cRowCells[i].getElementsByTagName("SPAN");
      for (var i2=0; i2<cArrows.length; i2++) {
        oArrow = cArrows[i2];
        if (oArrow && oArrow.className == gUpDownArrowClassName) {
          if (i!=oTable.getAttribute("sortColumn")*1) {
            oArrow.style.visibility="hidden";
          }
          else {
            oArrow.style.visibility="visible";
            oArrow.innerHTML = oTable.getAttribute("sortDirection")*1 ? gSortDescHTML : gSortAscHTML;
          }
        }
      }
    }
  }

  function sstsResetAlternatingRowClassNames (oTable) {
    var cTableDataRows = sstsGetTableDataRows(oTable)
    for (var i=0; i<cTableDataRows.length; i++) {
      if ((i%2)==0)
        cTableDataRows[i].className = gOddRow;
      else
        cTableDataRows[i].className = gEvenRow;
    }
  }

  function sstsAddTotals(oTable,aSortingArray) {
    // accept arguments on totalling through oTable props?  probably the best idea.
    //TBD TODO
  }

  function sstsGetParentNodeByTagName(elm,tag) {
    try {
      while (elm) {
        if (elm && elm.tagName.toUpperCase() == tag.toUpperCase())
          return elm;
        elm = elm.parentNode;
      }
    } catch (e) {
      //Debugger.Exception("sstsGetParentNodeByTagName", e.description);
    }
    return null;
  }

  function sstsSetWaitState( bWaiting, bShowWaitMsg )
  {
    var waitDiv;
    waitDiv = document.getElementById(gWaitDivID);
    if (waitDiv == null) {
      waitDiv = document.body.appendChild(document.createElement("div"));
      waitDiv.id = gWaitDivID;
      waitDiv.innerHTML = gWaitDivText;
      waitDiv.style.cssText = "width: 150px; padding: 5px; background-color: #FFF; border: 1px solid black; font-family: verdana,arial,sans-serif; font-size: 12px; position:absolute; text-align: center;";
    }
    if (WAIT_START == bWaiting) {
      var evtY = window.event ? window.event.clientY : 0;
      var evtX = window.event ? window.event.clientX : 0;
      if (SHOW_WAIT_MSG == bShowWaitMsg) {
        waitDiv.style.top     = (evtY+20) + "px";
        waitDiv.style.left    = (evtX-(waitDiv.offsetWidth/2))  + "px";
        waitDiv.style.display = "block";
      }
      document.body.style.cursor = "wait";
    }
    if (WAIT_COMPLETE == bWaiting ) {
      waitDiv.style.display = "none";
      document.body.style.cursor = "";
    }
  }

  function sstsGetElementXYObject(src){
    var a = sstsGetElementXYArray(src);
    return {x:a[0],y:a[1]};
  }

  function sstsGetElementXYArray(src) {
    var xy=[0,0];
    var p = src;
    while (p) {
      xy[0]+=p.offsetLeft;
      xy[1]+=p.offsetTop;
      p=p.offsetParent;
    }
    return xy;
  }

  //
  //  Data Comparison
  //
  function sstsDataComparer(a,b) {
    return sstsDataComparerHelper(a[0],b[0],0,-1);
  }
  function sstsDataComparerHelper(a,b,i,ret) {
    //
    // handle arrays (versions and ip addresses) first
    if (typeof(a[i])=='object') {
      ret = sstsDataComparerArrayHelper(a[i],b[i],0);
    }

    //
    // special case MAX_STRING (used for empty cells)
    else if (a[i]==MAX_STRING||b[i]==MAX_STRING) {
      ret = a[i]==MAX_STRING?1:-1;
    }

    //
    // handle basic data types
    else {
      if (a[i] < b[i]) {
        ret = -1;
      } else if (a[i] > b[i]) {
        ret = 1;
      } else if ( (a.length>i+1) && (b.length>i+1) ) {
        ret = sstsDataComparerHelper(a,b,i+1);
      } else if (a.length > b.length) {
        ret = 1;
      } else if (b.length == a.length) {
        ret = 0;
      }
    }
    return ret;
  }
  //
  // loop through an array starting at element 0
  // comparing element i to i of each array
  // such as [1,2,3,4] vs [1,2,3,5];
  // when i == 0, a[i] == b[i]
  // when i == 1, a[i] == b[i]
  // when i == 2, a[i] == b[i]
  // when i == 3, a[i] <  b[i] return -1
  //
  // this function casts every array member to a number.
  //
  function sstsDataComparerArrayHelper(a,b,i,aVal,bVal) {
    if (! isNaN((aVal=a[i]*1)) && ! isNaN((bVal=b[i]*1))) {
      if (aVal < bVal) {
        return -1;
      } else if (aVal > bVal) {
        return 1;
      } else if ( (a.length>i+1) && (b.length>i+1) ) {
        return sstsDataComparerArrayHelper(a,b,i+1);
      } else if (a.length > b.length) {
        return 1;
      } else if (b.length == a.length) {
        return 0;
      }
    }
    return -1;
  }

  function sstsReplaceTableWithSortedCopy(oTable,aSortingArray) {
    //
    // Based on the order listed in aSortingArray, clone
    // the appropriate rows into the table's body
    //

    /*
      BUGFIX:  While the following line is correct, and should be
               faster than removing each row individually,
               IE Crashes with removeChild on TBODY.  To avoid this
               we'll slowly remove each node within the TBODY
               before appending the new ones.
      OLD: oTable.removeChild(oTable.getElementsByTagName("TBODY")[0]);
    */
    var oTableBody = sstsGetOrAddTableElement(oTable,"TBODY");
    var cRows = sstsGetTableDataRows(oTable);
    var iCount = cRows.length-1;
    var iRowsPerRecord = (oTable.getAttribute("RowsPerRecord")||"1")*1 || 1;
    while(iCount >= 0) { // Massacre
      oTableBody.removeChild(cRows[iCount--]);
    }
    var oCopiedTableDataRows = sstsGetTableDataRows(gTableCopies[oTable.id]);
    var iSortedRowReference = -1;
    for (var i=0; i<aSortingArray.length; i++) { // ProCreate
      iSortedRowReference = aSortingArray[i][1];
      oTableBody.appendChild(oCopiedTableDataRows[iSortedRowReference].cloneNode(true));
      if (iRowsPerRecord > 1) {
        for (var iExtraRows=1; iExtraRows<iRowsPerRecord; iExtraRows++) { 
          oTableBody.appendChild(oCopiedTableDataRows[iSortedRowReference+iExtraRows].cloneNode(true));
        }
      }
    }
    return true;
  }


  function sstsGetOrAddTableElement(oTable,sElementTag) {
    if (oTable) {
      var oChildren = oTable.getElementsByTagName(sElementTag);
      if ( oChildren != null && oChildren != undefined && oChildren.length > 0) {
         return oChildren[0];
      } else {
        return oTable.appendChild(document.createElement(sElementTag));
      }
    }
    return null;
  }
  function sstsGetLastOrAddEmptyElementRow( oTable, sElementTag ) {
    var oTableElement = sstsGetOrAddTableElement(oTable,sElementTag);
    var oTableRows = oTableElement.getElementsByTagName("TR");
    if (oTableRows.length > 0) {
      return oTableRows[oTableRows.length-1]; // Last
    }
    var oTableRow  = sstsAddRow(oTableElement);
    var oTableBody = sstsGetOrAddTableElement(oTable,"TBODY");
    var oDataRow   = sstsGetFirstDataRow(oTable);
    if (oDataRow) {
      sstsAddCells(oTableRow,sstsGetRowCells(oDataRow).length); // add the empty cells
    }
    return oTableRow; // the Appended
  }
  function sstsGetRowCells(oTableRow) {
    var cCells = oTableRow.getElementsByTagName("TD");
    if (cCells.length == 0 && oTableRow.getElementsByTagName("TH").length)
      cCells = oTableRow.getElementsByTagName("TH");
    return cCells;
  }
  function sstsAddRow(oTableElement) {
    var TR = oTableElement.appendChild(document.createElement("TR"));
    return TR;
  }
  function sstsAddCell(oTableRow) {
    var TD = oTableRow.appendChild(document.createElement("TD"));
    return TD;
  }
  function sstsAddHeaderCell(oTableRow) {
    var TH = oTableRow.appendChild(document.createElement("TH"));
    return TR;
  }
  function sstsAddCells(oTableRow,iCount) {
    for (var i=0; i<iCount; i++) {
      sstsAddCell(oTableRow);
    }
    return oTableRow.getElementsByTagName("TD");
  }
  function sstsGetTableDataRows(oTable) {
    return sstsGetOrAddTableElement(oTable,"TBODY").getElementsByTagName("TR");
  }
  function sstsGetFirstDataRow(oTable) {
    var cTR = sstsGetTableDataRows(oTable);
    if (cTR.length)
      return cTR[0];
    return null;
  }
  function sstsAddSortArrowsToCells(oTableRow) {
    sstsAttachEvent(oTableRow,'click',sstsElementClickHandler);
    var oArrow;
    var cCells = sstsGetRowCells(oTableRow);
    var iSortDirection = sstsGetParentNodeByTagName(oTableRow, "TABLE").getAttribute("sortDirection")*1;
    for (var i2=0; i2<cCells.length; i2++) {
      if (cCells[i2].className.indexOf(gNonSortableColumnClass)==-1) {

        if (cCells[i2].getElementsByTagName("A").length == 0) { // don't update cells that have links in them.
          cCells[i2].innerHTML = "<a href='#' onclick='return false;'>"+cCells[i2].innerHTML+"</a>";
        }

        oArrow = cCells[i2].appendChild(document.createElement("SPAN"));
        oArrow.innerHTML = iSortDirection==0 ? gSortAscHTML : gSortDescHTML ;

        if (i2 == oTableRow.parentNode.getAttribute("sortColumn")*1)
          oArrow.style.visibility = "visible";
        else
          oArrow.style.visibility = "hidden";

        oArrow.className = gUpDownArrowClassName;
      }
    }
  }

  function sstsCleanSampleData(a) {
    a=a.replace(/\-\>/g,'-&gt;').replace(/<[^>]*>/g, '').replace(/\&nbsp\;/g,'');
    return a;
  }
  function sstsGetSortTypeFromSample(oSampleHeaderCell,oSampleDataCell) {
    var mySortType='', asNumberSample, asDateSample, asCurrencySample, asPercentageSample, asLabeledInt;

    if (oSampleHeaderCell.coltype && sstsDataTypeFunctionMap[oSampleHeaderCell.coltype] && oSampleHeaderCell.coltype != 'string') {
      //
      // Any type but string is respected; we'll attempt to re-cast string data.
      //
      mySortType = oSampleHeaderCell.coltype;
    } else {

      // TBD TODO should respect an attribute which determines if we use innerHTML or innerText;
      var dataSample = sstsCleanSampleData(oSampleDataCell.innerHTML);
      asNumberSample  = dataSample.replace(/^\s+|\s+$/g, '');

      asVersionSample = asNumberSample.replace(/\%/g, '').replace(/\,/g, '.');
      if (asVersionSample.match(/^\d+\.\d+\.?\d+?$/)) { //enhance to support , as well.
        mySortType = 'version';
      } else {
        
        asLabeledInt = dataSample;
        if (asLabeledInt.match(/^\d+\s+\w+$/gi)) {
          mySortType = 'labeledint';
        } else {

          asCurrencySample = asNumberSample.replace(/\$/g, '');
          if (asCurrencySample.match(/(?:^\d+$)|(?:^\d+\.\d+$)/)) {
            mySortType = 'currency';
          } else {

            asPercentageSample = asNumberSample;
            if ((asPercentageSample.match(/(?:^\d+\%$)|(?:^\d+\.\d+\%$)|(?:^\.\d+\%$)|(?:^\d+\.\%$)(?:^\%\d+$)|(?:^\%\d+\.\d+$)|(?:^\%\.\d+$)|(?:^\%\d+\.$)/))) {
              mySortType = 'percentage';
            } else {

              if (asNumberSample.match(/(?:^\d+$)|(?:^\d+\.\d+$)/)) {
                mySortType = 'num';
              } else {

                try {
                  asDateSample = new Date(dataSample);
                  if (asDateSample.valueOf()) { //TBD, improve date detection
                    mySortType = 'date';
                    oSampleHeaderCell.coltype='date';
                  }
                } catch (e) {
                  mySortType = '';
                }
              }
            }
          }
        }
      }
    }
    return mySortType || 'string';;
  }

  var sstsDataTypeFunctionMap = {
    'num'        : sstsCastValueTo_NUMBER,
    'int'        : sstsCastValueTo_NUMBER,
    'integer'    : sstsCastValueTo_NUMBER,
    'labeledint' : sstsCastValueTo_LABELEDINT,
    'number'     : sstsCastValueTo_NUMBER,
    'string'     : sstsCastValueTo_STRING,
    'html'       : sstsCastValueTo_STRING,
    'date'       : sstsCastValueTo_DATE,
    'currency'   : sstsCastValueTo_CURRENCY,
    'percentage' : sstsCastValueTo_PERCENTAGE,
    'version'    : sstsCastValueTo_VERSION,
    'ipaddress'  : sstsCastValueTo_VERSION
  }
  function sstsCastValueTo_NUMBER (a) {
    var b = sstsCleanSampleData(a);
    a=b.replace(/^\s+|\s+$/g,'').replace(/\$/g, '');
    if (a=='')
      return MAX_NUMBER;
    if (isNaN(new Number(a)))
      return MAX_NUMBER_2;
    return a*1;
  }
  function sstsCastValueTo_CURRENCY(a) {
    a = sstsCleanSampleData(a).replace(/^\s+|\s+$/g,'');
    var _currency = sstsDataTypeFunctionMap['num'](a);
    return _currency;
  }
  function sstsCastValueTo_PERCENTAGE(a) {
    a = sstsCleanSampleData(a).replace(/^\s+|\s+$/g,'').replace(/\%/g, '');
    var _percentage = sstsDataTypeFunctionMap['num'](a);
    return _percentage;
  }
  function sstsCastValueTo_DATE (a) {
    a = sstsCleanSampleData(a).replace(/^\s+|\s+$/g,'');
    var b = new Date(a);
    // match buildstamps, 2004122501, doesn't match 04122501 though.
    if (isNaN(b) && (a.toString().length >= 8 && a.toString().length <=10))
      b = new Date(a.slice(0,4) + '/' + a.slice(4,6) + '/' + a.slice(6,8));  // take a big swing.
    if (isNaN(b)) { b = MAX_NUMBER; }
    return b.valueOf();
  }
  function sstsCastValueTo_VERSION (a) {
    a = sstsCleanSampleData(a).replace(/^\s+|\s+$/g,'').replace(/\,/g,'.').replace(/[^\d|\.]/gi,'');
    var c = [MAX_NUMBER,MAX_NUMBER,MAX_NUMBER,MAX_NUMBER,MAX_NUMBER];
    if (''!=a) {
      var b=a.split('.');
      for (var i=0; i<b.length; i++) {
        c[i] = isNaN(new Number(b[i])) ? MAX_NUMBER : b[i]*1; // new Number returns an Object, dont use.
      }
    }
    return c;
  }
  function sstsCastValueTo_LABELEDINT (a) {
    a = sstsCleanSampleData(a);
    a = a.split(" ")[0]*1;
    return a;
  }
  function sstsCastValueTo_STRING (a) {
    a = sstsCleanSampleData(a);
    if (a=='') return MAX_STRING;
    else if (gCastStringToLowerCase) a=a.toLowerCase();
    return a;
  }

  var Debugger = {};
  var DebuggerWindow = gDEBUG ? window.open('','sstsDebuggerWindow','') : null;
  Debugger.Debug = function (a,b,c) {
    if (gDEBUG) {
      var NewMsg = DebuggerWindow.document.createElement("li");
      NewMsg.innerHTML = [a,b,c].join(' : ');
      DebuggerWindow.document.body.appendChild(NewMsg);
      return NewMsg;
    }
  }
  Debugger.Debug("ssTableSort Created", "Debugger Started");
}
]]>  
  </script>
  </head>
  <body marginheight="8" topmargin="8" marginwidth="8" leftmargin="8">
    <table width="100%"><tr><td>
    <xsl:for-each select="/SPRTReportInstance/SPRTReport">
      <xsl:if test="Name">
        <font class="pageheader"><xsl:value-of select="Name"/></font>
        <hr width="100%"></hr>
      </xsl:if>  
    </xsl:for-each>
    </td></tr></table>
    <table cellpadding="0" cellspacing="0" class="clsTable1">
    <tr>
      <td class="clsTableHeader">Results (# of rows shown: <xsl:value-of select="/SPRTReportInstance/SPRTReportInstanceInfo/RowsShown" />)</td>
    </tr>
    <tr>
      <td>
        <table cellpadding="0" cellspacing="0" class="sortable" width="100%">
          <thead>
          <tr class="clsTableSubHeader">
            <xsl:apply-templates select="s:Schema/s:ElementType/s:AttributeType" />
          </tr>
          </thead>
          <tbody>
            <xsl:apply-templates select="rs:data/z:row" />
            <xsl:for-each select="/SPRTReportInstance/SPRTReport/Total">
              <xsl:variable name="totalcol"><xsl:value-of select="./@countcol"/></xsl:variable>
              <xsl:variable name="totalalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[@rs:name=$totalcol]/@aliasname"/></xsl:variable>
              <tr class="clsTableRowMaster1"><td colspan="255" class="clsTableRowMaster1"><b>TotalTotal forfor <xsl:value-of select="./@display"/> == <xsl:value-of select="sum(/SPRTReportInstance/SPRTReportOutput/rs:data/z:row/@*[name(.)=$totalalias])"/></b></td></tr>
            </xsl:for-each>
          </tbody>
        </table>
      </td>
    </tr>
  </table>
  </body>
  </html>
</xsl:template>

<!--  This template outputs the instance info and the parameters that were used to run the report.  -->
<xsl:template match="/SPRTReportInstance/SPRTReportInstanceInfo">
  <table>
    <tr>
      <td style="clsReportAttrHeading"><B>Report run date:</B></td>
      <td style="clsReportAttrValue"><xsl:value-of select="RunDate" /><BR/></td>
    </tr>
    <tr>
      <td style="clsReportAttrHeading"><B>Rows Returned:</B></td>
      <td style="clsReportAttrValue"><xsl:value-of select="RowsShown" /><BR/></td>
    </tr>
    <tr>
      <td style="clsReportAttrHeading"><B>Total Rows:</B></td>
      <td style="clsReportAttrValue"><xsl:value-of select="Rows" /><BR/></td>
    </tr>
    <tr>
      <td style="clsReportAttrHeading"><B>Report Variables:</B></td>
    </tr>
      <xsl:for-each select="SqlVariable">
        <tr>
          <td><b>&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<xsl:value-of select="attribute::name"/></b></td><td><xsl:value-of select="attribute::varvalue"/></td>
        </tr>
      </xsl:for-each>
    <tr>
      <td style="clsReportAttrHeading"><B>SQL Query:</B></td>
      <td style="clsReportAttrValue"><xsl:value-of select="SQLQuery" /><BR/></td>
    </tr>
  </table>
</xsl:template>

<!--  This template sets up the column headers for the report.  -->
<xsl:template match="s:Schema/s:ElementType/s:AttributeType">
    <xsl:variable name="colname"><xsl:value-of select="@rs:name"/></xsl:variable>
    <xsl:variable name="coltype"><xsl:value-of select="s:datatype/@dt:type" /></xsl:variable>
    <xsl:variable name="uppercolname"><xsl:value-of select="translate(@rs:name,$upperabc,$lowerabc)"/></xsl:variable>
    <xsl:variable name="hiddencol"><xsl:value-of select="/SPRTReportInstance/SPRTReport/Column[translate(@name,$upperabc,$lowerabc)=$uppercolname]/@hidden"/></xsl:variable>
    <xsl:variable name="coldisplay"><xsl:value-of select="/SPRTReportInstance/SPRTReport/Column[translate(@name,$upperabc,$lowerabc)=$uppercolname]"/></xsl:variable>
    <xsl:variable name="mhover"><xsl:value-of select="/SPRTReportInstance/SPRTReport/Column[translate(@name,$upperabc,$lowerabc)=$uppercolname]/@hovertext"/></xsl:variable>
    
    <xsl:if test="$hiddencol != 'true'">
      <xsl:choose>
        <xsl:when test="$coldisplay != ''">
          <xsl:element name="th">
            <xsl:attribute name="class">clsTableSubHeader</xsl:attribute>
            <xsl:attribute name="title"><xsl:value-of select="$mhover"/></xsl:attribute>
            <xsl:attribute name="coltype"><xsl:value-of select="$coltype" /></xsl:attribute>
            <xsl:value-of disable-output-escaping="yes" select="$coldisplay"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:element name="th">
            <xsl:attribute name="class">clsTableSubHeader</xsl:attribute>
            <xsl:attribute name="coltype"><xsl:value-of select="$coltype" /></xsl:attribute>
            <xsl:value-of select="$colname" />
          </xsl:element>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:if>
</xsl:template>

<!--  This template writes out the data rows for the report.  The choose statement
      below is used to alternate row color in the output.  -->
<xsl:template match="rs:data/z:row">
  <xsl:element name="tr">
    <xsl:choose>
      <xsl:when test="position() mod 2 = 0">
        <xsl:attribute name="class">clsTableRow2</xsl:attribute>
      </xsl:when>
      <xsl:when test="position() mod 2 = 1">
        <xsl:attribute name="class">clsTableRow1</xsl:attribute>
      </xsl:when>
    </xsl:choose>

<!--  First we set up a variable that contains the data from the row.  We then
      must iterate the columns stored in the ElementType schema to determine
      to format each column we are outputting.  -->
    <xsl:variable name="rowdata" select="."/>
    <xsl:variable name="prevrowdata" select="preceding-sibling::z:row[1]"/>
    <xsl:for-each select="../../s:Schema/s:ElementType/s:AttributeType">
      <xsl:variable name="colname"><xsl:value-of select="@rs:name"/></xsl:variable>
      <xsl:variable name="uppercolname"><xsl:value-of select="translate(@rs:name,$upperabc,$lowerabc)"/></xsl:variable>
      <xsl:variable name="colalias"><xsl:value-of select="@aliasname"/></xsl:variable>
      <xsl:variable name="coltype"><xsl:value-of select="s:datatype/@dt:type"/></xsl:variable>
      <xsl:variable name="colvalue"><xsl:value-of select="$rowdata/@*[name(.)=$colalias]"/></xsl:variable>
      <xsl:variable name="prevvalue"><xsl:value-of select="$prevrowdata/@*[name(.)=$colalias]"/></xsl:variable>
      <xsl:variable name="hiddencol"><xsl:value-of select="/SPRTReportInstance/SPRTReport/Column[translate(@name,$upperabc,$lowerabc)=$uppercolname]/@hidden"/></xsl:variable>
      <xsl:if test="$hiddencol != 'true'">
        <xsl:element name="td">
          <xsl:attribute name="class">clsTableCell</xsl:attribute>
          <xsl:attribute name="coltype"><xsl:value-of select="$coltype" /></xsl:attribute>
          <xsl:if test="($coltype = 'int') or ($coltype = 'num')">
            <xsl:attribute name="align">right</xsl:attribute>
          </xsl:if>

 
    

<!--  This if statement tests to determine whether for a defined break column
      the data in the column is equal to the data in the previous row, and will not
      print the unless it is different.  This provides for a more readable report -->
      <xsl:if test="($colvalue != $prevvalue) or ($breakalias != $colalias)">

<!--  This section implements DrillDown by hyperlinking the column if the
      column name matches the one from the <DrillDown> element in the report.
      It uses a very long XSL line to build the link to avoid whitespace in the URL.  -->
          <xsl:variable name="isdrillcol" select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]"/>
          <xsl:variable name="nondrillval" select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@nondrillvalue"/>
          <xsl:variable name="isdrillcol1" select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]"/>
          <xsl:variable name="nondrillval1" select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@nondrillvalue"/>
          <xsl:variable name="isobjectlink" select="/SPRTReportInstance/SPRTReport/ObjectLink[translate(@linkcol,$upperabc,$lowerabc)=$uppercolname]"/>
          <xsl:choose>
            <xsl:when test="$isdrillcol">
              <xsl:choose>
                <xsl:when test="$nondrillval = $colvalue">
                  <xsl:value-of select="$colvalue"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:element name="a">
                    <xsl:attribute name="href"><xsl:value-of select="/SPRTReportInstance/SPRTReportInstanceInfo/WebBase"/>/servicegateway_report/jsp/protected/reportView.jsp?reportGuid=<xsl:value-of select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@report"/>&amp;<xsl:for-each select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/Parameter[@type='column']"><xsl:variable name="paramcol"><xsl:value-of select="@name"/></xsl:variable><xsl:variable name="paramalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate($paramcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable>variablesVal(<xsl:value-of select="@qsname"/>)=<xsl:value-of select="$rowdata/@*[name(.)=$paramalias]"/>&amp;</xsl:for-each><xsl:apply-templates select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/Parameter[@type='SqlVariable']"/><xsl:apply-templates select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/Parameter[@type='literal']"/></xsl:attribute>
                    <xsl:attribute name="title">
                       <xsl:value-of select="/SPRTReportInstance/SPRTReport/DrillDown[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@display"/>
                    </xsl:attribute>
                    <xsl:value-of select="$colvalue"/>
                  </xsl:element>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
            <xsl:when test="$isdrillcol1">
              <xsl:choose>
                <xsl:when test="$nondrillval1 = $colvalue">
                  <xsl:value-of select="$colvalue"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:element name="a">
                    <xsl:attribute name="href"><xsl:value-of select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@report"/>?<xsl:for-each select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/Parameter[@type='column']"><xsl:variable name="paramcol"><xsl:value-of select="@name"/></xsl:variable><xsl:variable name="paramalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate($paramcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable><xsl:value-of select="@qsname"/>=<xsl:value-of select="$rowdata/@*[name(.)=$paramalias]"/>&amp;</xsl:for-each><xsl:apply-templates select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/Parameter[@type='SqlVariable']"/></xsl:attribute>
                    <xsl:attribute name="title">
                      <xsl:value-of select="/SPRTReportInstance/SPRTReport/OpenNewURL[translate(@drillcol,$upperabc,$lowerabc)=$uppercolname]/@display"/>
                    </xsl:attribute>
                    <xsl:value-of select="$colvalue"/>
                  </xsl:element>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:when>
            <!-- An implementation for the ObjectLink tag, should it exist in the report -->
            <xsl:when test="$isobjectlink">
              <xsl:variable name="ol_objecttype" select="/SPRTReportInstance/SPRTReport/ObjectLink/@objecttype"/>
              <xsl:variable name="ol_display" select="/SPRTReportInstance/SPRTReport/ObjectLink/@display"/>
              <xsl:variable name="ol_idcol" select="/SPRTReportInstance/SPRTReport/ObjectLink/@idcol"/>
              <xsl:element name="a">
                <xsl:attribute name="href">/opadmin/ReportObjectView.do?objecttype=<xsl:value-of select="$ol_objecttype"/>&amp;<xsl:variable name="ol_idcolalias"><xsl:value-of select="/SPRTReportInstance/SPRTReportOutput/s:Schema/s:ElementType/s:AttributeType[translate(@rs:name,$upperabc,$lowerabc)=translate($ol_idcol,$upperabc,$lowerabc)]/@aliasname"/></xsl:variable>id=<xsl:value-of select="$rowdata/@*[name(.)=$ol_idcolalias]"/></xsl:attribute>
                <xsl:attribute name="title"><xsl:value-of select="$ol_display"/></xsl:attribute>
                <xsl:value-of select="$colvalue"/>
              </xsl:element>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$colvalue"/>
            </xsl:otherwise>
          </xsl:choose>
        </xsl:if>
        <span>&#160;</span><!-- force IE to apply style attributes to an empty cell by populating it with a non breaking space. -->
        </xsl:element>  <!--  </td>  -->
      </xsl:if>  <!-- if not a hidden column -->
    </xsl:for-each>
  </xsl:element>  <!--  </tr>  -->

<!--  Use the variables that are defined at the top of the xsl to determine
      whether you need to insert a total, subtotal or line break after each row.  -->
  <xsl:if test="$groupalias != ''">
    <xsl:if test="(./@*[name(.)=$groupalias] != following-sibling::z:row[1]/@*[name(.)=$groupalias]) or (position() = last())">
      <tr class="clsTableRowMaster1"><td class="clsTableRowMaster1" colspan="255"><xsl:variable name="subtotal" select="key('subtotal_key', ./@*[name(.)=$groupalias])"/>
      <b>TotalTotal forfor <xsl:value-of select="@*[name(.)=$groupalias]"/> == <xsl:value-of select="sum($subtotal/@*[name(.)=$countalias])"/></b>
      </td></tr>
    </xsl:if>
  </xsl:if>
  <xsl:if test="$breakalias != ''">
    <xsl:if test="(./@*[name(.)=$breakalias] != following-sibling::z:row[1]/@*[name(.)=$breakalias]) or (position() = last())">
      <xsl:value-of disable-output-escaping="yes" select="$breakdata"/>
    </xsl:if>
  </xsl:if>
</xsl:template>

<!--  This template adds any SqlVariable parameters to the query string of a DrillDown link.
      It is all on one long line in order to avoid whitespace in the URL.  -->
<xsl:template match="/SPRTReportInstance/SPRTReport/DrillDown/Parameter[@type='SqlVariable']">
  <xsl:variable name="reportvarname"><xsl:value-of select="@name"/></xsl:variable>
  <xsl:variable xmlns:encoder="xalan://java.net.URLEncoder" name="paramval" select="encoder:encode( string( /SPRTReportInstance/SPRTReportInstanceInfo/SqlVariable[@name=$reportvarname]/@varvalue ) ) "/>
  <xsl:text>variablesVal(</xsl:text><xsl:value-of select="@qsname"/><xsl:text>)</xsl:text>=<xsl:value-of select="$paramval"/><xsl:text>&amp;</xsl:text>
</xsl:template>

</xsl:stylesheet>