XSLT variable not working - xslt

I have the following piece of XSLT code:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:variable name="condition">(coasts='Adriatic Sea')or(coasts='Mediterranean Sea')</xsl:variable>
<xsl:template match="cia">
<html>
<head></head>
<body>
<table border="1">
<tr>
<th>Country</th>
<th>Capital</th>
<th>Area</th>
<th>Population</th>
<th>Inflation rate</th>
</tr>
<xsl:for-each select="country">
<xsl:if test="{$condition}">
<tr>
<td>
<xsl:value-of select="#name"/>
</td>
<td>
<xsl:value-of select="#capital"/>
</td>
<td>
<xsl:value-of select="#total_area"/>
</td>
<td>
<xsl:value-of select="#population"/>
</td>
<td>
<xsl:value-of select="#inflation"/>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
If put the conditional expression directly in the if element the code works fine, however, my problem is that when I assign the same conditional expression to the variable and then reference it in the if element it doesn't work. Am I doing something wrong? Is this possible?
Thanks!

There are multiple problems:
The brackets in <xsl:if test="{$condition}"> are unnecessary; use <xsl:if test="$condition">
Use the following xsl:variable construct:
<xsl:variable name="condition"
select="(coasts='Adriatic Sea')or(coasts='Mediterranean Sea')"/>
When you had the condition in your xsl:if the test was performed relative to each country. This is not the case in a top-level variable. The value of the variable is the result of the expression, not the expression itself. If you insist on a variable, then initialize it inside the loop.
See the following stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml">
<xsl:template match="cia">
<html>
<head></head>
<body>
<table border="1">
<tr>
<th>Country</th>
<th>Capital</th>
<th>Area</th>
<th>Population</th>
<th>Inflation rate</th>
</tr>
<xsl:for-each select="country">
<xsl:variable name="condition"
select="(coasts='Adriatic Sea') or
(coasts='Mediterranean Sea')" />
<xsl:if test="$condition">
<tr>
<td>
<xsl:value-of select="#name" />
</td>
<td>
<xsl:value-of select="#capital" />
</td>
<td>
<xsl:value-of select="#total_area" />
</td>
<td>
<xsl:value-of select="#population" />
</td>
<td>
<xsl:value-of select="#inflation" />
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Input:
<cia>
<country name="test1" inflation="22">
<coasts>Adriatic Sea</coasts>
</country>
<country name="test2" inflation="7">
<coasts>No match</coasts>
</country>
</cia>
Output (only the first country passes the test):
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
<table border="1">
<tr>
<th>Country</th>
<th>Capital</th>
<th>Area</th>
<th>Population</th>
<th>Inflation rate</th>
</tr>
<tr>
<td>test1</td>
<td></td>
<td></td>
<td></td>
<td>22</td>
</tr>
</table>
</body>
</html>
Note that you don't really even need a separate condition; it's better to select just the desired elements in the first place. This loop produces the same output:
<xsl:for-each
select="country[(coasts='Adriatic Sea') or
coasts='Mediterranean Sea')]">
<tr>
<td>
<xsl:value-of select="#name" />
</td>
<td>
<xsl:value-of select="#capital" />
</td>
<td>
<xsl:value-of select="#total_area" />
</td>
<td>
<xsl:value-of select="#population" />
</td>
<td>
<xsl:value-of select="#inflation" />
</td>
</tr>
</xsl:for-each>

Replace:
<xsl:for-each select="country">
with
<xsl:apply templates select="country"/>
also, add these templates:
<xsl:template match="country"/>
<xsl:template match=
"country[coasts='Adriatic Sea'
or
coasts='Mediterranean Sea'
]">
<xsl:template match=
"country[coasts='Adriatic Sea'
or
coasts='Mediterranean Sea'
]">
<tr>
<td>
<xsl:value-of select="#name"/>
</td>
<td>
<xsl:value-of select="#capital"/>
</td>
<td>
<xsl:value-of select="#total_area"/>
</td>
<td>
<xsl:value-of select="#population"/>
</td>
<td>
<xsl:value-of select="#inflation"/>
</td>
</tr>
</xsl:template>
Did you note that the <xsl:if> "magically" disappeared?
Of course, this code can be improved even further, but you haven't provided neither an instance of the XML document on which the transformation is to be applied, nor the desired output.

Related

how locate an element in source xml file dynamically in a loop

if we have the following xml input:
<root xmlns:ns="http://www.blabla">
<ns:element1 attribute="attr1">10</ns:element1>
<ns:element1 attribute="attr2">20</ns:element1>
<ns:element2 attribute="attr1">30</ns:element1>
<ns:element2 attribute="attr2">40</ns:element1>
</root>
how can we locate each element inside a for-each in xslt?
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root">
<html>
<body>
<h2>My Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Column 1</th>
<th style="text-align:left">Column 2</th>
</tr>
<xsl:for-each select="1 to 10">
<xsl:variable name="name" select="concat('element', .)"/>
<tr>
<td>
<xsl:value-of select="???what should be here???[lower-case(#attribute)='attr0']"/>
</td>
<td>
<xsl:value-of select="???same question???[lower-case(#attribute)='attr1']"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
Please note that I want to follow this procedure (if possible) as the input is very dynamic and we don't always get all elements in every row.
I appreciate your help.
The expression you want is this...
<xsl:value-of select="*[local-name() = $name][lower-case(#attribute)='attr1']"/>
... Except this will fail with an error along the lines of Required item type of context item for the child axis is node(); supplied expression (.) has item type xs:integer, due to the code being executed in the context of the xsl:for-each on atomic values. To get around this, you will need to save a reference to the child elements in a variable before the xsl:for-each.
Try this XSLT
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root">
<html>
<body>
<h2>My Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Title</th>
</tr>
<xsl:variable name="children" select="*" />
<xsl:for-each select="1 to 10">
<xsl:variable name="name" select="concat('element', .)"/>
<tr>
<td>
<xsl:value-of select="$children[local-name() = $name][lower-case(#attribute)='attr1']"/>
</td>
<td>
<xsl:value-of select="$children[local-name() = $name][lower-case(#attribute)='attr2']"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Or slightly better, to reduce code duplication...
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root">
<html>
<body>
<h2>My Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Title</th>
</tr>
<xsl:variable name="children" select="*" />
<xsl:for-each select="1 to 10">
<xsl:variable name="name" select="concat('element', .)"/>
<xsl:variable name="element" select="$children[local-name() = $name]"/>
<tr>
<td>
<xsl:value-of select="$element[lower-case(#attribute)='attr1']"/>
</td>
<td>
<xsl:value-of select="$element[lower-case(#attribute)='attr2']"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Note, I would really consider changing your input XML if you have control over it. Numbering elements using the element name makes it harder to manipulate. Ideally you would do this instead...
<ns:element num="1" attribute="attr1">10</ns:element>
If you dont have control try to take count of the elements and run the loop as per count like this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns="http://www.blabla">
<xsl:template match="root">
<html>
<body>
<h2>My Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th style="text-align:left">Column 1</th>
<th style="text-align:left">Column 2</th>
</tr>
<xsl:variable name="all-element" select="count(//*:element)"/>
<xsl:for-each select="*[concat('ns:element', (1 to $all-element))]">
<xsl:message select="."/>
<tr>
<td>
<xsl:value-of select="#attribute"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

Adding rowspan via XSL

I have the following xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Loci>
<Locus>
<Id>MTBC1726</Id>
<Alleles>
<Allele>
<Name>1.0</Name>
<Description>No annotation provided</Description>
</Allele>
<Allele>
<Name>2.0</Name>
<Description>No annotation provided</Description>
</Allele>
</Alleles>
</Locus>
<Locus>
<Id>MTBC3142</Id>
<Alleles>
<Allele>
<Name>1.0</Name>
<Description>No annotation provided</Description>
</Allele>
</Alleles>
</Locus>
</Loci>
And I want to create the following result:
which, in HTML, would look like this:
<html>
<body>
<table border="1">
<tr>
<th>Locus</th>
<th>Allele</th>
<th>Description</th>
</tr>
<tr>
<td rowspan="2">MTBC1726</td>
<td>1.0</td>
<td >No annotation provided</td>
</tr>
<tr>
<td>2.0</td>
<td >No annotation provided</td>
</tr>
<tr>
<td >MTBC3142</td>
<td>1.0</td>
<td >No annotation provided</td>
</tr>
</table>
</body>
</html>
I have created the following XSL:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr>
<th>Locus</th>
<th>Allele</th>
<th>Description</th>
</tr>
<xsl:for-each select="Loci/Locus">
<tr>
<td><xsl:value-of select="Id"/></td>
<xsl:for-each select="Alleles/Allele">
<td><xsl:value-of select="Name"/></td>
<td><xsl:value-of select="Description"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
but that produces a table like this:
So, my question is: how do I add the rowspan attribute with a count based on the number of <Allele> nodes?
How about this:
<table border="1">
<tr>
<th>Locus</th>
<th>Allele</th>
<th>Description</th>
</tr>
<xsl:for-each select="Loci/Locus">
<xsl:for-each select="Alleles/Allele">
<tr>
<xsl:if test="position() = 1">
<td rowspan="{last()}">
<xsl:value-of select="ancestor::Locus[1]/Id"/>
</td>
</xsl:if>
<td><xsl:value-of select="Name"/></td>
<td><xsl:value-of select="Description"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
The idea here is that within the inner for-each you can use position() to see whether you're on the first Allele for this Locus, and last() to give the number of Allele elements that the current Locus contains. The ancestor::Locus[1] is because we need to extract the Locus Id at a point where the current context is its first Allele.
If you want to avoid adding rowspan="1" for single-allele loci, you'll have to use a conditional xsl:attribute instead of an attribute value template:
<xsl:if test="position() = 1">
<td>
<xsl:if test="last() > 1">
<xsl:attribute name="rowspan">
<xsl:value-of select="last()" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="ancestor::Locus[1]/Id"/>
</td>
</xsl:if>
You could use the XSL count() function to define a variable, and then output that variable as your attribute value:
<xsl:variable name="recordCount" select="count(Alleles/Allele)"/>
<td rowspan="{$recordCount}"><xsl:value-of select="Id"/></td>
You can count the number of Allele and use that value to create your rowspan. I also put in a check so that it didn't add a rowspan=1 for cases when there was only the one Allele
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr>
<th>Locus</th>
<th>Allele</th>
<th>Description</th>
</tr>
<xsl:for-each select="Loci/Locus">
<tr>
<td>
<xsl:if test="count(Alleles/Allele) > 1">
<xsl:attribute name="rowspan">
<xsl:value-of select="count(Alleles/Allele)"/>
</xsl:attribute>
</xsl:if>
<xsl:value-of select="Id"/>
</td>
<xsl:for-each select="Alleles/Allele">
<td><xsl:value-of select="Name"/></td>
<td><xsl:value-of select="Description"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>

XSLT for variable length child nodes

I am trying to write an XSLT template for the following XML structure:
<dealership>
<division>
<division_name>BMW</division_name>
<models>
<model_no>328i</model_no>
<model_no>M3</model_no>
<model_no>X5</model_no>
<model_no>528i</model_no>
</models>
<salesman>
<salesman_name>Bob</salesman_name>
<salesman_name>Jerry</salesman_name>
</salesman>
<mechanics>
<mechanic_name>Greg</mechanic_name>
<mechanic_name>Mike</mechanic_name>
<mechanic_name>Sean</mechanic_name>
</mechanics>
</division>
</dealership>
I need to output it to a HTML table in this format:
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<tr>
<td>BMW</td>
<td>328i</td>
<td>Bob</td>
<td>Greg</td>
</tr>
<tr>
<td></td>
<td>M3</td>
<td>Jerry</td>
<td>Mike</td>
</tr>
<tr>
<td></td>
<td>X5</td>
<td></td>
<td>Sean</td>
</tr>
<tr>
<td></td>
<td>528i</td>
<td></td>
<td></td>
</tr>
</table>
The problem is there can be any number of models, salesman, and mechanics. So somehow I need to get the node with the most children to know how many rows to create in the table, then I need a way to track which cells in the rows are empty. Any help would be greatly appreciated.
The best way I can think of to do it is to call a named template with the row number as a parameter. The template will then check to see if there is any data to output, and if so then build that row of the table and call itself with the next row number as a new parameter value.
This code demonstrates. The output is different from the HTML you show because yours doesn't correspond to the XML data you have given. As far as I can tell this is correct.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="html" />
<xsl:template match="/dealership/division">
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<xsl:call-template name="row" >
<xsl:with-param name="i" select="1" />
</xsl:call-template>
</table>
</xsl:template>
<xsl:template name="row">
<xsl:param name="i"/>
<xsl:if test="models/model_no[$i] |
salesman/salesman_name[$i] |
mechanics/mechanic_name[$i]">
<tr>
<td>
<xsl:value-of select="division_name[$i]"/>
</td>
<td>
<xsl:value-of select="models/model_no[$i]"/>
</td>
<td>
<xsl:value-of select="salesman/salesman_name[$i]"/>
</td>
<td>
<xsl:value-of select="mechanics/mechanic_name[$i]"/>
</td>
</tr>
<xsl:call-template name="row" >
<xsl:with-param name="i" select="$i + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
output
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<tr>
<td>BMW</td>
<td>328i</td>
<td>Bob</td>
<td>Greg</td>
</tr>
<tr>
<td></td>
<td>M3</td>
<td>Jerry</td>
<td>Mike</td>
</tr>
<tr>
<td></td>
<td>X5</td>
<td></td>
<td>Sean</td>
</tr>
</table>
Hear another possible solution.
<xsl:template match="/dealership/division">
<xsl:variable name="maxcnt">
<xsl:for-each select="*" >
<xsl:sort select="count(*)" order="descending"/>
<xsl:if test ="position()=1">
<xsl:value-of select="name(.)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<xsl:apply-templates select="*[name()=$maxcnt]/*" mode="row"/>
</table>
</xsl:template>
<xsl:template match="*" mode="row">
<xsl:variable name="pos" select="count(preceding-sibling::*)+1"/>
<tr>
<td>
<xsl:value-of select="../../division_name[$pos]"/>
</td>
<td>
<xsl:value-of select="../../models/model_no[$pos]"/>
</td>
<td>
<xsl:value-of select="../../salesman/salesman_name[$pos]"/>
</td>
<td>
<xsl:value-of select="../../mechanics/mechanic_name[$pos]"/>
</td>
</tr>
</xsl:template>
The first step is to figure out which child of division has the maximum count of children by it self. This is done by an for-each over all children sorted by count of children. Therefore the first on is the one with most children.
<xsl:for-each select="*" >
<xsl:sort select="count(*)" order="descending"/>
<xsl:if test ="position()=1">
<xsl:value-of select="name(.)"/>
</xsl:if>
</xsl:for-each>
This is based on a very good explanation from Dimitre Novatchev(*)

How to enumerate the sorted records in XSL 1.0?

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>

using urn:helper in xsl

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.