I need to perform a cyclical sequence within another public secuanci and get the data of each person and each status, the problem that I have with the code is that it does not iterate the data that I am delivering. I need help in the second for-each when I have empty fields and then I can work with Word content controls
XML file
<?xml version="1.0"?>
<emailList>
<person>
<name>name 1</name>
<email>g#gmail.com</email>
<status>
<active>1</active>
<active>2</active>
<active>3</active>
</status>
</person>
<person>
<name>name 2</name>
<email>n#hotmail.com</email>
<status>
<active>4</active>
<active>5</active>
</status>
</person>
</emailList>
XSL file
<xsl:stylesheet version="1.0">
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
<head>
<title>Email Listing</title>
</head>
<body>
<table>
<tr>
<th>Name</th>
<th>E-mail Address</th>
<th>Status</th>
</tr>
<xsl:for-each select="emailList/person">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
<td>
<xsl:for-each select="emailList/person/status">
<xsl:value-of select="active"/>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
You inner xsl:for-each will be relative to the outer one, which is selecting person.
Try changing it to this...
<xsl:for-each select="status/active">
<xsl:value-of select="."/>
</xsl:for-each>
Where . selects the current node.
If you wanted to separate the values by commas, you could do this....
<xsl:for-each select="status/active">
<xsl:if test="position() > 1">,</xsl:if>
<xsl:value-of select="."/>
</xsl:for-each>
Better still, upgrade to XSLT 2.0 and do away with this xsl:for-each entirely..
<td>
<xsl:value-of select="status/active" separator="," />
</td>
<xsl:template match="/">
<html>
<head>
<title>Email Listing</title>
</head>
<body>
<table>
<tr>
<th>Name</th>
<th>E-mail Address</th>
<th>Status</th>
</tr>
<xsl:for-each select="emailList/person">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="email"/></td>
<td>
<xsl:for-each select="status">
<xsl:value-of select="active"/>
</xsl:for-each>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
Related
Here is an excerpt from an xsl document (inside a template technically):
<table>
<tr>
<th>INSTANCE</th>
<th>SWVER</th>
<th>SYSTEMID</th>
<th>SYSTIME</th>
<th>SYSMEM</th>
<th>CUTMEM</th>
<th>FILEMEM</th>
<th>CALCONFIG</th>
</tr>
<tr>
<td><xsl:value-of select='#INSTANCE'/></td>
<td><xsl:value-of select='#SWVER'/></td>
<td><xsl:value-of select='#SYSTEMID'/></td>
<td><xsl:value-of select='#SYSTIME'/></td>
<td><xsl:value-of select='#SYSMEM'/></td>
<td><xsl:value-of select='#CUTMEM'/></td>
<td><xsl:value-of select='#FILEMEM'/></td>
<td><xsl:value-of select="#CALCONFIG"/></td>
</tr>
</table>
Is there some way that I can avoid the redundancy of writing out the attributes both as table headers and as the attribute selection? I cannot use external sources.
I was thinking I could define some xsl variable that contains a basic structure, as follows and generate the table from there.
<list>
<item>INSTANCE</item>
...
<item>CALCONFIG</item>
</list>
The XML data is just a bunch of tags, of the same value that contain at least the above listed attributes. Each tag looks something like this:
<THING INSTANCE="boop" SWVER="foo" SYSTEMID="123"
...
CALCONFIG="cal.cfg" SOMETHINGELSE="bar"
/>
To illustrate the point I made in a comment to your question, consider the following example:
XML
<root>
<item color="red" name="alpha" size="small" garbage="123" id="1"/>
<item color="green" name="bravo" size="medium" garbage="456" id="2"/>
<item color="blue" name="charlie" size="large" garbage="789" id="3"/>
</root>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://www.example.com/my"
exclude-result-prefixes="my">
<xsl:output method="html" encoding="utf-8"/>
<xsl:strip-space elements="*"/>
<my:columns>
<col>id</col>
<col>name</col>
<col>size</col>
<col>color</col>
</my:columns>
<xsl:variable name="columns" select="document('')/xsl:stylesheet/my:columns" />
<xsl:template match="/root">
<table border="1">
<tr>
<xsl:for-each select="$columns/col">
<th>
<xsl:value-of select="." />
</th>
</xsl:for-each>
</tr>
<xsl:for-each select="item">
<xsl:variable name="attributes" select="#*" />
<tr>
<xsl:for-each select="$columns/col">
<td>
<xsl:value-of select="$attributes[name()=current()]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Result (rendered)
Bryant, you need to work with two files (XML and XSL):
First, you need to specify a template (example.xsl):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>instance</th>
<th>swver</th>
<th>systemid</th>
<th>systime</th>
<th>sysmem</th>
<th>cutmem</th>
<th>filemem</th>
<th>calconfig</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="instance"/></td>
<td><xsl:value-of select="swver"/></td>
<td><xsl:value-of select="systemid"/></td>
<td><xsl:value-of select="systime"/></td>
<td><xsl:value-of select="sysmem"/></td>
<td><xsl:value-of select="cutmem"/></td>
<td><xsl:value-of select="filemem"/></td>
<td><xsl:value-of select="calconfig"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
And then you need to define your XML file (example.xml), based on the template (example.xsl):
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="example.xsl"?>
<catalog>
<cd>
<instance>instance1</instance>
<swver>swver1</swver>
<systemid>systemid1</systemid>
<sysmem>sysmem1</sysmem>
<systime>systime1</systime>
<cutmem>cutmem1</cutmem>
<filemem>filemem1</filemem>
<calconfig>calconfig1</calconfig>
</cd>
<cd>
<instance>instance2</instance>
<swver>swver2</swver>
<systemid>systemid2</systemid>
<sysmem>sysmem2</sysmem>
<systime>systime2</systime>
<cutmem>cutmem2</cutmem>
<filemem>filemem2</filemem>
<calconfig>calconfig2</calconfig>
</cd>
.
.
</catalog>
Result:
Reference:
http://www.w3schools.com/xsl/xsl_transformation.asp
Hope this helps!
I want to transform xml to html using xsl but I'm struggling to make it work although it should be pretty straightforward.
Input XML:
<EEExport Version="201510" Language="International" LanguageIsoCode="int-INT">
<Navigation>
<Navigation Name="Navigation" NavigationID="E905C889-63EF-431E-BD74-A470685F65E0">
<Navigation Name="Oven" NavigationID="B929861A-57D1-4C20-BE2C-0DC006F4D6CE">
</Navigation>
<Navigation Name="Cooker" NavigationID="643B0A58-D83B-4D8F-9E97-A5C8E572B1E5">
</Navigation>
<Navigation Name="Dishwasher" NavigationID="FAB9B544-109D-4B83-A6E4-25114E1D25BA">
<Product ProductID="887B5B3C-F9C7-4F4A-8E0B-1FC62830C508">
<MasterData>
<Brand>Brand1</Brand>
<ProductCode>911 424 310</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >F55600IM0P</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543317288</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >None</Attribute>
</Container>
</Containers>
</Product>
<Product ProductID="D4DB8281-42D7-4240-8731-220FD728481D">
<MasterData>
<Brand>Brand2</Brand>
<ProductCode>911 536 090</ProductCode>
<Category ID="B1679547-77B2">Dish_Washer</Category>
</MasterData>
<Containers>
<Container ContainerName="STechSpec_Dish_Washer">
<Attribute AttributeID="36214A61" Name="ModelD" >ZDT26020FA</Attribute>
<Attribute AttributeID="C3C36430" Name="BarCode" >7332543397303</Attribute>
<Attribute AttributeID="0B38C70E" Name="CutleryShelves" >Cutlery Drawer</Attribute>
</Container>
</Containers>
</Product>
</Navigation>
</Navigation>
</Navigation>
</EEExport>
I only want to show specific product fields of category 'Dishwasher'.
Desired output:
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<tr>
<td>Brand1</td>
<td>911 424 310</td>
<td>F55600IM0P</td>
<td>None</td>
</tr>
<tr>
<td>Brand2</td>
<td>911 536 090</td>
<td>ZDT26020FA</td>
<td>Cutlery Drawer</td>
</tr>
</table>
</body>
</html>
Current xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="/EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="/Masterdata/Brand"/></td>
<td><xsl:value-of select="/Masterdata/ProductCode"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="/Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Obviously I'm doing something wrong. Any help is greatly appreciated.
There are two problems with your XSLT.
Firstly, when you start an XPath expression with / then this represents the top-level document node, and so the search will be relative to that, and not to the node you are currently positioned on.
So instead of doing this:
<xsl:value-of select="/Masterdata/Brand"/>
Do this:
<xsl:value-of select="Masterdata/Brand"/>
Having said that, this leads on to the second issue. XML and XSLT are case sensitive. In your XML you use MasterData, but in your XSLT you refer to Masterdata. So, the expression should actually be like this:
<xsl:value-of select="MasterData/Brand"/>
Try this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="#e3e3e3">
<th>Brand</th>
<th>Product Code</th>
<th>Model D</th>
<th>Cutlery Shelves</th>
</tr>
<xsl:for-each select="EEExport/Navigation/Navigation/Navigation[#Name='Dishwasher']/Product">
<tr>
<td><xsl:value-of select="MasterData/Brand"/></td>
<td><xsl:value-of select="MasterData/ProductCode"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='ModelD']"/></td>
<td><xsl:value-of select="Containers/Container/Attribute[#Name='CutleryShelves']"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I have following xml document:
...
<x>
<symptom><descr></descr></symptom>
<cause></cause>
<solution></solution>
<cause></cause>
<solution></solution>
</x>
...
In my document I have several <x>
In each <x> I have only one <symptom> and n <cause> and <solution> whereby the amount of <cause> and <solution> is always the same.
I want to get following autmatically generated structure:
<table>
<tr>
<td rowspan=count(cause)><xsl:value-of select="symptom/descr"></td>
<td><xsl:value-of select="cause"></td>
<td><xsl:value-of select="symptom"></td>
<tr>
<tr>
<td><xsl:value-of select="cause"></td>
<td><xsl:value-of select="symptom"></td>
<tr>
...
</table>
I tried following code, which I know is totally wrong. But I'm stuck since several hours and couldn't find any good solution on the internet.
<xsl:for-each select="cause">
<tr>
<td rowspan="count(.)">
<xsl:value-of select="../descr[1]"/>
</td>
<td>
<xsl:value-of select="."/>
</td>
<xsl:for-each select="../solution">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
You're on the right lines with one tr per cause, how about this:
<xsl:template match="x">
<table>
<xsl:for-each select="cause">
<!-- the index of this cause within the list of causes in the current x -->
<xsl:variable name="pos" select="position()" />
<tr>
<!-- first cause - create the spanning symptom cell -->
<xsl:if test="$pos = 1">
<td rowspan="{last()}"><xsl:value-of select="../symptom/descr"/></td>
</xsl:if>
<!-- this cause -->
<td><xsl:value-of select="." /></td>
<!-- the matching solution -->
<td><xsl:value-of select="../solution[$pos]" /></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
A trick here is the last() function, which returns the total number of nodes that the current for-each (or apply-templates) is processing, which in this case is precisely the number of rows you want to span.
This is based on the assumption that you want as result a table with following structure: Given an example input XML
<x>
<symptom>
<descr>
Description
</descr>
</symptom>
<cause>
Cause 1
</cause>
<solution>
Solution 1
</solution>
<cause>
Cause 2
</cause>
<solution>
Solution 2
</solution>
</x>
I assume you want following table:
<table>
<tr>
<td rowspan="2">Description</td>
<td>Cause 1</td>
<td>Solution 1</td>
</tr>
<tr>
<td>Cause 2</td>
<td>Solution 2</td>
</tr>
</table>
This could be done with following XSLT:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="x">
<table>
<xsl:for-each select="cause">
<xsl:apply-templates select="." mode="row">
<xsl:with-param name="amount" select="count(../cause)"/>
<xsl:with-param name="position" select="position()"/>
</xsl:apply-templates>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="cause" mode="row">
<xsl:param name="amount"/>
<xsl:param name="position"/>
<tr>
<xsl:if test="$position = 1">
<td rowspan="{$amount}">
<xsl:value-of select="//symptom/descr"/>
</td>
</xsl:if>
<td>
<xsl:value-of select="."/>
</td>
<td>
<xsl:value-of select="following-sibling::solution"/>
</td>
</tr>
</xsl:template>
</xsl:transform>
For each cause a row is created by applying the template
<xsl:template match="cause" mode="row">
with the amount of rows and the the position of the current cause as parameters. If the position is 1, the description is written as value in a td with the amount of cause as value of rowspan.
Each row contains the value of the current cause:
<td>
<xsl:value-of select="."/>
</td>
and the value of the solution at the same position (the solution which is the following-sibling of the current cause):
<td>
<xsl:value-of select="following-sibling::solution"/>
</td>
Input:
<?xml version="1.0" encoding="utf-8" ?>
<Software>
<MS version="5.2.3.1"/>
<Java version="5.1.0.29" />
<Oracle id="A" version="1.0.1.11" />
<SQL id="P" version="1.0.1.11" />
</Software>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<xsl:for-each select="//*[1]">
<xsl:for-each select="#*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<tr>
<xsl:value-of select="local-name()"/> ::
<xsl:for-each select="#*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Output:
Current output [wrong]:
This script gives output without column name
"id". Some "version" column value added in "id(not visible)" column as
there is no attribute name id in node. eg. MS node has version
attribute only hence output result added version info in "id" column.
Please go through output once, possibly save and check in html for proper understanding.
<table>
<tr>
<td/>
<td>
<td>version</td>
</td>
</tr>
<tr>
<td>Software ::
</td>
</tr>
<tr>
<td>MS ::
<td>5.2.3.1</td></td>
</tr>
<tr>
<td>Java ::
<td>5.1.0.29</td></td>
</tr>
<tr>
<td>Oracle ::
<td>A</td><td>1.0.1.11</td></td>
</tr>
<tr>
<td>SQL ::
<td>P</td><td>1.0.1.11</td></td>
</tr>
</table>
Expected output:
Every attribute as columnname/header and all column
have their own value. NOTE: Attributes MS, JAVA, etc as column Name
should not be hard coded because the number of attributes may change on runtime.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td/>
<td>
id<td>version</td>
</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not exist</td><td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not exist</td><td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td><td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td><td>1.0.1.11</td>
</tr>
</table>
</body>
</html>
If you are looking to output one column for each possible attribute name, and not restrict it to just id and version, then (in XSLT 1.0) you could make use of a technique called Muenchian Grouping to get the distinct attribute names.
First define a key to look up the attributes by their name
<xsl:key name="columns" match="#*" use="local-name()" />
Then, to get the distinct ones (or rather, get the first occurrence of each distinct name), you can define a variable like so
<xsl:variable name="columns" select="//#*[generate-id() = generate-id(key('columns', local-name())[1])]" />
Then, to output the column headers, you can just iterate over this variable
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
For each row, you would take a similar approach. Assuming you were positioned on a child element, you could first define a variable that contains the attributes of the current element. Then you would iterate over the columns variable again, and output the value of the corresponding attribute for the current element
<xsl:variable name="attributes" select="#*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:key name="columns" match="#*" use="local-name()" />
<xsl:variable name="columns" select="//#*[generate-id() = generate-id(key('columns', local-name())[1])]" />
<xsl:template match="Software">
<table>
<tr>
<td>Software</td>
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="local-name()" /></td>
</xsl:for-each>
</tr>
<xsl:apply-templates select="*" />
</table>
</xsl:template>
<xsl:template match="Software/*">
<tr>
<td><xsl:value-of select="local-name()" /></td>
<xsl:variable name="attributes" select="#*" />
<xsl:for-each select="$columns">
<xsl:sort select="local-name()" />
<td><xsl:value-of select="$attributes[local-name() = local-name(current())]" /></td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
This should output the following
<table>
<tr>
<td>Software</td>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS</td>
<td/>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java</td>
<td/>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
Note, for brevity, I have not included code to output "Not exists" in the case where the attribute does not exist. But it should be simple enough to add a check for this. (Just store the value in a variable, and use an xsl:choose)
EDIT: If you want to restrict the attributes to specifically be for Software elements too, try changing the key to this:
<xsl:key name="columns" match="Software/*/#*" use="local-name()" />
Hummm, I have tried to fix the HTML issue and the problem you are facing.
This is a bit mannual, but can achieve your requirement. Here is the XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<table>
<tr>
<td></td>
<td>id</td>
<xsl:for-each select="//*[1]">
<xsl:for-each select="#*">
<td><xsl:value-of select="name()"/></td>
</xsl:for-each>
</xsl:for-each>
</tr>
<xsl:for-each select="//*">
<xsl:if test="position() > 1">
<tr>
<td><xsl:value-of select="local-name()"/> ::</td>
<td>
<xsl:choose>
<xsl:when test="#id"><xsl:value-of select="#id"/></xsl:when>
<xsl:otherwise>Not Exist</xsl:otherwise>
</xsl:choose>
</td>
<td>
<xsl:if test="#version"><xsl:value-of select="#version"/></xsl:if>
</td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Here is the output of it:
<table>
<tr>
<td/>
<td>id</td>
<td>version</td>
</tr>
<tr>
<td>MS ::</td>
<td>Not Exist</td>
<td>5.2.3.1</td>
</tr>
<tr>
<td>Java ::</td>
<td>Not Exist</td>
<td>5.1.0.29</td>
</tr>
<tr>
<td>Oracle ::</td>
<td>A</td>
<td>1.0.1.11</td>
</tr>
<tr>
<td>SQL ::</td>
<td>P</td>
<td>1.0.1.11</td>
</tr>
</table>
I have tested it on http://www.xslfiddle.net/
I'm new at XSLT language so i don't now how to do that..i want to sort all rows by category from table except the count products..i don't want to affect the order off count_products..please help..the code i have made so far
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title></title>
<link rel="stylesheet" href="css/xsl_style.css" type="text/css"/>
</head>
<body>
<div class="tableStyle" >
<table>
<tr bgcolor="#B5E4EA">
<td>A/A</td>
<td>Product Name</td>
<td>Price</td>
<td>Corpration</td>
<td>Category</td>
</tr>
<xsl:for-each select="auction_products/product">
<xsl:sort select="category"/>
<tr>
<td><xsl:value-of select="count_products"/></td>
<td><xsl:value-of select="product_name"/></td>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="corporation"/></td>
<td><xsl:value-of select="category"/></td>
</tr>
</xsl:for-each>
</table>
</div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
If you want the rows to be sorted but the count_products column to come out in document order then you'd need a trick like this:
<xsl:variable name="allProducts" select="auction_products/product" />
<xsl:for-each select="$allProducts">
<xsl:sort select="category"/>
<xsl:variable name="pos" select="position()" />
<tr>
<td><xsl:value-of select="$allProducts[$pos]/count_products"/></td>
<td><xsl:value-of select="product_name"/></td>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="corporation"/></td>
<td><xsl:value-of select="category"/></td>
</tr>
</xsl:for-each>
to take the count_products child from the nth product regardless of the sorting applied to the for-each.
Of course, if count_products is really just a counter (1, 2, 3, ...) then you could just use <xsl:value-of select="$pos" /> directly.