XSLT Remove Blank Element - xslt

I'm trying to remove empty elements within my XML document. I want id31, id32 and id33 removed when they are empty. Below is an example of the XSLT output. I'm trying to use the XSLT below but I'm not having any luck. Any ideas on what I'm doing wrong? Thanks
Data
<Item type="Part AML">
<related_id>
<Item type="Manufacturer Part">
<id keyed_name="1234" type="Manufacturer Part"></id>
<manufacturer keyed_name="Bobs Workshop" type="Manufacturer"></manufacturer>
<item_number>1234</item_number>
</Item>
</related_id>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000005" type="Document">
<Item type="Document">
<id keyed_name="D000005" type="Document"></id>
<major_rev>B</major_rev>
<name>Firmware 8-16-12</name>
<item_number>D000005</item_number>
</Item>
</related_id>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000003" type="Document">
<Item type="Document">
<id keyed_name="D000003" type="Document"></id>
<major_rev>A</major_rev>
<name>Design Spec</name>
<item_number>D000003</item_number>
</Item>
</related_id>
</Item>
Output
<td width="5%" align="center" uniqueID="ms__id31"></td>
<td width="13%" align="center" uniqueID="ms__id32"></td>
<td width="13%" align="center" uniqueID="ms__id33"></td>
<td width="5%" align="center" uniqueID="ms__id34">D000003</td>
<td width="13%" align="center" uniqueID="ms__id35">Design Spec</td>
<td width="8%" align="center" uniqueID="ms__id36">A</td>
Code from forums
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(#*|*|comment()|processing-instruction()) and normalize-space()='']"/>
My XSLT
<xsl:template match="Item[#type='Part AML']|Item[#type='Part Document']">
<tr>
<td width="5%" align="center" uniqueID="ms__id31">
<xsl:value-of select="state"/>
</td>
<td width="13%" align="center" uniqueID="ms__id32">
<xsl:value-of select="related_id[#type='Manufacturer Part']/Item/manufacturer/#keyed_name"/>
</td>
<td width="13%" align="center" uniqueID="ms__id33">
<xsl:value-of select="related_id[#type='Manufacturer Part']/Item/item_number"></xsl:value-of>
</td>
<td width="13%" align="center" uniqueID="ms__id34">
<xsl:value-of select="related_id[#type='Document']/Item/item_number"></xsl:value-of>
</td>
<td width="13%" align="center" uniqueID="ms__id35">
<xsl:value-of select="related_id[#type='Document']/Item/name"/>
</td>
<td width="8%" align="center" uniqueID="ms__id36">
<xsl:value-of select="related_id[#type='Document']/Item/major_rev"/>
</td>
</tr>

Use templates. This way, none are applied in the empty case:
<xsl:template match="Item[#type='Part AML']|Item[#type='Part Document']">
<tr>
<xsl:apply-templates select="state"/>
<xsl:apply-templates select="related_id[#type='Manufacturer Part']/Item/manufacturer/#keyed_name"/>
<xsl:apply-templates select="related_id[#type='Manufacturer Part']/Item/item_number">
<td width="13%" align="center" uniqueID="ms__id34">
<xsl:value-of select="related_id[#type='Document']/Item/item_number"></xsl:value-of>
</td>
<td width="13%" align="center" uniqueID="ms__id35">
<xsl:value-of select="related_id[#type='Document']/Item/name"/>
</td>
<td width="8%" align="center" uniqueID="ms__id36">
<xsl:value-of select="related_id[#type='Document']/Item/major_rev"/>
</td>
</tr>
</xsl:template>
<xsl:template match="Item[#type='Part AML' or #type='Part Document']/state">
<td width="5%" align="center" uniqueID="ms__id31">
<xsl:apply-templates>
</td>
</xsl:template>
<xsl:template match="Item[#type='Part AML' or #type='Part Document']/related_id[#type='Manufacturer Part']/Item/manufacturer/#keyed_name">
<td width="13%" align="center" uniqueID="ms__id32">
<xsl:apply-templates>
</td>
</xsl:template>
<xsl:template match="Item[#type='Part AML' or #type='Part Document']/related_id[#type='Manufacturer Part']/Item/item_number">
<td width="13%" align="center" uniqueID="ms__id33">
<xsl:apply-templates>
</td>
</xsl:template>
You can use the same pattern for the remaining <td>s if they might have empty values too.

Related

grouping elements and adding their element values in xslt

source document:
the below is the xml document.
<?xml version="1.0"?>
<Library>
<Book code="123">
<BookName>XML</BookName>
<Category>Programming</Category>
<Quantity>10</Quantity>
<Price>100</Price>
</Book>
<Book code="345">
<BookName>Photoshop</BookName>
<Category>Design</Category>
<Quantity>50</Quantity>
<Price>200</Price>
</Book>
<Book code="123">
<BookName>XML</BookName>
<Category>Programming</Category>
<Quantity>5</Quantity>
<Price>100</Price>
</Book>
<Book code="345">
<BookName>Photoshop</BookName>
<Category>Design</Category>
<Quantity>10</Quantity>
<Price>200</Price>
</Book>
<Book code="456">
<BookName>Illustrator</BookName>
<Category>Design</Category>
<Quantity>100</Quantity>
<Price>300</Price>
</Book>
</Library>
xslt stylesheet:
this is the present stylesheet. I have tried to use xslt 2. However, I am not getting how to get the desired output.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Books Information</h1>
<table border="1">
<xsl:for-each-group select="Library/Book" group-by="Category">
<xsl:sort select="current-grouping-key()"/>
<tr>
<td colspan="4">Category:
<b>
<xsl:value-of select="current-grouping-key()"/>
</b>
</td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<xsl:apply-templates select="current-group()">
<xsl:sort select="#code"/>
</xsl:apply-templates>
</xsl:for-each-group>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Book">
<tr>
<td><xsl:value-of select="#code"/></td>
<td><xsl:value-of select="Quantity"/></td>
<td><xsl:value-of select="Price"/></td>
<td> </td>
</tr>
</xsl:template>
</xsl:stylesheet>
current output
<html>
<body>
<h1>Books Information</h1>
<table border="1">
<tr>
<td colspan="4">Category:
<b>Design</b></td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<tr>
<td>345</td>
<td>50</td>
<td>200</td>
<td></td>
</tr>
<tr>
<td>345</td>
<td>10</td>
<td>200</td>
<td></td>
</tr>
<tr>
<td>456</td>
<td>100</td>
<td>300</td>
<td></td>
</tr>
<tr>
<td colspan="4">Category:
<b>Programming</b></td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<tr>
<td>123</td>
<td>10</td>
<td>100</td>
<td></td>
</tr>
<tr>
<td>123</td>
<td>5</td>
<td>100</td>
<td></td>
</tr>
</table>
</body>
</html>
expected output
<html>
<body>
<h1>Books Information</h1>
<table border="1">
<tr>
<td colspan="4">Category:
<b>Design</b></td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<tr>
<td>345</td>
<td>60</td>
<td>200</td>
<td>1200</td>
</tr>
<tr>
<td>456</td>
<td>100</td>
<td>300</td>
<td></td>
</tr>
<tr>
<td colspan="4">Subtotal: 1500</td>
</tr>
<tr>
<td colspan="4">Category:
<b>Programming</b></td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<tr>
<td>123</td>
<td>15</td>
<td>1500</td>
<td></td>
</tr>
<tr>
<td colspan="4">subtotal: 1500</td>
</tr>
<tr>
<td colspan="4">Grand TOtal: 3000</td>
</tr>
</table>
</body>
</html>
It looks like you are doing two lots of grouping here. First by "Category" and within each category you then group by "Code".
You first grouping looks fine, but for the second grouping, you need to replace these lines...
<xsl:apply-templates select="current-group()">
<xsl:sort select="#code"/>
</xsl:apply-templates>
With these lines, as this will then group the books within the current category by their code
<xsl:for-each-group select="current-group()" group-by="#code">
<xsl:sort select="current-grouping-key()" />
<xsl:apply-templates select="." />
</xsl:for-each-group>
In terms of getting the totals for each group, you can use this expression
<xsl:value-of select="sum(current-group()/(Quantity * Price))" />
This will work for both groups, so can be used to get the amount for the "code" and the sub-total for the "category". For the overall total, it would just be this
<xsl:value-of select="sum(Library/Book/(Quantity * Price))" />
Try this XSLT
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h1>Books Information</h1>
<table border="1">
<xsl:for-each-group select="Library/Book" group-by="Category">
<xsl:sort select="current-grouping-key()"/>
<tr>
<td colspan="4">Category:
<b>
<xsl:value-of select="current-grouping-key()"/>
</b>
</td>
</tr>
<tr>
<th>Book Code</th>
<th>Quantity</th>
<th>Unit Price</th>
<th>Price</th>
</tr>
<xsl:for-each-group select="current-group()" group-by="#code">
<xsl:sort select="current-grouping-key()" />
<xsl:apply-templates select="." />
</xsl:for-each-group>
<tr>
<td colspan="4">subtotal: <xsl:value-of select="sum(current-group()/(Quantity * Price))" /></td>
</tr>
</xsl:for-each-group>
<tr>
<td colspan="4">Total: <xsl:value-of select="sum(Library/Book/(Quantity * Price))" /></td>
</tr>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Book">
<tr>
<td><xsl:value-of select="#code"/></td>
<td><xsl:value-of select="Quantity"/></td>
<td><xsl:value-of select="Price"/></td>
<td><xsl:value-of select="sum(current-group()/(Quantity * Price))" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>

duplication in xslt preceeding-sibling

i've the below xml document.
<toc-div>
<toc-item>
<toc-title>CHAPTER 1 INTRODUCTION</toc-title>
<toc-subitem num="1.">
<toc-title>The British Virgin Islands</toc-title>
<toc-pg>1.001</toc-pg>
</toc-subitem>
<toc-subitem num="2.">
<toc-title>History and early constitutional developments</toc-title>
<toc-pg>1.003</toc-pg>
</toc-subitem>
<toc-subitem num="3.">
<toc-title>Development as a financial centre</toc-title>
<toc-pg>1.008</toc-pg>
</toc-subitem>
<toc-subitem num="4.">
<toc-title>Common Law and Equity</toc-title>
<toc-pg>1.015</toc-pg>
</toc-subitem>
<toc-subitem num="5.">
<toc-title>Statutes</toc-title>
<toc-pg>1.017</toc-pg>
</toc-subitem>
<toc-subitem num="6.">
<toc-title>Taxation</toc-title>
<toc-pg>1.022</toc-pg>
</toc-subitem>
</toc-item>
and i'm applying the below xslt.
<xsl:template match="toc-subitem">
<table>
<td>
<xsl:value-of select="preceding-sibling::toc-title[1]"/>
</td></table>
<xsl:variable name="tocpg">
<xsl:value-of select="current()/toc-pg"/></xsl:variable>
<xsl:variable name="abc">
<xsl:choose>
<xsl:when test="not(contains(#num, '('))">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="before">
<xsl:value-of select="normalize-space(substring-before($tocpg, '.'))"/>
</xsl:variable>
<xsl:variable name="after">
<xsl:value-of select="normalize-space(substring-after($tocpg, '.'))"/>
</xsl:variable>
<xsl:variable name="z">
<xsl:value-of select="current()/#num"/>
</xsl:variable>
<xsl:variable name="tocpgtag" select="translate($tocpg,'.', '-')"/>
<xsl:variable name="numa" select="number(translate(#num, '.', ''))" />
<xsl:variable name="itemlevel">
<xsl:value-of select="$ThisDocument//ntw:nums[#num=$abc]/#word"/>
</xsl:variable>
<xsl:variable name="tocitemlevel">
<xsl:value-of select="concat('toc-item-', $itemlevel,'-level')"/>
</xsl:variable>
<xsl:variable name="conc">
<xsl:value-of select="concat('er:#BVI_CH_0',$before, '/P', normalize-space($tocpgtag))"/>
</xsl:variable>
<table class="{$tocitemlevel}">
<tbody>
<tr>
<td class="toc-subitem-num">
<xsl:value-of select="$z" />
</td>
<td class="toc-title">
<xsl:value-of select="current()/toc-title" />
</td>
<td class="toc-pg">
<a href="{$conc}">
<xsl:value-of select="current()/toc-pg" />
</a>
</td>
</tr>
</tbody>
</table>
</xsl:template>
when i'm applying this template, the output i'm getting is as below.
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">1.</td>
<td class="toc-title">The British Virgin Islands</td>
<td class="toc-pg">1.001</td>
</tr>
</tbody>
</table>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">2.</td>
<td class="toc-title">History and early constitutional developments</td>
<td class="toc-pg">1.003</td>
</tr>
</tbody>
</table>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">3.</td>
<td class="toc-title">Development as a financial centre</td>
<td class="toc-pg">1.008</td>
</tr>
</tbody>
</table>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">4.</td>
<td class="toc-title">Common Law and Equity</td>
<td class="toc-pg">1.015</td>
</tr>
</tbody>
</table>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">5.</td>
<td class="toc-title">Statutes</td>
<td class="toc-pg">1.017</td>
</tr>
</tbody>
</table>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">6.</td>
<td class="toc-title">Taxation</td>
<td class="toc-pg">1.022</td>
</tr>
</tbody>
</table>
but i want to get it as below
<table>
<td>CHAPTER 1 INTRODUCTION</td>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">1.</td>
<td class="toc-title">The British Virgin Islands</td>
<td class="toc-pg">1.001</td>
</tr>
</tbody>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">2.</td>
<td class="toc-title">History and early constitutional developments</td>
<td class="toc-pg">1.003</td>
</tr>
</tbody>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">3.</td>
<td class="toc-title">Development as a financial centre</td>
<td class="toc-pg">1.008</td>
</tr>
</tbody>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">4.</td>
<td class="toc-title">Common Law and Equity</td>
<td class="toc-pg">1.015</td>
</tr>
</tbody>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">5.</td>
<td class="toc-title">Statutes</td>
<td class="toc-pg">1.017</td>
</tr>
</tbody>
</table>
<table class="toc-item--level">
<tbody>
<tr>
<td class="toc-subitem-num">6.</td>
<td class="toc-title">Taxation</td>
<td class="toc-pg">1.022</td>
</tr>
</tbody>
</table>
please let me know where I'm going wrong.
Thanks
Note:
Your title table is not valid - it does not have <tr>.
The reason your XSLT gave you duplicate toc-title was that you printed it for every toc-subitem processed. In the solution below it is printed only once.
Make the following change to your XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
<xsl:template match="//toc-item">
<table>
<td>
<!-- Print the title *once* -->
<xsl:value-of select="./toc-title"/>
</td>
</table>
<!-- Process each subitem -->
<xsl:apply-templates select="toc-subitem"/>
</xsl:template>
<xsl:template match="toc-subitem">
<!-- Removed the <table> with the preceding sibling -->
<xsl:variable name="tocpg">
<xsl:value-of select="current()/toc-pg"/></xsl:variable>
<!-- Put the rest of your XSLT here, no changes there -->
</xsl:template>
</xsl:stylesheet>
You should use separate templates for this (I also cleaned up a bunch of the <xsl:variable>s):
<xsl:template match="toc-title">
<table>
<tr>
<td>
<xsl:value-of select="preceding-sibling::toc-title[1]"/>
</td>
</tr>
</table>
</xsl:template>
<xsl:template match="toc-subitem">
<xsl:variable name="tocpg" select="toc-pg" />
<xsl:variable name="abc" select="1 + contains(#num, '(')" />
<xsl:variable name="before"
select="normalize-space(substring-before($tocpg, '.'))"/>
<xsl:variable name="after"
select="normalize-space(substring-after($tocpg, '.'))"/>
<xsl:variable name="z" select="#num"/>
<xsl:variable name="tocpgtag" select="translate($tocpg,'.', '-')"/>
<xsl:variable name="numa" select="number(translate(#num, '.', ''))" />
<xsl:variable name="itemlevel"
select="$ThisDocument//ntw:nums[#num=$abc]/#word"/>
<xsl:variable name="tocitemlevel"
select="concat('toc-item-', $itemlevel,'-level')"/>
<xsl:variable name="conc"
select="concat('er:#BVI_CH_0',$before, '/P',
normalize-space($tocpgtag))"/>
<table class="{$tocitemlevel}">
<tbody>
<tr>
<td class="toc-subitem-num">
<xsl:value-of select="$z" />
</td>
<td class="toc-title">
<xsl:value-of select="toc-title" />
</td>
<td class="toc-pg">
<a href="{$conc}">
<xsl:value-of select="toc-pg" />
</a>
</td>
</tr>
</tbody>
</table>
</xsl:template>
However, I think putting every row in its own table is not a very good design. Why have you chosen to do that?
I don't really understand why you'd want output like that (<td> is not a valid child of <table>, for example, in HTML), but this stylesheet should get you closer (I rewrote the stylesheet to split your code into separate <xsl:template> elements):
Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<table>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="toc-item/toc-title">
<td><xsl:value-of select="."/></td>
</xsl:template>
<xsl:template match="toc-subitem">
<!--
I don't know how your code that fetches the TOC item level is supposed
to work so you'll have to figure that out yourself.
-->
<table class="toc-item-$level-level">
<tbody>
<tr>
<xsl:apply-templates select="#* | node()"/>
</tr>
</tbody>
</table>
</xsl:template>
<xsl:template match="#num">
<td class="toc-subitem-num">
<xsl:value-of select="."/>
</td>
</xsl:template>
<xsl:template match="toc-subitem/toc-title">
<td class="toc-title">
<xsl:value-of select="."/>
</td>
</xsl:template>
<xsl:template match="toc-pg">
<td class="toc-pg">
<a href="{concat('er:#BVI_CH_0', substring-before(., '.'), '/P', translate(., '.', '-'))}">
<xsl:value-of select="."/>
</a>
</td>
</xsl:template>
</xsl:stylesheet>
Input
<?xml version="1.0"?>
<toc-div>
<toc-item>
<toc-title>CHAPTER 1 INTRODUCTION</toc-title>
<toc-subitem num="1.">
<toc-title>The British Virgin Islands</toc-title>
<toc-pg>1.001</toc-pg>
</toc-subitem>
<toc-subitem num="2.">
<toc-title>History and early constitutional developments</toc-title>
<toc-pg>1.003</toc-pg>
</toc-subitem>
<toc-subitem num="3.">
<toc-title>Development as a financial centre</toc-title>
<toc-pg>1.008</toc-pg>
</toc-subitem>
<toc-subitem num="4.">
<toc-title>Common Law and Equity</toc-title>
<toc-pg>1.015</toc-pg>
</toc-subitem>
<toc-subitem num="5.">
<toc-title>Statutes</toc-title>
<toc-pg>1.017</toc-pg>
</toc-subitem>
<toc-subitem num="6.">
<toc-title>Taxation</toc-title>
<toc-pg>1.022</toc-pg>
</toc-subitem>
</toc-item>
</toc-div>
Output
<html>
<body>
<table>
<td>CHAPTER 1 INTRODUCTION</td>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">1.</td>
<td class="toc-title">The British Virgin Islands</td>
<td class="toc-pg">
1.001
</td>
</tr>
</tbody>
</table>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">2.</td>
<td class="toc-title">History and early constitutional developments</td>
<td class="toc-pg">
1.003
</td>
</tr>
</tbody>
</table>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">3.</td>
<td class="toc-title">Development as a financial centre</td>
<td class="toc-pg">
1.008
</td>
</tr>
</tbody>
</table>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">4.</td>
<td class="toc-title">Common Law and Equity</td>
<td class="toc-pg">
1.015
</td>
</tr>
</tbody>
</table>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">5.</td>
<td class="toc-title">Statutes</td>
<td class="toc-pg">
1.017
</td>
</tr>
</tbody>
</table>
<table class="toc-item-$level-level">
<tbody>
<tr>
<td class="toc-subitem-num">6.</td>
<td class="toc-title">Taxation</td>
<td class="toc-pg">
1.022
</td>
</tr>
</tbody>
</table>
</table>
</body>
</html>
Just remove the <html> and <body> elements from the first <xsl:template> rule if you really don't need them.

XSLT Dynamic Rows

I'm having an issue with the data being properly formatted. The top level node is Part. The elements below the node are AML and Documents. The AML and Documents can be different values. AML can be greater than Documents and Documents can be greater then AML. I need the elements for Documents and AML to be on the same row, so that the table is properly formatted. Please let me know if you need anymore information and thank you for your help its greatly appreciated.
Data
<Item type="Part">
<item_number>E008643</item_number>
<Relationships>
<Item type="Part AML">
<related_id keyed_name="0000-009" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Fasteners Co." type="Manufacturer"></manufacturer>
<item_number>0000-009</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part AML">
<related_id keyed_name="1234" type="Manufacturer Part">
<Item type="Manufacturer Part">
<id keyed_name="1234" type="Manufacturer Part"></id>
<manufacturer keyed_name="Vishay/Dale" type="Manufacturer"></manufacturer>
<item_number>1234</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000006" type="Document">
<Item type="Document">
<id keyed_name="D000006" type="Document"></id>
<major_rev>B</major_rev>
<name>Hardware Doc</name>
<item_number>D000006</item_number>
</Item>
</related_id>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000005" type="Document">
<Item type="Document">
<major_rev>B</major_rev>
<name>Firmware</name>
<item_number>D000005</item_number>
</Item>
</related_id>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000003" type="Document">
<Item type="Document">
<major_rev>A</major_rev>
<name>Design Spec</name>
<item_number>D000003</item_number>
</Item>
</related_id>
</Item>
<Item type="Part BOM">
<related_id keyed_name="E000371" type="Part">
<Item type="Part">
<item_number>E000371</item_number>
<Relationships>
<Item type="Part AML">
<related_id keyed_name="3Z1JTTD" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Speer" type="Manufacturer"></manufacturer>
<item_number>3Z1JTTD</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part AML">
<related_id keyed_name="000T" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Nickel" type="Manufacturer"></manufacturer>
<item_number>000T</item_number>
</Item>
</related_id>
<source_id keyed_name="E000371" type="Part"></source_id>
<state>Preliminary</state>
</Item>
<Item type="Part AML">
<related_id keyed_name="R00V" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Sonic" type="Manufacturer"></manufacturer>
<item_number>R00V</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part AML">
<related_id keyed_name="TRF" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Components" type="Manufacturer"></manufacturer>
<item_number>TRF</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part AML">
<related_id keyed_name="70RL" type="Manufacturer Part">
<Item type="Manufacturer Part">
<manufacturer keyed_name="Comp" type="Manufacturer"></manufacturer>
<item_number>70RL</item_number>
</Item>
</related_id>
<state>Preliminary</state>
</Item>
<Item type="Part Document">
<related_id keyed_name="D000007" type="Document">
<Item type="Document">
<major_rev>B</major_rev>
<name>BOX</name>
<item_number>D000007</item_number>
</Item>
</related_id>
<state is_null="1" />
</Item>
<Item type="Part Document">
<related_id keyed_name="D000008" type="Document">
<Item type="Document">
<major_rev>A</major_rev>
<name>SOCKET</name>
<item_number>D000008</item_number>
</Item>
</related_id>
<state is_null="1" />
</Item>
</Relationships>
</Item>
</related_id>
</Item>
</Relationships>
Style Sheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:aras="http://www.aras-corp.com" exclude-result-prefixes="msxsl">
<xsl:output method="html" omit-xml-declaration="yes" standalone="yes" indent="yes"></xsl:output>
<xsl:template match="/">
<html>
<head></head>
<style type="text/css" userData="Global">
table {empty-cells:show; border-collapse:collapse;}
th {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid; background-color:#CCCCCC; text-transform:capitalize;}
td {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid;}
td.noBorder {font-family:helvetica; font-size:8pt; padding:2px; border-width:0;}
</style>
<body topmargin="50" leftmargin="50">
<table border="0" cellspacing="0" cellpadding="0" width="1850">
<tr valign="top">
<td class="noBorder" align="left" colspan="9" uniqueID="ms__id39">
</td>
</tr>
<tr valign="bottom">
<td class="noBorder" colspan="13" style="font-family:helvetica;font-size:15pt;color:#DA1943;padding:2px;" align="left" uniqueID="ms__id22">Bill of Materials Report - <xsl:value-of select="//Item/name"></xsl:value-of> Rev <xsl:value-of select="//Item/major_rev"></xsl:value-of>
</td>
<td class="noBorder" colspan="7" style="font-family:helvetica;font-size:10pt;padding:2px;" align="right" uniqueID="ms__id23">Generated on: <script>function m00(r, n){r += ""; if (!n) n = 2; while(r.length < n){r = "0" + r;} return r;} var dt = new Date(); var a = top.opener.top.aras; if (a){var s = m00(dt.getUTCFullYear(),4)+"-"+m00((dt.getUTCMonth()+1))+"-"+m00(dt.getUTCDate())+"T"+m00(dt.getUTCHours())+":"+m00(dt.getUTCMinutes())+":"+m00(dt.getUTCSeconds())+"+0000"; s = a.convertToNeutral(s, "date", "yyyy-MM-ddTHH:mm:sszzz"); s = a.convertFromNeutral(s, "date", "short_date"); document.write(s);}</script>
</td>
</tr>
<tr>
<th>Part Number</th>
<th>Manufacturer</th>
<th>Manufacturer Part</th>
<th>Document Number</th>
<th>Document Name</th>
<th>Document Rev</th>
</tr>
<xsl:apply-templates select="//Item[#type='Part']"></xsl:apply-templates>
</table>
</body>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
</html>
</xsl:template>
<xsl:template match="Item[#type='Part']">
<!-- Find the number Row Span -->
<xsl:variable name="AML">
<xsl:choose>
<xsl:when test="count(Relationships/Item[#type='Part AML'])=0">1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(Relationships/Item[#type='Part AML'])"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="Doc">
<xsl:choose>
<xsl:when test="count(Relationships/Item[#type='Part Document'])=0">1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="count(Relationships/Item[#type='Part Document'])"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="rowCount">
<xsl:choose>
<xsl:when test="$AML < $Doc"><xsl:value-of select="$Doc"></xsl:value-of></xsl:when>
<xsl:otherwise>
<xsl:value-of select="$AML"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Grab values -->
<tr>
<td rowspan="{$rowCount}" width="5%" align="center" uniqueID="ms__id16">
<xsl:value-of select="item_number"></xsl:value-of>
</td>
<td width="13%" align="center" uniqueID="ms__id26">
<xsl:value-of select="Relationships/Item[#type='Part AML'][1]/related_id/Item/manufacturer/#keyed_name"></xsl:value-of>
</td>
<td width="13%" align="center" uniqueID="ms__id27">
<xsl:value-of select="Relationships/Item[#type='Part AML'][1]/related_id/Item/item_number"></xsl:value-of>
</td>
<td width="5%" align="center" uniqueID="ms__id28">
<xsl:value-of select="Relationships/Item[#type='Part Document'][1]/related_id/Item/item_number"></xsl:value-of>
</td>
<td width="13%px" align="center" uniqueID="ms__id29">
<xsl:value-of select="Relationships/Item[#type='Part Document'][1]/related_id/Item/name"></xsl:value-of>
</td>
<td width="8%" align="center" uniqueID="ms__id30">
<xsl:value-of select="Relationships/Item[#type='Part Document'][1]/related_id/Item/major_rev"></xsl:value-of>
</td>
<td rowspan="{$rowCount}" width="8%" align="center" uniqueID="ms__id37">
<xsl:value-of select="count(Relationships/Item[#type='Part AML'])"></xsl:value-of>
</td>
<td rowspan="{$rowCount}" width="8%" align="center" uniqueID="ms__id38">
<xsl:value-of select="count(Relationships/Item[#type='Part Document'])"></xsl:value-of>
</td>
<td rowspan="{$rowCount}" width="8%" align="center" uniqueID="ms__id40">
<xsl:value-of select="position() mod 2 = 1"></xsl:value-of>
</td>
</tr>
<!-- Assing first row for AML and Doc -->
<xsl:apply-templates select="Relationships/Item[#type='Part AML'][position()!=1]|Relationships/Item[#type='Part Document'][position()!=1]"></xsl:apply-templates>
</xsl:template>
<!-- AML and Doc Rows 2+ -->
<xsl:template match="text()" />
<xsl:template match="Item[#type = 'Part AML'][not(following-sibling::Item[1]/#type = 'Part Document')]">
<xsl:call-template name="ItemRow">
<xsl:with-param name="AmlItem" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template match="Item[#type='Part Document']">
<xsl:variable name="lastItem" select="preceding-sibling::Item[1][#type = 'Part AML']" />
<xsl:call-template name="ItemRow">
<xsl:with-param name="AmlItem" select="$lastItem" />
<xsl:with-param name="PartDocument" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="ItemRow">
<xsl:param name="AmlItem" />
<xsl:param name="PartDocument" select="_" />
<xsl:variable name="rowData">
<row value="{$AmlItem/related_id/Item/manufacturer/#keyed_name}" id="32" />
<row value="{$AmlItem/related_id/Item[#type='Manufacturer Part']/item_number}" id="33" />
<row value="{$PartDocument/related_id[#type='Document']/Item/item_number}" id="34" />
<row value="{$PartDocument/related_id[#type='Document']/Item/name}" id="35" />
<row value="{$PartDocument/related_id[#type='Document']/Item/major_rev}" id="36" />
</xsl:variable>
<tr>
<xsl:for-each select="msxsl:node-set($rowData)/row">
<td width="13%" align="center" uniqueID="ms__id{#id}">
<xsl:value-of select="#value"/>
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
Output 1-7-12
<td width="13%" align="center" uniqueID="ms__id32">Bobs Workshop</td>
<td width="13%" align="center" uniqueID="ms__id33">1234</td>
<td width="13%" align="center" uniqueID="ms__id34">D000005</td>
<td width="13%" align="center" uniqueID="ms__id35">Firmware</td>
<td width="13%" align="center" uniqueID="ms__id36">B</td>
<td width="13%" align="center" uniqueID="ms__id34">D000003</td>
<td width="13%" align="center" uniqueID="ms__id35">Design Spec</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
Desired Output
<!-- If both present -->
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Bobs Workshop</td>
<td width="13%" align="center" uniqueID="ms__id33">1234</td>
<td width="13%" align="center" uniqueID="ms__id34">D000005</td>
<td width="13%" align="center" uniqueID="ms__id35">Firmware</td>
<td width="13%" align="center" uniqueID="ms__id36">B</td>
</tr>
<!-- If only Doc is present -->
<tr>
<td width="13%" align="center" uniqueID="ms__id32">""</td>
<td width="13%" align="center" uniqueID="ms__id33">""</td>
<td width="13%" align="center" uniqueID="ms__id34">D000003</td>
<td width="13%" align="center" uniqueID="ms__id35">Design Spec</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
</tr>
<!-- If only AML is present -->
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Nickel</td>
<td width="13%" align="center" uniqueID="ms__id33">000T</td>
<td width="13%" align="center" uniqueID="ms__id34">""</td>
<td width="13%" align="center" uniqueID="ms__id35">""</td>
<td width="13%" align="center" uniqueID="ms__id36">""</td>
</tr>
Desired Full HTML Output
<html xmlns:aras="http://www.aras-corp.com">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-16">
</head>
<style type="text/css" userData="Global">
table {empty-cells:show; border-collapse:collapse;}
th {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid; background-color:#CCCCCC; text-transform:capitalize;}
td {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid;}
td.noBorder {font-family:helvetica; font-size:8pt; padding:2px; border-width:0;}
</style>
<body topmargin="50" leftmargin="50">
<table border="0" cellspacing="0" cellpadding="0" width="1850">
<tr valign="top">
</tr>
<tr valign="bottom">
<td class="noBorder" colspan="13" style="font-family:helvetica;font-size:15pt;color:#DA1943;padding:2px;" align="left" uniqueID="ms__id22">Bill of Materials Report - 9.6 Hz Parts Rev 1</td>
<td class="noBorder" colspan="7" style="font-family:helvetica;font-size:10pt;padding:2px;" align="right" uniqueID="ms__id23">Generated on: <script>function m00(r, n){r += ""; if (!n) n = 2; while(r.length < n){r = "0" + r;} return r;} var dt = new Date(); var a = top.opener.top.aras; if (a){var s = m00(dt.getUTCFullYear(),4)+"-"+m00((dt.getUTCMonth()+1))+"-"+m00(dt.getUTCDate())+"T"+m00(dt.getUTCHours())+":"+m00(dt.getUTCMinutes())+":"+m00(dt.getUTCSeconds())+"+0000"; s = a.convertToNeutral(s, "date", "yyyy-MM-ddTHH:mm:sszzz"); s = a.convertFromNeutral(s, "date", "short_date"); document.write(s);}</script></td>
</tr>
<tr>
<th colspan="6">Indenture Level</th>
<th>Part Number</th>
<th>Legacy Part Number</th>
<th>Revision</th>
<th>Name</th>
<th>Description</th>
<th>Parameters</th>
<th>RoHS/Pb-Free</th>
<th>Quantity</th>
<th>Reference Designator</th>
<th>Manufacturer</th>
<th>Manufacturer Part</th>
<th>Document Number</th>
<th>Document Name</th>
<th>Document Rev</th>
<th>Pos AML</th>
<th>Pos Doc</th>
<th>Mod</th>
</tr>
<tr>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id10">0</td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id11"></td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id12"></td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id13"></td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id14"></td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id15"></td>
<td rowspan="3" width="5%" align="center" uniqueID="ms__id16">E008643</td>
<td rowspan="3" width="5%" align="center" uniqueID="ms__id17"></td>
<td rowspan="3" width="2%" align="center" uniqueID="ms__id18">1</td>
<td rowspan="3" width="13%" align="center" uniqueID="ms__id19">9.6 Hz Parts</td>
<td rowspan="3" width="13%" align="center" uniqueID="ms__id20">Test</td>
<td rowspan="3" width="13%" align="center" uniqueID="ms__id21">Assembly</td>
<td rowspan="3" width="5%" align="center" uniqueID="ms__id22"></td>
<td rowspan="3" width="5%" align="center" uniqueID="ms__id23">1</td>
<td rowspan="3" width="5%" align="center" uniqueID="ms__id24"></td>
<td width="13%" align="center" uniqueID="ms__id26">Fasteners Co.</td>
<td width="13%" align="center" uniqueID="ms__id27">009</td>
<td width="5%" align="center" uniqueID="ms__id28">D000006</td>
<td width="13%px" align="center" uniqueID="ms__id29">Hardware Doc</td>
<td width="8%" align="center" uniqueID="ms__id30">B</td>
<td rowspan="3" width="8%" align="center" uniqueID="ms__id37">2</td>
<td rowspan="3" width="8%" align="center" uniqueID="ms__id38">3</td>
<td rowspan="3" width="8%" align="center" uniqueID="ms__id40">true</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Vishay/Dale</td>
<td width="13%" align="center" uniqueID="ms__id33">1234</td>
<td width="13%" align="center" uniqueID="ms__id34">D000005</td>
<td width="13%" align="center" uniqueID="ms__id35">Firmware</td>
<td width="13%" align="center" uniqueID="ms__id36">B</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32"></td>
<td width="13%" align="center" uniqueID="ms__id33"></td>
<td width="13%" align="center" uniqueID="ms__id34">D000003</td>
<td width="13%" align="center" uniqueID="ms__id35">Design Spec</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
</tr>
<tr>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id10"></td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id11">1</td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id12"></td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id13"></td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id14"></td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id15"></td>
<td rowspan="5" width="5%" align="center" uniqueID="ms__id16">E000371</td>
<td rowspan="5" width="5%" align="center" uniqueID="ms__id17">0061</td>
<td rowspan="5" width="2%" align="center" uniqueID="ms__id18">A</td>
<td rowspan="5" width="13%" align="center" uniqueID="ms__id19">0?</td>
<td rowspan="5" width="13%" align="center" uniqueID="ms__id20">Thick Film ''</td>
<td rowspan="5" width="13%" align="center" uniqueID="ms__id21">0, 100, 0.05</td>
<td rowspan="5" width="5%" align="center" uniqueID="ms__id22">Yes</td>
<td rowspan="5" width="5%" align="center" uniqueID="ms__id23">1</td>
<td rowspan="5" width="5%" align="center" uniqueID="ms__id24">R34</td>
<td width="13%" align="center" uniqueID="ms__id26">Speer</td>
<td width="13%" align="center" uniqueID="ms__id27">RK73Z1JTTD</td>
<td width="5%" align="center" uniqueID="ms__id28">D000010</td>
<td width="13%px" align="center" uniqueID="ms__id29">BOX</td>
<td width="8%" align="center" uniqueID="ms__id30">B</td>
<td rowspan="5" width="8%" align="center" uniqueID="ms__id37">5</td>
<td rowspan="5" width="8%" align="center" uniqueID="ms__id38">3</td>
<td rowspan="5" width="8%" align="center" uniqueID="ms__id40">false</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Nickel</td>
<td width="13%" align="center" uniqueID="ms__id33">000T</td>
<td width="13%" align="center" uniqueID="ms__id34">D000011</td>
<td width="13%" align="center" uniqueID="ms__id35">SOCKET</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Sonic</td>
<td width="13%" align="center" uniqueID="ms__id33">R00V</td>
<td width="13%" align="center" uniqueID="ms__id34">D000007</td>
<td width="13%" align="center" uniqueID="ms__id35">MOUNT</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32">NIC</td>
<td width="13%" align="center" uniqueID="ms__id33">OTRF</td>
<td width="13%" align="center" uniqueID="ms__id34"></td>
<td width="13%" align="center" uniqueID="ms__id35"></td>
<td width="13%" align="center" uniqueID="ms__id36"></td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32">Test</td>
<td width="13%" align="center" uniqueID="ms__id33">9874</td>
<td width="13%" align="center" uniqueID="ms__id34"></td>
<td width="13%" align="center" uniqueID="ms__id35"></td>
<td width="13%" align="center" uniqueID="ms__id36"></td>
</tr>
<tr>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id10"></td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id11">1</td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id12"></td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id13"></td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id14"></td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id15"></td>
<td rowspan="2" width="5%" align="center" uniqueID="ms__id16">E001163</td>
<td rowspan="2" width="5%" align="center" uniqueID="ms__id17">0145</td>
<td rowspan="2" width="2%" align="center" uniqueID="ms__id18">A</td>
<td rowspan="2" width="13%" align="center" uniqueID="ms__id19">8200</td>
<td rowspan="2" width="13%" align="center" uniqueID="ms__id20">PPS Film ''</td>
<td rowspan="2" width="13%" align="center" uniqueID="ms__id21">
</td>
<td rowspan="2" width="5%" align="center" uniqueID="ms__id22">Yes</td>
<td rowspan="2" width="5%" align="center" uniqueID="ms__id23">30</td>
<td rowspan="2" width="5%" align="center" uniqueID="ms__id24">C1-C5,C12,C17,C22,C25,C27-C29,C31</td>
<td width="13%" align="center" uniqueID="ms__id26">Sonic</td>
<td width="13%" align="center" uniqueID="ms__id27">822GX5</td>
<td width="5%" align="center" uniqueID="ms__id28">D000012</td>
<td width="13%px" align="center" uniqueID="ms__id29">Doc Test</td>
<td width="8%" align="center" uniqueID="ms__id30">A</td>
<td rowspan="2" width="8%" align="center" uniqueID="ms__id37">2</td>
<td rowspan="2" width="8%" align="center" uniqueID="ms__id38">2</td>
<td rowspan="2" width="8%" align="center" uniqueID="ms__id40">true</td>
</tr>
<tr>
<td width="13%" align="center" uniqueID="ms__id32"></td>
<td width="13%" align="center" uniqueID="ms__id33"></td>
<td width="13%" align="center" uniqueID="ms__id34">D000008</td>
<td width="13%" align="center" uniqueID="ms__id35">ADAPTER</td>
<td width="13%" align="center" uniqueID="ms__id36">A</td>
</tr>
</table>
</body><script src="../../javascript/PopupMenu.js"></script><script src="../../javascript/PopupMenu.js"></script><script src="../../javascript/PopupMenu.js"></script><script src="../../javascript/PopupMenu.js"></script></html>
What XSLT processor are you using?
I believe this should do what you want:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:aras="http://www.aras-corp.com" exclude-result-prefixes="msxsl">
<xsl:output method="html" omit-xml-declaration="yes" standalone="yes" indent="yes"></xsl:output>
<xsl:template match="/">
<html>
<head></head>
<style type="text/css" userData="Global">
table {empty-cells:show; border-collapse:collapse;}
th {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid; background-color:#CCCCCC; text-transform:capitalize;}
td {font-family:helvetica; font-size:8pt; padding:2px; border:1px #000000 solid;}
td.noBorder {font-family:helvetica; font-size:8pt; padding:2px; border-width:0;}
</style>
<body topmargin="50" leftmargin="50">
<table border="0" cellspacing="0" cellpadding="0" width="1850">
<tr valign="top">
<td class="noBorder" align="left" colspan="9" uniqueID="ms__id39">
</td>
</tr>
<tr valign="bottom">
<td class="noBorder" colspan="13" style="font-family:helvetica;font-size:15pt;color:#DA1943;padding:2px;" align="left" uniqueID="ms__id22">
Bill of Materials Report - <xsl:value-of select="//Item/name"></xsl:value-of> Rev <xsl:value-of select="//Item/major_rev"></xsl:value-of>
</td>
<td class="noBorder" colspan="7" style="font-family:helvetica;font-size:10pt;padding:2px;" align="right" uniqueID="ms__id23">
Generated on: <script>function m00(r, n){r += ""; if (!n) n = 2; while(r.length < n){r = "0" + r;} return r;} var dt = new Date(); var a = top.opener.top.aras; if (a){var s = m00(dt.getUTCFullYear(),4)+"-"+m00((dt.getUTCMonth()+1))+"-"+m00(dt.getUTCDate())+"T"+m00(dt.getUTCHours())+":"+m00(dt.getUTCMinutes())+":"+m00(dt.getUTCSeconds())+"+0000"; s = a.convertToNeutral(s, "date", "yyyy-MM-ddTHH:mm:sszzz"); s = a.convertFromNeutral(s, "date", "short_date"); document.write(s);}</script>
</td>
</tr>
<tr>
<th width="12%" colspan="6">Indent Level</th>
<th width="5%">Part Number</th>
<th width="13%">Manufacturer</th>
<th width="13%">Manufacturer Part</th>
<th width="13%">Document Number</th>
<th width="13%">Document Name</th>
<th width="13%">Document Rev</th>
<th width="8%">Pos AML</th>
<th width="8%">Pos Doc</th>
<th width="8%">Mod</th>
</tr>
<xsl:apply-templates select="//Item[#type='Part']"></xsl:apply-templates>
</table>
</body>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
<script src="../../javascript/PopupMenu.js"></script>
</html>
</xsl:template>
<xsl:template match="Item[#type='Part']">
<xsl:variable name="AmlItems" select="Relationships/Item[#type='Part AML']"/>
<xsl:variable name="DocItems" select="Relationships/Item[#type='Part Document']"/>
<xsl:variable name="MoreAmlItems" select="count($AmlItems) > count($DocItems)" />
<xsl:variable name="largerGroup" select="$AmlItems[$MoreAmlItems] | $DocItems[not($MoreAmlItems)]" />
<!-- Ensure rowCount is at least 1 -->
<xsl:variable name="rowCount" select="count($largerGroup) + (count($largerGroup) = 0)"/>
<!-- Grab values -->
<tr>
<xsl:call-template name="IndentLevel">
<xsl:with-param name="rowSpan" select="$rowCount" />
</xsl:call-template>
<td rowspan="{$rowCount}" align="center" uniqueID="ms__id16">
<xsl:value-of select="item_number"></xsl:value-of>
</td>
<xsl:apply-templates select="$largerGroup[1]" />
<td rowspan="{$rowCount}" align="center" uniqueID="ms__id37">
<xsl:value-of select="count($AmlItems)"></xsl:value-of>
</td>
<td rowspan="{$rowCount}" align="center" uniqueID="ms__id38">
<xsl:value-of select="count($DocItems)"></xsl:value-of>
</td>
<td rowspan="{$rowCount}" align="center" uniqueID="ms__id40">
<xsl:value-of select="position() mod 2 = 1"></xsl:value-of>
</td>
</tr>
<!-- Assing first row for AML and Doc -->
<xsl:apply-templates select="$largerGroup[position() > 1]"></xsl:apply-templates>
</xsl:template>
<xsl:template name="IndentLevel">
<xsl:param name="level" select="0" />
<xsl:param name="rowSpan" />
<td rowspan="{$rowSpan}" width="2%" align="center" uniqueID="ms__id{10+$level}">
<xsl:if test="count(ancestor::Item[#type = 'Part']) = $level">
<xsl:value-of select="$level"/>
</xsl:if>
</td>
<!-- Stop when we reach 5 -->
<xsl:if test="$level < 5">
<xsl:call-template name="IndentLevel">
<xsl:with-param name="level" select="$level + 1" />
<xsl:with-param name="rowSpan" select="$rowSpan" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<!-- AML and Doc Rows 2+ -->
<xsl:template match="text()" />
<xsl:template match="Item[#type = 'Part AML']">
<xsl:variable name="pos" select="position()" />
<xsl:variable name="isTop" select="not(preceding-sibling::Item[#type = 'Part AML'])"/>
<xsl:call-template name="ItemRow">
<xsl:with-param name="AmlItem" select="." />
<xsl:with-param name="PartDocument" select="../Item[#type = 'Part Document'][position() = $pos + not($isTop)]" />
<xsl:with-param name="IsTop" select="$isTop" />
</xsl:call-template>
</xsl:template>
<xsl:template match="Item[#type='Part Document']">
<xsl:variable name="pos" select="position()" />
<xsl:variable name="isTop" select="not(preceding-sibling::Item[#type = 'Part Document'])"/>
<xsl:call-template name="ItemRow">
<xsl:with-param name="AmlItem" select="../Item[#type = 'Part AML'][position() = $pos + not($isTop)]" />
<xsl:with-param name="PartDocument" select="." />
<xsl:with-param name="IsTop" select="$isTop" />
</xsl:call-template>
</xsl:template>
<xsl:template name="ItemRow">
<xsl:param name="AmlItem" />
<xsl:param name="PartDocument" select="_" />
<xsl:param name="IsTop" />
<xsl:variable name="startingId" select="26 * $IsTop + 32 * not($IsTop)" />
<xsl:variable name="rowData">
<cell value="{$AmlItem/related_id/Item/manufacturer/#keyed_name}" />
<cell value="{$AmlItem/related_id/Item[#type='Manufacturer Part']/item_number}" />
<cell value="{$PartDocument/related_id[#type='Document']/Item/item_number}" />
<cell value="{$PartDocument/related_id[#type='Document']/Item/name}" />
<cell value="{$PartDocument/related_id[#type='Document']/Item/major_rev}" />
</xsl:variable>
<xsl:variable name="rowCells">
<xsl:call-template name="RowCells">
<xsl:with-param name="rowData" select="$rowData" />
<xsl:with-param name="startingId" select="$startingId" />
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$IsTop">
<xsl:copy-of select="$rowCells"/>
</xsl:when>
<xsl:otherwise>
<tr>
<xsl:copy-of select="$rowCells"/>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RowCells">
<xsl:param name="rowData" />
<xsl:param name="startingId" />
<xsl:for-each select="msxsl:node-set($rowData)/cell">
<td align="center" uniqueID="ms__id{$startingId + position() - 1}">
<xsl:value-of select="#value"/>
</td>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
If you're using a non-Microsoft XSLT processor, you would need to change the msxsl namespace to something else according to the table on this page:
http://www.xml.com/pub/a/2003/07/16/nodeset.html
There seems to be an inconsistency between your source XML and your output. The <related_id> in the first Item has no type attribute, so your [#type='Manufacturer Part'] filter would fail to locate anything. Is there supposed to be a type attribute there?
In your first template I would change it like this.
<xsl:template match="Item[#type='Part AML']|Item[#type='Part Document']">
<tr>
<xsl:apply-templates select="related_id/Item/manufacturer/#keyed_name"/>
...
</tr>
</xsl:template>
That should build out your rows like you want.

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.

Using keys in xslt for converting trx file of mstest

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.