xslt sorting not working - xslt

basically i want to sort data by level and i'm getting an error. I'm a newbie to xslt. i tried the below code but not working.
here is my xml file.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="XSLTEx1WT.xsl"?>
<Modules>
<module code="CSE2041">
<name>Web Technologies II</name>
<credit>3</credit>
<level>2</level>
</module>
<module code="CSE2031Y">
<name>Object Oriented Software Development</name>
<credit>6</credit>
<level>2</level>
</module>
<module code="CSE1041">
<name>Web Technologies I</name>
<credit>3</credit>
<level>1</level>
</module>
</Modules>
here is my xsl file
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:variable name="deptCredit" select="99"/>
<xsl:variable name="myBorder" select="1"/>
<xsl:template match="/">
<html>
<head>
<title>XSLT Exercise 1</title></head>
<body>
<table border="{$myBorder}">
<thead><tr><th>Module Name</th><th>No. of Credits</th><th>Level</th></tr></thead>
<tbody>
<xsl:apply-templates>
**<xsl:sort select="level" data-type="number"/>**
</xsl:apply-templates>
<tr><td colspan="3">Departmental credits needed: <xsl:value-of select="$deptCredit"/></td></tr>
<tr><td colspan="3">Percentage cleared: <strong> <xsl:value-of select="format-number(sum(//credit/text()) div $deptCredit,'##.##%')"/></strong>
</td></tr>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="module">
<xsl:apply-templates select="#code"/>
<tr><xsl:apply-templates select="*"/></tr>
</xsl:template>
<xsl:template match="name">
<xsl:call-template name="sjName"/>
</xsl:template>
<xsl:template match="#code">
<tr style="background-color:silver;">
<td colspan="3" style="text-align:center;">
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
<xsl:template match="credit">
<td style="color:blue;"><strong><xsl:value-of select="text()"/></strong></td>
</xsl:template>
<xsl:template match="level">
<td style="color:blue;"><strong><xsl:value-of select="text()"/></strong></td>
</xsl:template>
<xsl:template name="sjName">
<xsl:choose>
<xsl:when test="contains(../#code,'Y')">
<td style="color:orange;font-weight:bold;"><xsl:value-of select="."/></td>
</xsl:when>
<xsl:otherwise>
<td style="color:lime;font-weight:bold;"><xsl:value-of select="."/></td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
i have tried the above but its not working

You simply need to change this:
<xsl:apply-templates>
<xsl:sort select="level" data-type="number"/>
</xsl:apply-templates>
to this:
<xsl:apply-templates select="Modules/module">
<xsl:sort select="level" data-type="number"/>
</xsl:apply-templates>

Related

Transforming XML into HTML with couple representations

My XML contains description of some resource. I want to build HTML with JSON, XML, etc. representation of this resource.
Here is XML:
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<resource name="item">
<parameters>
<parameter name="id">
<example-value>1234</example-value>
<type>integer</type>
</parameter>
<parameter name="name">
<example-value>parameter</example-value>
<type>string</type>
</parameter>
<parameter name="timestamp">
<example-value>1466589751</example-value>
<type>integer</type>
</parameter>
<parameter name="status">
<example-value>1</example-value>
<type>integer</type>
</parameter>
</parameters>
</resource>
</resources>
And here is how I do it:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<html>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="resources">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="resource">
<div>
<h2>
<xsl:value-of select="#name"/>
</h2>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="parameters">
<h3>
<xsl:text>Examples</xsl:text>
</h3>
<div>
<xsl:call-template name="CSVExample"/>
<xsl:call-template name="TableExample"/>
<xsl:call-template name="JSONExample"/>
<xsl:call-template name="XMLExample"/>
</div>
</xsl:template>
<xsl:template name="CSVExample">
<div>
<pre>
<xsl:for-each select="parameter">
<xsl:value-of select="concat('"',#name,'"')"/>
<xsl:if test="position() < last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:for-each select="parameter">
<xsl:value-of select="concat('"',example-value,'"')"/>
<xsl:if test="position() < last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</pre>
</div>
</xsl:template>
<xsl:template name="TableExample">
<div>
<pre>
<table>
<tr>
<xsl:for-each select="parameter">
<th>
<xsl:value-of select="#name"/>
</th>
</xsl:for-each>
</tr>
<tr>
<xsl:for-each select="parameter">
<td>
<xsl:value-of select="example-value"/>
</td>
</xsl:for-each>
</tr>
</table>
</pre>
</div>
</xsl:template>
<xsl:template name="JSONExample">
<div>
<pre>
<xsl:text>{</xsl:text>
<xsl:for-each select="parameter">
<xsl:value-of select="concat('"',#name,'":')"/>
<xsl:if test="type = 'string'">
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:value-of select="example-value"/>
<xsl:if test="type = 'string'">
<xsl:text>"</xsl:text>
</xsl:if>
<xsl:if test="position() < last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text>}</xsl:text>
</pre>
</div>
</xsl:template>
<xsl:template name="XMLExample">
<div>
<pre>
<parameters>
<xsl:for-each select="parameter">
<xsl:element name="{#name}">
<xsl:value-of select="example-value"/>
</xsl:element>
</xsl:for-each>
</parameters>
</pre>
</div>
</xsl:template>
</xsl:stylesheet>
Do You think this is right way to do such a case? I mean templates structure, calls, applys, etc.
Should I mayby replace for-each with some apply-templates? I read somewhere that is better to avoid for-each in favour of apply-templates. But is that true in this case?
I'm sure we could discuss many alternative ways to rework your xsl but to be honest this is not the correct forum for such things -- You really ought to be using that code review forum on Stack Exchange.
That said, I think your xsl structure is generally good - better than most we see on this site!
However, as it stands if <parameters> exits without any child <<parameter> nodes the call-templates wil still generate unwanted(?) content.
You would be better to use apply-templates with a mode attribute.
<xsl:template match="properties" mode="CSVExample">
....
</xsl:template>
and replace the call-templates with
<xsl:apply-templates select="." mode="CSVExample"/>
As for deciding betwee the for-each or apply-templates : When using a select="", I dont think it generally matters which way you go. Personally, I opt for apply-templates every time, it's more flexible and only use for-each whenever the code looks neater or is easier to understand that way.

How to build a string with XSLT?

I have this XML snippet
<MediaTypes>
<DVD>true</DVD>
<HDDVD>false</HDDVD>
<BluRay>true</BluRay>
</MediaTypes>
And I want to create an output that looks like this
DVD / Blu-ray
or like this
DVD
or like this
DVD / HD-DVD / Blu-ray
depending on the true/false states
But I'm a total beginner in the XSLT game. :-/
Here's a snippet of the full XML
<?xml version="1.0" encoding="Windows-1252"?>
<Collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DVD>
<ProfileTimestamp>2012-06-07T05:20:51Z</ProfileTimestamp>
<ID>0044005507027.5</ID>
<MediaTypes>
<DVD>true</DVD>
<HDDVD>false</HDDVD>
<BluRay>false</BluRay>
</MediaTypes>
<UPC>0-044005-507027</UPC>
<CollectionNumber>448</CollectionNumber>
<CollectionType IsPartOfOwnedCollection="true">Owned</CollectionType>
<Title>The Big Lebowski</Title>
<DistTrait />
<OriginalTitle />
<CountryOfOrigin>United States</CountryOfOrigin>
...
</DVD>
<DVD>
...
</DVD>
</Collection>
I tried to follow the advices given below (regarding the loop), but it doesn't seem to work.
This is the XSL I have so far (complete):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="MediaTypes" match="MediaTypes">
Test
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>DVD Profiler Double Dips</title>
</head>
<body>
<div>
<h1>DVD Profiler Double Dips</h1>
</div>
<table border="1" cellpadding="3" cellspacing="0">
<tr>
<th>Title</th>
<th>Edition</th>
<th>Production Year</th>
<th>DVD /</th>
<th>Purchase Date</th>
<th>Collection Type</th>
<th>Original Title</th>
<th>Sort Title</th>
</tr>
<xsl:for-each select="/Collection/DVD">
<tr>
<td>
<xsl:value-of select="Title"/>
</td>
<td>
<xsl:if test="DistTrait != ''">
<xsl:value-of select="DistTrait"/>
</xsl:if>
<xsl:if test="DistTrait = ''">
 
</xsl:if>
</td>
<td>
<xsl:if test="ProductionYear != ''">
<xsl:value-of select="ProductionYear"/>
</xsl:if>
<xsl:if test="ProductionYear = ''">
 
</xsl:if>
</td>
<td>
<xsl:call-template name="MediaTypes" />
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But where
<xsl:call-template name="MediaTypes" />
is standing, only "Test" comes out
Yay!
You guys are awesome. Yes
<xsl:apply-templates select="MediaTypes"/>
Was my weapon of choice.
My final template looks like this:
<xsl:template name="MediaTypes" match="MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text> / </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="CustomMediaType != ''">
<xsl:if test="*[.='true']">
<xsl:text> / </xsl:text>
</xsl:if>
<xsl:value-of select="CustomMediaType"/>
</xsl:if>
</xsl:template>
begins to understand how stuff works
Thanks for all your help!
The question is rather trivial - the real problem is that you only show a snippet of the XML document. XSLT is very much context-dependent.
Here is a template to match any <MediaTypes> element and output the required string; hopefully you'll know how to incorporate it into your own stylesheet:
<xsl:template match="MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
I'd advice you to change the xml a bit
Here is an example
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" ?>
<MediaTypes>
<Media name="DVD">true</Media>
<Media name="HDDVD">false</Media>
<Media name="BluRay">true</Media>
</MediaTypes>
This way you may write XPATH expressions like //MediaTypes/Media
However did #michael.hor257k write a nice solution, jacking this xml pattern into that would look like this
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="//MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="#name"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This will render DVD/BluRay
Test here http://xslttest.appspot.com/

XSLT - format comma seperated list into table format

A web service is returning a list of persons in the below xml format. The values are seperated by a semicolon. I need to display the values in 2 or 3 columns (Needs to be a variable).
Desired Results:
<table border="1">
<tr>
<td>Smith, John</td>
<td>Jackson, Samuel</td>
<td>Wayne, Bruce</td>
</tr>
<tr>
<td>Cosby, Bill</td>
<td>Kent, Clarke</td>
<td>Leno, Jay</td>
</tr>
<tr>
<td>OBrian, Conan</td>
<td> </td>
<td> </td>
</tr>
</table>
Xml sample
<?xml version="1.0" encoding="UTF-8"?> <PI>Smith, John; Jackson,
Samuel; Wayne, Bruce; Cosby, Bill; Kent, Clarke; Leno, Jay; OBrian,
Conan; </PI>
Please accept Holman's solution. His technique is spot-on.
XSLT 2.0 Solution
Your sample input data suggests semicolon terminated list, rather than a semicolon separated list.
This XSLT 2.0 stylesheet will work correctly with either a semicolon terminated list or a semicolon separated list. It takes one input parameter col-count, which defaults to 3.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:param name="col-count" select="3" />
<xsl:template match="/*">
<table border="1">
<xsl:variable name="names" select="tokenize(.,';')[normalize-space(.)]" />
<xsl:for-each-group select="$names , for $x in 1 to
($col-count - (count($names) mod $col-count)) mod $col-count return ''"
group-by="(position() - 1) idiv $col-count">
<tr>
<xsl:for-each select="current-group()">
<td><xsl:value-of select="normalize-space(.)" /></td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>
Notes:
(1) Notice the brevity of the solution, and the absence of clumsy xsl:if statements. The use of calculated sequences (as opposed to input document node selections), is not just limited to the group-by attribute, but can also to applied to select. The use of computed sequences suggests a more functional view, rather than a procedural view.
(2) If you want the output to be safe for old browsers, then replace ...
<xsl:for-each-group select="$names , for $x in 1 to
($col-count - (count($names) mod $col-count)) mod $col-count return ''"
group-by="(position() - 1) idiv $col-count">
... with ...
<xsl:for-each-group select="$names , for $x in 1 to
($col-count - (count($names) mod $col-count)) mod $col-count return ' '"
group-by="(position() - 1) idiv $col-count">
XSLT 1.0 Solution
If you are stuck on XSLT 1.0, then you could use this equivalent, but less efficient stylesheet ...
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:esl="http://exslt.org/common"
xmlns:so="http://stackoverflow.com/questions/18066463"
version="1.0"
exclude-result-prefixes="xsl so esl">
<xsl:output method="html" doctype-system="about:legacy-compat" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:variable name="col-count" select="3" /><!-- Must be 2 or 3. -->
<xsl:variable name="empty-rtf">
<so:name> </so:name>
</xsl:variable>
<xsl:variable name="empty" select="esl:node-set($empty-rtf)/*" />
<xsl:template match="/*">
<table border="1">
<xsl:variable name="names-rtf">
<xsl:call-template name="split">
<xsl:with-param name="list" select="." />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="names" select="esl:node-set($names-rtf)/*" />
<xsl:for-each select="$names[(position() mod $col-count) = 1]">
<xsl:variable name="row" select="position() - 1" />
<tr>
<xsl:apply-templates select="$names[floor((position() - 1) div $col-count) = $row]" />
<xsl:if test="position()=last()">
<xsl:for-each select="($names|$empty)[position() <=
(($col-count - (count($names) mod $col-count)) mod $col-count)]">
<xsl:apply-templates select="$empty" />
</xsl:for-each>
</xsl:if>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="split">
<xsl:param name="list" />
<xsl:choose>
<xsl:when test="contains($list,';')">
<xsl:call-template name="split">
<xsl:with-param name="list" select="substring-before($list,';')" />
</xsl:call-template>
<xsl:call-template name="split">
<xsl:with-param name="list" select="substring-after($list,';')" />
</xsl:call-template>
</xsl:when>
<xsl:when test="normalize-space($list)">
<so:name><xsl:value-of select="normalize-space($list)" /></so:name>
</xsl:when>
<xsl:otherwise />
</xsl:choose>
</xsl:template>
<xsl:template match="so:*" priority="2">
<td><xsl:value-of select="." /></td>
</xsl:template>
</xsl:stylesheet>
Here is an XSLT 2.0 solution with the number of columns as a variable as requested. This employs a technique I teach in the classroom that underscores that grouping need not be by values in the XML (as many XSLT users assume), rather, it can be by any arbitrary calculation (in this case, the result of division).
[edited to show multiple invocations with different number of columns]
t:\ftemp>type names.xml
<?xml version="1.0" encoding="UTF-8"?> <PI>Smith, John; Jackson,
Samuel; Wayne, Bruce; Cosby, Bill; Kent, Clarke; Leno, Jay; OBrian,
Conan; </PI>
t:\ftemp>call xslt2 names.xml names.xsl names.out.xml "cols=3"
t:\ftemp>type names.out.xml
<?xml version="1.0" encoding="UTF-8"?>
<table border="1">
<tr>
<td>Smith, John</td>
<td>Jackson, Samuel</td>
<td>Wayne, Bruce</td>
</tr>
<tr>
<td>Cosby, Bill</td>
<td>Kent, Clarke</td>
<td>Leno, Jay</td>
</tr>
<tr>
<td>OBrian, Conan</td>
<td/>
<td/>
</tr>
</table>
t:\ftemp>call xslt2 names.xml names.xsl names.out.xml "cols=2"
t:\ftemp>type names.out.xml
<?xml version="1.0" encoding="UTF-8"?>
<table border="1">
<tr>
<td>Smith, John</td>
<td>Jackson, Samuel</td>
</tr>
<tr>
<td>Wayne, Bruce</td>
<td>Cosby, Bill</td>
</tr>
<tr>
<td>Kent, Clarke</td>
<td>Leno, Jay</td>
</tr>
<tr>
<td>OBrian, Conan</td>
<td/>
</tr>
</table>
t:\ftemp>type names.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:param name="cols" required="yes"/>
<xsl:template match="PI">
<table border="1">
<!--determine population and group by number of columns-->
<xsl:for-each-group select="tokenize(.,';\s+')"
group-by="(position()-1) idiv $cols">
<tr>
<!--put members into the row-->
<xsl:for-each select="current-group()">
<td>
<xsl:value-of select="normalize-space(.)"/>
</td>
</xsl:for-each>
<!--filler for the last row-->
<xsl:if test="position()=last()">
<xsl:for-each select="count(current-group())+1 to $cols">
<td/>
</xsl:for-each>
</xsl:if>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:stylesheet>
t:\ftemp>rem

sorting decimals with XSLT

I am trying to sort some XML data, i have followed W3s tutorials, but my code doesn't work, whats wrong?
<xsl:for-each select="garage/car[colour='red']">
<xsl:apply-templates>
<xsl:sort select="number(price)" order="descending" data-type="number" />
</xsl:apply-templates>
<tr>
<td><xsl:value-of select="make"/></td>
<td><xsl:value-of select="model"/></td>
<td><xsl:value-of select="price"/></td>
</tr>
</xsl:for-each>
XML example~:
<garage>
<car>
<make>vw</make>
<model>golf</model>
<color>red</color>
<price>5.99</price>
</car>
<car>
<make>ford</make>
<model>focus</model>
<color>black</color>
<price>3.66</price>
</car>
<car>
<make>honda</make>
<model>civic</model>
<color>red</color>
<price>15.99</price>
</car>
</garage>
So you want to show all the red cars in descending price order?
It helps if you are consistent with your spelling of color/colour! I am British and feel your pain!
Also you are mixing up the for-each and apply-templates (both work)
apply-templates method:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" indent="yes" />
<xsl:template match="/">
<xsl:apply-templates select="garage/car[color='red']">
<xsl:sort select="number(price)" order="descending" data-type="number" />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="car[color='red']">
<tr>
<td>
<xsl:value-of select="make" />
</td>
<td>
<xsl:value-of select="model" />
</td>
<td>
<xsl:value-of select="price" />
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
for-each method:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" indent="yes" />
<xsl:template match="/">
<xsl:for-each select="garage/car[color='red']">
<xsl:sort select="number(price)" order="descending" data-type="number" />
<tr>
<td>
<xsl:value-of select="make" />
</td>
<td>
<xsl:value-of select="model" />
</td>
<td>
<xsl:value-of select="price" />
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

xsl : getting specific node values from a table

My XML Code
<DBE:Attribute name="Test1" type="Table">
<DBE:Table>
<DBE:TableHeader>
<DBE:TableColumn>t1</DBE:TableColumn>
<DBE:TableColumn>t2</DBE:TableColumn>
<DBE:TableColumn>t3</DBE:TableColumn>
<DBE:TableColumn>t4</DBE:TableColumn>
<DBE:TableColumn>t5</DBE:TableColumn>
<DBE:TableColumn>t6</DBE:TableColumn>
<DBE:TableColumn>t7</DBE:TableColumn>
<DBE:TableColumn>t8</DBE:TableColumn>
<DBE:TableColumn>t9</DBE:TableColumn>
<DBE:TableColumn>t10</DBE:TableColumn>
<DBE:TableColumn>t11</DBE:TableColumn>
<DBE:TableColumn>t12</DBE:TableColumn>
<DBE:TableColumn>t13</DBE:TableColumn>
</DBE:TableHeader>
<DBE:TableRow>
<DBE:TableData>0300 </DBE:TableData>
<DBE:TableData/>
<DBE:TableData>25</DBE:TableData>
<DBE:TableData>25</DBE:TableData>
<DBE:TableData>2009/09/03</DBE:TableData>
<DBE:TableData/>
<DBE:TableData>BAG</DBE:TableData>
<DBE:TableData>rrr</DBE:TableData>
<DBE:TableData>Yes</DBE:TableData>
<DBE:TableData>12</DBE:TableData>
<DBE:TableData>2009/03/09</DBE:TableData>
<DBE:TableData>GO</DBE:TableData>
<DBE:TableData/>
</DBE:TableRow>
</DBE:Table>
</DBE:Attribute>
I would like my output to be ->
t7 t5 t1 t13 --> Header
---------------------------------------------------------------
BAG 2009/09/03 0300 GO --> ROW1
.............................................................. --> ROW2
and so on
My XSL code --> (for only selected values to be displayed)
<xsl:for-each select="DBE:Attribute[#name='Test1']/DBE:Table/DBE:TableRow">
<tr bgcolor="white">
<xsl:for-each select="DBE:TableData">
<td>
<xsl:value-of select="node()|*">
</xsl:value-of>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
You could create a selector variable that holds the numeric position of columns you want. See the variable named "selector" below. Once you have that, a simple if in your TableData and TableColumn templates does the rest.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:DBE="foo.bar">
<xsl:variable name="selector">;1;5;7;12;</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DBE:Attribute">
<html>
<body><xsl:apply-templates/></body>
</html>
</xsl:template>
<xsl:template match="DBE:Table">
<table border="1">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="DBE:TableHeader">
<tr>
<xsl:apply-templates select="DBE:TableColumn"/>
</tr>
</xsl:template>
<xsl:template match="DBE:TableColumn">
<xsl:variable name="pos">
<xsl:text>;</xsl:text><xsl:value-of select="string(position())"/><xsl:text>;</xsl:text>
</xsl:variable>
<xsl:if test="contains($selector, $pos)">
<th>
<xsl:value-of select="."/>
</th>
</xsl:if>
</xsl:template>
<xsl:template match="DBE:TableRow">
<tr>
<xsl:apply-templates select="DBE:TableData"/>
</tr>
</xsl:template>
<xsl:template match="DBE:TableData">
<xsl:variable name="pos">
<xsl:text>;</xsl:text><xsl:value-of select="string(position())"/><xsl:text>;</xsl:text>
</xsl:variable>
<xsl:if test="contains($selector, $pos)">
<td>
<xsl:value-of select="."/>
</td>
</xsl:if>
</xsl:template>
</xsl:stylesheet>