I have written an xsl for converting the trx file of mstest into html.
Following from this link, I'm unable to get the class names and number of passes and failures for each class to be printed in the output.
I'm not sure where I'm goin wrong. the style sheet is applied on the same input file in the link.
Thanks.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
<xsl:param name="today"></xsl:param>
<xsl:param name="results"></xsl:param>
<xsl:param name="pass" select="'Passed'"/>
<xsl:param name="fail" select="'Failed'"/>
<xsl:param name="incon" select="'Inconclusive'"/>
<xsl:param name="error" select="'Error'"/>
<xsl:key name="class-key" match="#className" use="."/>
<xsl:variable name="unique-classes" select="//t:TestMethod/#className[generate-id(.)=generate-id(key('class-key',.))]" />
<xsl:template match="/">
<html>
<head>
<script type="text/javascript">
//Some javascript code
</script>
</head>
<body style="font-family:Verdana; font-size:10pt">
Coverage Summary
<xsl:call-template name="summary" />
<xsl:call-template name="details2" />
</body>
</html>
</xsl:template>
<xsl:template name="summary">
<h3>Test Summary</h3></code>
<table style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt">
<tr>
<td style="font-weight:bold;">Total</td>
<td style="font-weight:bold;">Failed</td>
<td style="font-weight:bold;">Passed</td>
<td style="font-weight:bold;">Inconclusive</td>
<td style="font-weight:bold;">Error</td>
</tr>
<tr>
<td >
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#total"/>
</td>
<td style="background-color:pink;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#failed"/>
</td>
<td style="background-color:lightgreen;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#passed"/>
</td>
<td style="background-color:lightblue;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#inconclusive"/>
</td>
<td style="background-color:yellow;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#error"/>
</td>
</tr>
</table>
</xsl:template>
<xsl:template name="details2">
<h3>Unit Test Results</h3>
<table border="0" style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt;">
<tr>
<td></td>
<td id="data" style="font-weight:bold;">Test Name</td>
<td id="data" style="font-weight:bold;">Result</td>
<td id="data" style="font-weight:bold;">Duration</td>
</tr>
<xsl:for-each select="$unique-classes">
<xsl:sort />
<xsl:variable name="curClass" select="."/>
<xsl:variable name="parentId" select="generate-id(./..)" />
<xsl:variable name="currentId" select="generate-id(.)" />
<tr id="{$parentId}">
<td id="{$currentId}"
style="font-weight:bold; cursor:pointer;"
onClick="toggleDetail(this)">[+]</td>
<xsl:sort select="#name"/>
<xsl:variable name="testid" select="../#id"/>
<xsl:with-param name="testid" select="."/>
<xsl:with-param name="curClass" select="."/>
<xsl:call-template name="groups" />
</tr>
<xsl:call-template name="classRunsDetail">
<xsl:with-param name="curClass" select="."/>
</xsl:call-template>
<tr id="{$currentId}-end" style="display:none;">
<td style="border-bottom:0px solid black;height:1px;background-color:black" colspan="4"></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="classRunsDetail">
<xsl:param name="curClass"/>
<xsl:variable name="parentId" select="generate-id(.)" />
<xsl:for-each select="//t:UnitTest/t:TestMethod[#className=$curClass]">
<xsl:sort select="#name"/>
<xsl:variable name="testid" select="../#id"/>
<xsl:for-each select="//t:UnitTestResult[#testId=$testid]">
<tr id="{$parentId}">
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="#outcome = $fail">background-color:pink;</xsl:when>
<xsl:when test="#outcome = $pass">background-color:lightgreen;</xsl:when>
<xsl:when test="#outcome = $incon">background-color:lightblue;</xsl:when>
<xsl:otherwise>background-color:yellow;</xsl:otherwise>
</xsl:choose>
display:none;
</xsl:attribute>
<td></td>
<td id="data">
<xsl:value-of select="#testName"/>
</td>
<td id="data">
<xsl:choose>
<xsl:when test="#outcome = $fail">FAILED</xsl:when>
<xsl:when test="#outcome = $pass">Passed</xsl:when>
<xsl:when test="#outcome = $incon">Not Run</xsl:when>
<xsl:otherwise>Error</xsl:otherwise>
</xsl:choose>
</td>
<td id="data">
<xsl:value-of select="#duration"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:key name="class" match="t:TestMethod" use="#className"/>
<xsl:key name="result" match="t:UnitTestResult" use="#testName"/>
<xsl:template name="groups" match="t:TestMethod[count(.|key('class',#className)[1])=1]">
<xsl:variable name="result" select="key('result',key('class',#className)/#name)"/>
<td valign="bottom" style="background-color:beige;font-weight:bold;" colspan="3">
<xsl:value-of select="#className"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Passed'])"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Failed'])"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Inconclusive'])"/>
</td>
</xsl:template>
</xsl:stylesheet>
I was using XSL for the same thing, but it was a nightmare to analyze trx.
trx2html.codeplex.com Latest version, is based on LINQ2XML !!
The provided stylesheet didn't even run...
I'm just guessing here, because there is no desired output.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:t="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
<xsl:param name="pass" select="'Passed'"/>
<xsl:param name="fail" select="'Failed'"/>
<xsl:param name="incon" select="'Inconclusive'"/>
<xsl:param name="error" select="'Error'"/>
<xsl:key name="class" match="t:TestMethod" use="#className"/>
<xsl:key name="result" match="t:UnitTestResult" use="#testName"/>
<xsl:template match="text()"/>
<xsl:template match="/*">
<html>
<head>
<script type="text/javascript">
//Some javascript code
</script>
</head>
<body style="font-family:Verdana; font-size:10pt">
Coverage Summary
<xsl:apply-templates select="t:ResultSummary|t:TestDefinitions"/>
</body>
</html>
</xsl:template>
<xsl:template match="t:Counters">
<h3>Test Summary</h3>
<table style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt">
<tr>
<td style="font-weight:bold;">Total</td>
<td style="font-weight:bold;">Failed</td>
<td style="font-weight:bold;">Passed</td>
<td style="font-weight:bold;">Inconclusive</td>
<td style="font-weight:bold;">Error</td>
</tr>
<tr>
<td >
<xsl:value-of select="#total"/>
</td>
<td style="background-color:pink;">
<xsl:value-of select="#failed"/>
</td>
<td style="background-color:lightgreen;">
<xsl:value-of select="#passed"/>
</td>
<td style="background-color:lightblue;">
<xsl:value-of select="#inconclusive"/>
</td>
<td style="background-color:yellow;">
<xsl:value-of select="#error"/>
</td>
</tr>
</table>
</xsl:template>
<xsl:template match="t:TestDefinitions">
<h3>Unit Test Results</h3>
<table border="0" style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt;">
<tr>
<td></td>
<td id="data" style="font-weight:bold;">Test Name</td>
<td id="data" style="font-weight:bold;">Result</td>
<td id="data" style="font-weight:bold;">Duration</td>
</tr>
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="t:TestMethod[count(.|key('class',#className)[1])=1]">
<xsl:variable name="result" select="key('result',key('class',#className)/#name)"/>
<tr id="{generate-id(.)}">
<td id="{generate-id(#className)}"
style="font-weight:bold; cursor:pointer;"
onClick="toggleDetail(this)">[+]</td>
<td valign="bottom" style="background-color:beige;font-weight:bold;" colspan="3">
<xsl:value-of select="#className"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Passed'])"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Failed'])"/>
</td>
<td>
<xsl:value-of select="count($result[#outcome='Inconclusive'])"/>
</td>
</tr>
<xsl:apply-templates select="$result">
<xsl:sort select="#name"/>
<xsl:with-param name="id" select="generate-id(#className)"/>
</xsl:apply-templates>
<tr id="{generate-id(.)}-end" style="display:none;">
<td style="border-bottom:0px solid black;height:1px;background-color:black" colspan="4"></td>
</tr>
</xsl:template>
<xsl:template match="t:UnitTestResult">
<xsl:param name="id"/>
<tr id="{$id}">
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="#outcome = $fail">background-color:pink;</xsl:when>
<xsl:when test="#outcome = $pass">background-color:lightgreen;</xsl:when>
<xsl:when test="#outcome = $incon">background-color:lightblue;</xsl:when>
<xsl:otherwise>background-color:yellow;</xsl:otherwise>
</xsl:choose>
<xsl:text>display:none;</xsl:text>
</xsl:attribute>
<td></td>
<td id="data">
<xsl:value-of select="#testName"/>
</td>
<td id="data">
<xsl:choose>
<xsl:when test="#outcome = $fail">FAILED</xsl:when>
<xsl:when test="#outcome = $pass">Passed</xsl:when>
<xsl:when test="#outcome = $incon">Not Run</xsl:when>
<xsl:otherwise>Error</xsl:otherwise>
</xsl:choose>
</td>
<td id="data">
<xsl:value-of select="#duration"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Note: I've reversed your logic. Don't drive the transformation with for-each instructions. Apply templates to descendants, instead.
Related
I Have a Attribute that I want to display, but I only want to display the last portion of it indicated by an "-". I am using substring-after to do this but this only works if there is one charactor. There are occasions where there might be one and some where there is two. I have seen some recursive templates for this but I have not seen them in a For-each Loop like I have it here and I am not sure where I would put everything in my XSL document.
Here is my XML document:
<?xml version="1.0" encoding="UTF-8"?>
<JobList>
<Job T.number="28" />
<Job T.identifier="10mm Drill" />
<Job oper.jobName="2: T28-Contour Milling - Grind me back" />
<Job T.number="3" />
<Job T.identifier="9mm Drill" />
<Job oper.jobName="3: T3 Contour Milling" />
</JobList>
Here is my XSL Document. I am using XSL 1.0. The result I am looking for is I want this to be displayed as "10mm Drill - Grind me back" not "10mm Drill-Contour Milling - Grind me back" which is what I am getting now using the substring-after function or something with the same result.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" encoding="UTF-8" method="xml" />
<xsl:param name="REPORT">joblist</xsl:param>
<xsl:param name="LOCALE">en-GB</xsl:param>
<xsl:param name="FORMAT">html</xsl:param>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Tool Report</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="JobList">
<div style="font-size:;">
<table width="100%" style="margin-bottom:50px;font:bold 10px arial;">
<thead>
<tr>
<th style="text-align:center;font-family:Arial;font-size:13;font:bold 7px arial;">
<xsl:value-of select="#month">
</xsl:value-of>
<span>.</span>
<xsl:value-of select="#day">
</xsl:value-of>
<span>.</span>
<xsl:value-of select="#year">
</xsl:value-of>
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center;font:normal 7px arial;font-size:12px;">
<xsl:value-of select="//Job[position()=1]/#cfg.JOBLISTNAME" />
<span>
</span>
<span>
</span>
</td>
</tr>
</tbody>
<table width="100%" border="1" style="margin-bottom:50px;font:13px arial;">
<thead style="font:19;">
<tr style="font-size:19;">
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
<td style="text-align:center;font-weight:bold;font-size:19;">
</td>
</tr>
</thead>
<tbody style="font-size:19;">
<xsl:for-each select="//Job[not(#T.number=preceding::Job/#T.number)]">
<tr style="font-size:19;">
<td style="font-size:19;">
<xsl:value-of select="#T.number" />
</td>
<td>
</td>
<td style="font-size:19;">
<xsl:value-of select="#T.identifier" />
<xsl:choose>
<xsl:when test="contains(#T.toolComment3, 'GRIND') or contains(#T.toolComment3, 'Grind')">
<xsl:value-of select="#T.toolComment3" />
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="contains(#T.comment2, 'GRIND') or contains(#T.comment2, 'Grind')">
<xsl:value-of select="#T.comment2" />
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="contains(#oper.jobName, 'GRIND') or contains(#oper.jobName, 'Grind')">
<xsl:value-of select="substring-after(#oper.jobName, '-')" />
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</tbody>
</table>
</table>
</div>
</xsl:template>
</xsl:stylesheet>
Use a named recursive template to get the last token of the text string.
<xsl:template name="last-token">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="'-'"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="last-token">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Example of call: http://xsltransform.net/bFWR5Ew
I have some XML records that show sales by date. I need to pivot this information into a table that shows the sales for a week.
Here is the XML:
<?xml version="1.0"?>
-<data>
<report datetime="9/24/2013 10:27 AM"/>
<reportnumber displayas="Report Number">7</reportnumber>
<businessdate displayas="Business Date">08/19/2013 to 08/25/2013</businessdate>
<businesssiteids displayas="Store">NEBO Enchiladas</businesssiteids>
<colheaders>
-<colheader day7="08/25/2013" day7name="Sunday" day6="08/24/2013" day6name="Saturday" day5="08/23/2013" day5name="Friday" day4="08/22/2013" day4name="Thursday" day3="08/21/2013" day3name="Wednesday" day2="08/20/2013" day2name="Tuesday" day1="08/19/2013" day1name="Monday"/>
</colheaders>
<row ReportAmtDaily="0.000000" ListName="Closing Reading:" BusinessDate="2013-08-19T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="1"/>
<row ReportAmtDaily="0.000000" ListName="Closing Reading:" BusinessDate="2013-08-21T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="2"/>
<row ReportAmtDaily="0.000000" ListName="Closing Reading:" BusinessDate="2013-08-22T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="3"/>
<row ReportAmtDaily="0.000000" ListName="Closing Reading:" BusinessDate="2013-08-23T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="4"/>
<row ReportAmtDaily="0.000000" ListName=" - Opening Reading" BusinessDate="2013-08-19T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="5"/>
<row ReportAmtDaily="0.000000" ListName=" - Opening Reading" BusinessDate="2013-08-21T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="6"/>
<row ReportAmtDaily="0.000000" ListName=" - Opening Reading" BusinessDate="2013-08-22T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="7"/>
<row ReportAmtDaily="0.000000" ListName=" - Opening Reading" BusinessDate="2013-08-23T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="8"/>
<row ReportAmtDaily="3334.220000" ListName="Gross Sales:" BusinessDate="2013-08-19T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="9"/>
<row ReportAmtDaily="4187.620000" ListName="Gross Sales:" BusinessDate="2013-08-21T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="10"/>
<row ReportAmtDaily="572.190000" ListName="Gross Sales:" BusinessDate="2013-08-22T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="11"/>
<row ReportAmtDaily="10856.970000" ListName="Gross Sales:" BusinessDate="2013-08-23T00:00:00" BusinessSiteId="40E9E40D-5E7E-4EB3-99C6-8013CD31480D" linenumber="12"/>
</data>
I want the output to look like this for each businesssiteid:
------------------08/19/2013 08/20/20/2013 08/21/2013 08/22/2013 08/23/2013 08/24/2013 08/25/2013
Closing Reading: 0 0 0 0 0 0 0
-Opening Reading 0 0 0 0 0 0 0
Gross Sales 3334.22 0 4187.62 572.19 10856.97 0 0
I tried using a key and a variable in my XSLT but nothing returns either way and I don't think it's right because I need a value based on the combination of BusinessDate,ListName and BusinessSiteId.
This template of the returns the data in an un-pivoted format. Can someone point me in the right direction please.
<xsl:template match="row">
<tr>
<td>
<div class="col1">
<xsl:value-of select="#ListName"/>
</div>
</td>
<td>
<div class="col2">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col3">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col4">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col5">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col6">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col7">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col8">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col9">
<!--<xsl:value-of select="#"/>-->
</div>
</td>
</tr>
<!--</xsl:if>-->
XSLT
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="msxsl"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<user:data xmlns:user="user">
<datamodel name="Sales.SDR">
<editable value="false" />
<fields>ListName,ReportQtyDaily</fields>
<filters>
<filter field="ReportNumber" value="7" />
</filters>
<totals />
<sorting>
</sorting>
<grouping />
<parameters>
<parameter field="BusinessDate" prompt="true" />
<parameter field="BusinessSiteIds" prompt="true" />
</parameters>
<reportheader headerfile="netsales1.xslt"/>
</datamodel>
<version>1.0</version>
<reportdescription>Filtered by: ReportNumber Parameters:
BusinessDate,BusinessSiteIds Fields Displayed: Line
Text</reportdescription>
<orientation value="horizontal" />
</user:data>
<xsl:output method="html" />
<xsl:key name="kListName" match="/data/row/#ListName" use="."/>
<xsl:template match="data">
<html>
<head />
<style type="text/css">div.col1{width:2.00in;left}div.col2{width:1.00in;right}div.col3{width:1.00in;right}div.col4{width:1.00in;right}div.col5{width:1.00in;right}div.col6{width:1.00in;right}div.col7{width:1.00in;right}div.col8{width:1.00in;right}div.col9{width:1.00in;right}</style>
<body>
<table class="report_header">
<tr>
<td class="title">Weekly SDR</td>
</tr>
<tr>
<td>
<table>
<tr>
<td />
<td class="parameterlabel">Business Date:</td>
<td>
<xsl:value-of select="businessdate" />
</td>
</tr>
<tr>
<td />
<td class="parameterlabel">Store:</td>
<td>
<xsl:value-of select="businesssiteids" />
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td />
<td />
</tr>
<tr>
<td>
<table class="report_tabulardata">
<thead class="report_tabulardata">
<tr class="columnheader">
<xsl:apply-templates select="colheaders/colheader" />
</tr>
</thead>
</table>
</td>
</tr>
<tr>
<td>
<table class="report_tabulardata">
<xsl:apply-templates select="row" />
</table>
</td>
</tr>
</table>
</body>
</html>
...other templates remove to make it easier to read
<xsl:template match="row">
<!--<xsl:for-each select="row[#ListName]">
<xsl:variable name="desc" select="row[#ListName]"/>-->
<tr>
<td>
<div class="col1" align="left">
<xsl:value-of select="#ListName"/>
</div>
</td>
<!--<xsl:for-each select="//#region[generate-id(.)= generate-id(key('b',.)[1])]">
</xsl:for-each>-->
<td>
<div class="col2" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col3" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col4" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col5" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col6" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col7" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col8" align="right">
<xsl:value-of select="#ReportAmtDaily"/>
</div>
</td>
<td>
<div class="col9" align="right">
<!--<xsl:value-of select="sum($thisGroup/#ReportAmtDaily)"/>-->
</div>
</td>
</tr>
<!--</xsl:for-each>-->
</xsl:template>
</xsl:stylesheet>
Something like this might do the trick:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:variable
select="reverse(/data/colheaders/colheader/#*[not(local-name()[contains(.,'name')])])"
name="days"/>
<xsl:variable name="ids" select="distinct-values((//#BusinessSiteId))"/>
<xsl:template match="/">
<html>
<body>
<h2>Weekly Report</h2>
<p>Report date/time: <xsl:value-of select="/data/report/#datetime"/></p>
<p><xsl:value-of select="/data/reportnumber/#displayas"/>: <xsl:value-of
select="/data/reportnumber"/></p>
<p><xsl:value-of select="/data/businessdate/#displayas"/>: <xsl:value-of
select="/data/businessdate"/></p>
<p><xsl:value-of select="/data/businesssiteids/#displayas"/>: <xsl:value-of
select="/data/businesssiteids"/></p>
<xsl:for-each select="$ids">
<h4>Site ID: <xsl:value-of select="."/></h4>
<table>
<thead>
<tr>
<th/>
<xsl:apply-templates select="$days" mode="header"/>
</tr>
</thead>
<tbody>
<tr>
<td>Closing Reading:</td>
<xsl:apply-templates select="$days" mode="closing">
<xsl:with-param name="currentid" select="."/>
</xsl:apply-templates>
</tr>
<tr>
<td>Opening Reading:</td>
<xsl:apply-templates select="$days" mode="opening">
<xsl:with-param name="currentid" select="."/>
</xsl:apply-templates>
</tr>
<tr>
<td>Gross Sales:</td>
<xsl:apply-templates select="$days" mode="sales">
<xsl:with-param name="currentid" select="."/>
</xsl:apply-templates>
</tr>
</tbody>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template match="/data/colheaders/colheader/#*" mode="header">
<th>
<xsl:value-of select="."/>
</th>
</xsl:template>
<xsl:template match="/data/colheaders/colheader/#*" mode="closing">
<xsl:param name="currentid"/>
<xsl:variable
select="concat(substring-after(substring-after(.,'/'),'/') , '-', substring-before(.,'/'), '-', substring-before(substring-after(.,'/'),'/'))"
name="closedate"/>
<xsl:for-each select=".">
<xsl:choose>
<xsl:when
test="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName='Closing Reading:'][contains(.,$closedate)]">
<xsl:variable name="numbera" select="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName='Closing Reading:'][contains(.,$closedate)]/../#ReportAmtDaily"/>
<td>
<xsl:value-of
select="format-number( round(100*$numbera) div 100 ,
'###,###,##0.00' )"
/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:text>0</xsl:text>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="/data/colheaders/colheader/#*" mode="opening">
<xsl:param name="currentid"/>
<xsl:variable
select="concat(substring-after(substring-after(.,'/'),'/') , '-', substring-before(.,'/'), '-', substring-before(substring-after(.,'/'),'/'))"
name="opendate"/>
<xsl:for-each select=".">
<xsl:choose>
<xsl:when
test="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName=' - Opening Reading'][contains(.,$opendate)]">
<xsl:variable name="numberb" select="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName=' - Opening Reading'][contains(.,$opendate)]/../#ReportAmtDaily"/>
<td>
<xsl:value-of
select="format-number( round(100*$numberb) div 100 ,
'###,###,##0.00' )"
/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:text>0</xsl:text>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="/data/colheaders/colheader/#*" mode="sales">
<xsl:param name="currentid"/>
<xsl:variable
select="concat(substring-after(substring-after(.,'/'),'/') , '-', substring-before(.,'/'), '-', substring-before(substring-after(.,'/'),'/'))"
name="salesdate"/>
<xsl:for-each select=".">
<xsl:choose>
<xsl:when
test="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName='Gross Sales:'][contains(.,$salesdate)]">
<xsl:variable name="numberc" select="/data/row/#BusinessDate[../#BusinessSiteId=$currentid][../#ListName='Gross Sales:'][contains(.,$salesdate)]/../#ReportAmtDaily"/>
<td>
<xsl:value-of
select="format-number( round(100*$numberc) div 100 ,
'###,###,##0.00' )"
/>
</td>
</xsl:when>
<xsl:otherwise>
<td>
<xsl:text>0</xsl:text>
</td>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
Sorry for my weak English.
How to enumerate the sorted records in XSL 1.0?
Fragment of my code:
...
<tbody>
<xsl:for-each select="/doc:resources/doc:record">
<xsl:sort select="#id"/>
<xsl:choose>
<xsl:when test="(position() mod 2) = 0">
<tr bgcolor="#C0C0C0">
<td>
<xsl:number format="1"/>
</td>
<td>
<xsl:value-of select="#id"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:when>
<xsl:otherwise>
<tr>
<td>
<xsl:number format="1"/>
</td>
<td>
<xsl:value-of select="#id"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</tbody>
...
Incorrect result screen:
http://imglink.ru/pictures/01-04-12/92605b06b8b2c2670bba868c61288e9b.jpg
Regards
<xsl:for-each select="/doc:resources/doc:record">
<xsl:sort select="#id"/>
<tr>
<xsl:if test="position() mod 2 = 0">
<xsl:attribute name="bgcolor">#C0C0C0</xsl:attribute>
</xsl:if>
<td>
<xsl:value-of select="position()" />
</td>
<td>
<xsl:value-of select="#id"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
The reason for the incorrect numbers is that xsl:number doesn't know about the (dynamic) sorting and uses the structure of the original, unsorted document.
Here is one complete, short and simple, correct solution, using position(). In addition to this, no conditional instructions (xsl:choose, xsl:when, xsl:otherwise, xsl:if`) are used at all:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:doc="xxx">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<html>
<table>
<xsl:apply-templates select="*">
<xsl:sort select="#id"/>
</xsl:apply-templates>
</table>
</html>
</xsl:template>
<xsl:template match="doc:record">
<xsl:variable name="vColor" select=
"substring('C0C0C0FFFFFF', 6*(position() mod 2)+1, 6)"/>
<tr bgcolor="#{$vColor}">
<td>
<xsl:value-of select="position()"/>
</td>
<td>
<xsl:value-of select="#id"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied to the following XML document (none was provided!):
<doc:resources xmlns:doc="xxx">
<doc:record id="dadasd">
some value1
</doc:record>
<doc:record id="hkjhkhkhk">
some value2
</doc:record>
<doc:record id="xvxvxvxv">
some value3
</doc:record>
<doc:record id="afasf">
some value4
</doc:record>
<doc:record id="iuyiyuiy">
some value5
</doc:record>
</doc:resources>
the wanted, correct result is produced:
<html xmlns:doc="xxx">
<table>
<tr bgcolor="#FFFFFF">
<td>1</td>
<td>afasf</td>
<td>
some value4
</td>
</tr>
<tr bgcolor="#C0C0C0">
<td>2</td>
<td>dadasd</td>
<td>
some value1
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td>3</td>
<td>hkjhkhkhk</td>
<td>
some value2
</td>
</tr>
<tr bgcolor="#C0C0C0">
<td>4</td>
<td>iuyiyuiy</td>
<td>
some value5
</td>
</tr>
<tr bgcolor="#FFFFFF">
<td>5</td>
<td>xvxvxvxv</td>
<td>
some value3
</td>
</tr>
</table>
</html>
I'm new to xslt. I tried using urn:helper in the stylesheet tag. But it throws the following error.
"Cannot find the script or external object that implements prefix 'urn:Helper'".
Below is the snippet used in my code.
xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myObj="urn:Helper"
xmlns:t="http://microsoft.com/schemas/VisualStudio/TeamTest/2006"
Am I missing something?
Thanks..
edit: complete stylesheet
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:myObj="urn:Helper"
xmlns:t="http://microsoft.com/schemas/VisualStudio/TeamTest/2006">
<xsl:param name="today"></xsl:param>
<xsl:param name="results"></xsl:param>
<xsl:param name="pass" select="'Passed'"/>
<xsl:param name="fail" select="'Failed'"/>
<xsl:key name="class-key" match="#className" use="."/>
<xsl:variable name="unique-classes" select="//t:TestMethod/#className[generate-id(.) =generate-id(key('class-key',.))]" />
<xsl:template match="/">
<html>
<body style="font-family:Verdana; font-size:10pt">
<h1>Test Results Summary</h1>
<table style="font-family:Verdana; font-size:10pt">
<tr>
<td>
<b>Run Date/Time</b>
</td>
<td>
</td>
</tr>
<tr>
<td>
Start Time:
</td>
<td>
<xsl:value-of select="myObj:DateTimeToString(//t:TestRun/t:Times/#start)"/>
</td>
</tr>
<tr>
<td>
End Time:
</td>
<td>
<xsl:value-of select="myObj:DateTimeToString(//t:TestRun/t:Times/#finish)"/>
</td>
</tr>
<tr>
<td>
Duration:
</td>
<td>
<xsl:value-of select="myObj:TimeSpan(//t:TestRun/t:Times/#start,//t:TestRun/t:Times/#finish)"/>
</td>
</tr>
<tr>
<td>
<b>Results File</b>
</td>
<td>
<xsl:value-of select="$results"/>
</td>
</tr>
</table>
Coverage Summary
<xsl:call-template name="summary" />
<!--<xsl:call-template name="details" />-->
<xsl:call-template name="details2" />
</body>
</html>
</xsl:template>
<xsl:template name="summary">
<h3>Test Summary</h3>
<table style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt">
<tr>
<td style="font-weight:bold">Total</td>
<td style="font-weight:bold">Failed</td>
<td style="font-weight:bold">Passed</td>
<td style="font-weight:bold">Inconclusive</td>
</tr>
<tr>
<td >
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#total"/>
</td>
<td style="background-color:pink;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#failed"/>
</td>
<td style="background-color:lightgreen;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#passed"/>
</td>
<td style="background-color:yellow;">
<xsl:value-of select="/t:TestRun/t:ResultSummary/t:Counters/#inconclusive"/>
</td>
</tr>
</table>
</xsl:template>
<xsl:template name="details">
<h3>Unit Test Results</h3>
<table style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt;">
<tr>
<td style="font-weight:bold">Test Name</td>
<td style="font-weight:bold">Result</td>
<td style="font-weight:bold">Duration</td>
</tr>
<xsl:for-each select="/t:TestRun/t:Results/t:UnitTestResult">
<xsl:sort select="#testName"/>
<tr>
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="#outcome='Failed'">background-color:pink;</xsl:when>
<xsl:when test="#outcome='Passed'">background-color:lightgreen;</xsl:when>
<xsl:otherwise>background-color:yellow;</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<td>
<xsl:value-of select="#testName"/>
</td>
<td>
<xsl:choose>
<xsl:when test="#outcome='Failed'">FAILED</xsl:when>
<xsl:when test="#outcome='Passed'">Passed</xsl:when>
<xsl:otherwise>Inconclusive</xsl:otherwise>
</xsl:choose>
</td>
<td>
<xsl:value-of select="#duration"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="details2">
<h3>Unit Test Results</h3>
<table border="0" style="width:640;border:1px solid black;font-family:Verdana; font-size:10pt;">
<xsl:for-each select="$unique-classes">
<xsl:sort />
<xsl:variable name="curClass" select="."/>
<xsl:variable name="return" select="myObj:GetClassInformation($curClass)"/>
<!--<xsl:for-each select="//TestRun/tests/value/testMethod[className=$curClass]">-->
<tr>
<td valign="bottom" style="background-color:beige;font-weight:bold;" colspan="3">
<font>
<xsl:value-of select="concat('',$return/className)"/>
</font>
</td>
</tr>
<tr>
<td style="font-weight:bold">Test Name</td>
<td style="font-weight:bold">Result</td>
<td style="font-weight:bold">Duration</td>
</tr>
<xsl:for-each select="//t:UnitTest/t:TestMethod[#className=$curClass]">
<xsl:sort select="#name"/>
<xsl:variable name="testid" select="../#id"/>
<xsl:for-each select="//t:UnitTestResult[#testId=$testid]">
<xsl:call-template name="classRunsDetail">
<xsl:with-param name="testid" select="."/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>
<tr>
<td style="border-bottom:0px solid black;height:1px;background-color:black" colspan="3"></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="classRunsDetail">
<xsl:param name="testid"/>
<tr>
<xsl:attribute name="style">
<xsl:choose>
<xsl:when test="#outcome = $fail">background-color:pink;</xsl:when>
<xsl:when test="#outcome = $pass">background-color:lightgreen;</xsl:when>
<xsl:otherwise>background-color:yellow;</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<td>
<xsl:value-of select="#testName"/>
</td>
<td>
<xsl:choose>
<xsl:when test="#outcome = $fail">FAILED</xsl:when>
<xsl:when test="#outcome = $pass">Passed</xsl:when>
<xsl:otherwise>Inconclusive</xsl:otherwise>
</xsl:choose>
</td>
<td>
<xsl:value-of select="#duration"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
There is no problem with your xsl:stylesheet element.
The problem is here:
<xsl:value-of select="myObj:DateTimeToString(//t:TestRun/t:Times/#start)"/>
From http://www.w3.org/TR/xslt#section-Extension-Functions
If a FunctionName in a FunctionCall
expression is not an NCName (i.e. if
it contains a colon), then it is
treated as a call to an extension
function. The FunctionName is expanded
to a name using the namespace
declarations from the evaluation
context.
If the XSLT processor does not have an
implementation of an extension
function of a particular name
available, then the function-available
function must return false for that
name. If such an extension function
occurs in an expression and the
extension function is actually called,
the XSLT processor must signal an
error.
The answer: You are missing the extension function implementation.
So, you must provide details of your processor and re-ask what is the specific way that your processor is linked to the implementation of extended functions.
I see you grabbed that little helper object from this post. It seems right, but make sure you are using the C# code to actually do the transform.
Could anyone help me with the following transformation?
Here is the XML
<Chart>
<Chart.Series>
<DataSeries LegendText="Complete On Time" >
<DataSeries.DataPoints>
<DataPoint AxisXLabel="Sep 09" YValue="10" />
<DataPoint AxisXLabel="Oct 09" YValue="11" />
<DataPoint AxisXLabel="Nov 09" YValue="12" />
</DataSeries.DataPoints>
</DataSeries>
<DataSeries LegendText="Complete Overdue" >
<DataSeries.DataPoints>
<DataPoint YValue="1" />
<DataPoint YValue="2" />
<DataPoint YValue="3" />
</DataSeries.DataPoints>
</DataSeries>
</Chart.Series>
</Chart>
and here is the output id like
<table>
<thead>
<tr>
<th></th>
<th>Complete On Time</th>
<th>Complete Overdue</th>
</tr>
</thead>
<tbody>
<tr>
<th>Sep 09</th>
<th>10</th>
<th>1</th>
</tr>
<tr>
<th>Oct 09</th>
<th>11</th>
<th>2</th>
</tr>
<tr>
<th>Nov 09</th>
<th>12</th>
<th>3</th>
</tr>
</tbody>
A more natural solution:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- basic table structure -->
<xsl:template match="Chart">
<table>
<thead>
<xsl:apply-templates select="Chart.Series" mode="thead" />
</thead>
<tbody>
<xsl:apply-templates select="Chart.Series" mode="tbody" />
</tbody>
</table>
</xsl:template>
<!-- table head -->
<xsl:template match="Chart.Series" mode="thead">
<tr>
<th />
<xsl:for-each select="DataSeries">
<th>
<xsl:value-of select="#LegendText" />
</th>
</xsl:for-each>
</tr>
</xsl:template>
<!-- table body -->
<xsl:template match="Chart.Series" mode="tbody">
<xsl:variable name="ds" select="DataSeries" />
<!-- the first data series contains the labels -->
<xsl:for-each select="$ds[1]/*/DataPoint">
<xsl:variable name="pos" select="position()" />
<tr>
<td>
<xsl:value-of select="#AxisXLabel" />
</td>
<!-- process all data points at the current position -->
<xsl:apply-templates select="$ds/*/DataPoint[$pos]" />
</tr>
</xsl:for-each>
</xsl:template>
<!-- data points become a <td> -->
<xsl:template match="DataPoint">
<td>
<xsl:value-of select="#YValue" />
</td>
</xsl:template>
</xsl:stylesheet>
Note that I use template modes to do different things with the same input.
The result is:
<table>
<thead>
<tr>
<th />
<th>Complete On Time</th>
<th>Complete Overdue</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sep 09</td>
<td>10</td>
<td>1</td>
</tr>
<tr>
<td>Oct 09</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td>Nov 09</td>
<td>12</td>
<td>3</td>
</tr>
</tbody>
</table>
This is something close. It's been a couple of year for me though that I've done XSLT - ignore bad style.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output indent="yes" omit-xml-declaration="yes" ></xsl:output>
<xsl:template match="/">
<table>
<thead>
<tr>
<th></th>
<xsl:apply-templates select=".//DataSeries" />
</tr>
</thead>
<tbody>
<xsl:apply-templates select="//DataSeries[1]//DataPoint">
<xsl:with-param name="datablock">1</xsl:with-param>
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="DataSeries">
<th>
<xsl:value-of select="#LegendText"></xsl:value-of>
</th>
</xsl:template>
<xsl:template match="DataPoint">
<xsl:param name="datablock" />
<xsl:variable name="posi" select="position()"></xsl:variable>
<xsl:if test="$datablock = 1">
<tr>
<xsl:for-each select="#*">
<th>
<xsl:value-of select="."></xsl:value-of>
</th>
</xsl:for-each>
<xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
<xsl:with-param name="datablock" select="$datablock + 1">
</xsl:with-param>
</xsl:apply-templates>
</tr>
</xsl:if>
<xsl:if test="$datablock != 1">
<xsl:for-each select="#*">
<th>
<xsl:value-of select="."></xsl:value-of>
</th>
</xsl:for-each>
<xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
<xsl:with-param name="datablock" select="$datablock + 1">
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>