Please suggest for XSLT code for Table rowspan and colspan issues - xslt

<article>
<table id="tbl1">
<caption><p>Table 1. Sample Table</p></caption>
<thead>
<tr>
<td colspan="3">I</td>
<td colspan="4">II</td>
</tr>
<tr>
<td>Sl. No.</td>
<td>Name</td>
<td>Place</td>
<td>Subject 1</td>
<td>Subject 2</td>
<td>Subject 3</td>
<td>Grade</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">1</td>
<td colspan="2">Kishan</td>
<td>95</td>
<td>96</td>
<td rowspan="2">97</td>
<td>A</td>
</tr>
<tr>
<td>Kishan</td>
<td>Bangalore</td>
<td>94</td>
<td>96</td>
<td>A</td>
</tr>
<tr>
<td>Likhith</td>
<td>Bhadravathi</td>
<td>94</td>
<td>94</td>
<td>99</td>
<td>A</td>
</tr>
</tbody>
</table>
</article>
Required OutPut: If colspan is 2 is coded in second cell, then third should not be there, next cell name should be "colname="3" (start Index is 0). Same for rowspan, if present row's first cell having rowspan="3", then next two rows should not have colname="0", those next two rows start cells will have the name="1" (start index is 0, thats why 1 means second cell). Please suggest for the XSLT coding two address both rowspan and colspan present in same table.
<article>
<table id="tbl1">
<caption><p>Table 1. Sample Table</p></caption>
<thead>
<tr>
<td colname="0:0">I</td>
<td colname="0:3">II</td>
</tr>
<tr>
<td colname="1:0">Sl. No.</td>
<td colname="1:1">Name</td>
<td colname="1:2">Place</td>
<td colname="1:3">Subject 1</td>
<td colname="1:4">Subject 2</td>
<td colname="1:5">Subject 3</td>
<td colname="1:6">Grade</td>
</tr>
</thead>
<tbody>
<tr>
<td colname="2:0">1</td>
<td colname="2:1">Kishan</td>
<td colname="2:3">95</td>
<td colname="2:4">96</td>
<td colname="2:5">97</td>
<td colname="2:6">A</td>
</tr>
<tr>
<td colname="3:1">Kishan</td>
<td colname="3:2">Bangalore</td>
<td colname="3:3">94</td>
<td colname="3:4">96</td>
<td colname="3:6">A</td>
</tr>
<tr>
<td colname="4:1">Likhith</td>
<td colname="4:2">Bhadravathi</td>
<td colname="4:3">94</td>
<td colname="4:4">94</td>
<td colname="4:5">99</td>
<td colname="4:6">A</td>
</tr>
</tbody>
</table>
</article>
XSLT code from StackOverFlow site:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--rowspan in table with xslt-->
<xsl:template match="TABLE2">
<tbody>
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="ROW"/>
</xsl:call-template>
</tbody>
</xsl:template>
<xsl:template name="processRows">
<xsl:param name="rows"/>
<xsl:param name="index" select="1"/>
<!-- Bit vector for the columns -->
<xsl:param name="col1" select="0"/>
<xsl:param name="col2" select="0"/>
<xsl:param name="col3" select="0"/>
<xsl:param name="col4" select="0"/>
<xsl:param name="col5" select="0"/>
<xsl:param name="col6" select="0"/>
<xsl:variable name="cellsBefore2">
<xsl:choose>
<xsl:when test="$col1 > 0">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore3">
<xsl:choose>
<xsl:when test="$col2 > 0">
<xsl:value-of select="$cellsBefore2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore2 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore4">
<xsl:choose>
<xsl:when test="$col3 > 0">
<xsl:value-of select="$cellsBefore3"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore3 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore5">
<xsl:choose>
<xsl:when test="$col4 > 0">
<xsl:value-of select="$cellsBefore4"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore4 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore6">
<xsl:choose>
<xsl:when test="$col5 > 0">
<xsl:value-of select="$cellsBefore5"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore5 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<row>
<xsl:if test="$col1 = 0">
<entry colname="1">
<xsl:value-of select="$rows[$index]/CELL[1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col2 = 0">
<entry colname="2">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore2 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col3 = 0">
<entry colname="3">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore3 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col4 = 0">
<entry colname="4">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore4 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col5 = 0">
<entry colname="5">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore5 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col6 = 0">
<entry colname="6">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore6 + 1]/text()"/>
</entry>
</xsl:if>
</row>
<xsl:if test="$index < count($rows)">
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="$rows"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="col1">
<xsl:choose>
<xsl:when test="$col1 > 0">
<xsl:value-of select="$col1 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col2">
<xsl:choose>
<xsl:when test="$col2 > 0">
<xsl:value-of select="$col2 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore2 + 1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col3">
<xsl:choose>
<xsl:when test="$col3 > 0">
<xsl:value-of select="$col3 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore3 + 1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col4">
<xsl:choose>
<xsl:when test="$col4 > 0">
<xsl:value-of select="$col4 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore4 + 1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col5">
<xsl:choose>
<xsl:when test="$col5 > 0">
<xsl:value-of select="$col5 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore5 + 1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col6">
<xsl:choose>
<xsl:when test="$col6 > 0">
<xsl:value-of select="$col6 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore6 + 1]/#ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

This is not at all simple. Basically, you are asking how to render an HTML table visually, by positioning each cell on a (equi-spaced) x-y grid of rows and columns.
This is complex, because the position of each cell depends not only on the width (colspan) of the preceding cells in the same row, but also on the position of cells in preceding rows that span more than one row. This position is not known before the preceding cells themselves have been processed - so this is a giant render-as-you-go cascading operation.
Due to this complexity, I suggest solving the basic problem in isolation first, before introducing additional constraints (e.g. separate header rows or numbers starting from 0).
For testing, I have used the following table1 as the input:
<table border="1">
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
</tr>
<tr>
<td rowspan="2">A</td>
<td colspan="2">B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>E</td>
<td rowspan="2" colspan="2">F</td>
</tr>
<tr>
<td>G</td>
</tr>
<tr>
<td colspan="3">H</td>
</tr>
</table>
Applying the folowing stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/table">
<table>
<xsl:text>
</xsl:text>
<xsl:call-template name="generate-rows">
<xsl:with-param name="current-row" select="1"/>
<xsl:with-param name="last-row" select="count(tr)"/>
</xsl:call-template>
</table>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="current-row"/>
<xsl:param name="last-row"/>
<xsl:param name="result" select="some-dummy-node-to-make-this-a-node"/>
<!-- append current-row to previous result -->
<xsl:variable name="new-result">
<xsl:copy-of select="$result"/>
<row num="{$current-row}">
<xsl:text>
</xsl:text>
<!-- generate cells for current-row -->
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="1"/>
<xsl:with-param name="x" select="1"/>
<xsl:with-param name="last-cell" select="count(tr[$current-row]/td)"/>
<xsl:with-param name="previous-rows" select="$result"/>
</xsl:call-template>
</row>
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:choose>
<xsl:when test="$current-row < $last-row">
<!-- recursive call -->
<xsl:call-template name="generate-rows">
<xsl:with-param name="current-row" select="$current-row + 1"/>
<xsl:with-param name="last-row" select="$last-row"/>
<xsl:with-param name="result" select="$new-result"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- return result -->
<xsl:copy-of select="$new-result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="generate-cells">
<xsl:param name="current-row"/>
<xsl:param name="current-cell"/>
<xsl:param name="x"/>
<xsl:param name="last-cell"/>
<xsl:param name="previous-rows"/>
<xsl:variable name="my-cell" select="tr[$current-row]/td[$current-cell]" />
<xsl:choose>
<!-- if there's a collision, move one place to the right -->
<xsl:when test="exsl:node-set($previous-rows)/row/cell[#x <= $x and #x + #width > $x and #y + #height > $current-row]">
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="$current-cell"/>
<xsl:with-param name="x" select="$x + 1"/>
<xsl:with-param name="last-cell" select="$last-cell"/>
<xsl:with-param name="previous-rows" select="$previous-rows"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$my-cell/#colspan">
<xsl:value-of select="$my-cell/#colspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="height">
<xsl:choose>
<xsl:when test="$my-cell/#rowspan">
<xsl:value-of select="$my-cell/#rowspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:text> </xsl:text>
<cell num="{$current-cell}" y="{$current-row}" x="{$x}" width="{$width}" height="{$height}">
<xsl:value-of select="$my-cell"/>
</cell>
<xsl:text>
</xsl:text>
<xsl:if test="$current-cell < $last-cell">
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="$current-cell + 1"/>
<xsl:with-param name="x" select="$x + $width"/>
<xsl:with-param name="last-cell" select="count(tr[$current-row]/td)"/>
<xsl:with-param name="previous-rows" select="$previous-rows"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
produces the following result:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<row num="1">
<cell num="1" y="1" x="1" width="1" height="1">Column 1</cell>
<cell num="2" y="1" x="2" width="1" height="1">Column 2</cell>
<cell num="3" y="1" x="3" width="1" height="1">Column 3</cell>
</row>
<row num="2">
<cell num="1" y="2" x="1" width="1" height="2">A</cell>
<cell num="2" y="2" x="2" width="2" height="1">B</cell>
</row>
<row num="3">
<cell num="1" y="3" x="2" width="1" height="1">C</cell>
<cell num="2" y="3" x="3" width="1" height="1">D</cell>
</row>
<row num="4">
<cell num="1" y="4" x="1" width="1" height="1">E</cell>
<cell num="2" y="4" x="2" width="2" height="2">F</cell>
</row>
<row num="5">
<cell num="1" y="5" x="1" width="1" height="1">G</cell>
</row>
<row num="6">
<cell num="1" y="6" x="1" width="3" height="1">H</cell>
</row>
</table>
As you can see, the x-y positioning of each cell corresponds to the visual rendering of the original table in a browser:
--
1. From http://en.wikipedia.org/wiki/Help:Table
For XSLT 2.0:
Change the stylesheet declaration to:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
Change line #66 to:
<xsl:when test="$previous-rows/row/cell[#x <= $x and #x + #width > $x and #y + #height > $current-row]">

Related

Recursive Template Generating Extra Stuff

I am working with Xml that that has multiple levels where I am attempting to display as nested html tables. The Xml may contain one or more levels of information. The current state is the information from the Xml is shown, but has extra empty tables.
Below is the Xml and template I am using. How should I correct the problem?
<?xml version="1.0" encoding="UTF-8"?>
<ErrorRecord>
<Exception>
<ErrorRecord>Exception calling "Fill" with "2" argument(s): "Divide by zero error encountered."</ErrorRecord>
<WasThrownFromThrowStatement>True</WasThrownFromThrowStatement>
<TargetSite>Void CheckActionPreference(System.Management.Automation.Language.FunctionContext, System.Exception)</TargetSite>
<Message>Exception calling "Fill" with "2" argument(s): "Divide by zero error encountered."</Message>
<Data>System.Collections.ListDictionaryInternal</Data>
<InnerException>
<Error>
<Source>Core .Net SqlClient Data Provider</Source>
<Number>8134</Number>
<State>1</State>
<Class>16</Class>
<Server>.</Server>
<Message>Divide by zero error encountered.</Message>
<Procedure></Procedure>
<LineNumber>1</LineNumber>
</Error>
<ClientConnectionId>cdfed373-14fb-4dd7-bebf-7158695cb2c7</ClientConnectionId>
<Class>16</Class>
<LineNumber>1</LineNumber>
<Number>8134</Number>
<Procedure></Procedure>
<Server>.</Server>
<State>1</State>
<Source>Core .Net SqlClient Data Provider</Source>
<IsTransient>False</IsTransient>
<SqlState></SqlState>
<BatchCommand></BatchCommand>
<ErrorCode>-2146232060</ErrorCode>
<TargetSite>Void OnError(System.Data.SqlClient.SqlException, Boolean, System.Action`1[System.Action])</TargetSite>
<Message>Divide by zero error encountered.</Message>
<Data>System.Collections.ListDictionaryInternal</Data>
<InnerException></InnerException>
<HelpLink></HelpLink>
<HResult>-2146232060</HResult>
<StackTrace> at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
at System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
at System.Data.SqlClient.SqlDataReader.Read()
at System.Data.Common.DataAdapter.FillLoadDataRow(SchemaMapping mapping)
at System.Data.Common.DataAdapter.FillFromReader(DataSet dataset, DataTable datatable, String srcTable, DataReaderContainer dataReader, Int32 startRecord, Int32 maxRecords, DataColumn parentChapterColumn, Object parentChapterValue)
at System.Data.Common.DataAdapter.Fill(DataSet dataSet, String srcTable, IDataReader dataReader, Int32 startRecord, Int32 maxRecords)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, String srcTable)
at CallSite.Target(Closure, CallSite, Object, Object, Object)</StackTrace>
</InnerException>
<HelpLink></HelpLink>
<Source>System.Management.Automation</Source>
<HResult>-2146233087</HResult>
<StackTrace> at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)</StackTrace>
</Exception>
</ErrorRecord>
<xsl:template match = "ErrorRecord">
<xsl:call-template name="ErrorTable">
<xsl:with-param name="n" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template name="ErrorTable">
<xsl:param name="n" />
<xsl:for-each select="$n/*">
<table class="ErrorDetailTable">
<tr>
<th class="Property"> </th>
<th class="Value"> </th>
</tr>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">
<tr class="tr-even">
<xsl:call-template name="ErrorCells"/>
</tr>
</xsl:when>
<xsl:otherwise>
<tr class="tr-odd">
<xsl:call-template name="ErrorCells"/>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<tr><td colspan="2"> </td></tr>
</table>
</xsl:for-each>
</xsl:template>
<xsl:template name="ErrorCells">
<td class="Property"><xsl:value-of select ="local-name(.)"/></td>
<td class="Value">
<xsl:choose>
<xsl:when test="count(./*) > 0">
<xsl:call-template name="ErrorTable">
<xsl:with-param name="n" select=".." />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="replace_sab">
<xsl:with-param name="s" select="." />
<xsl:with-param name="a" select="'
'" />
<xsl:with-param name="b"><br /></xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:template>
<xsl:template name="replace_sab">
<!-- with string s, replace substring a by string b -->
<!-- s, a and b are parameters determined upon calling -->
<xsl:param name="s" />
<xsl:param name="a" />
<xsl:param name="b" />
<xsl:choose>
<xsl:when test="contains($s,$a)">
<xsl:value-of select="substring-before($s,$a)" />
<xsl:copy-of select="$b" />
<xsl:call-template name="replace_sab">
<xsl:with-param name="s" select="substring-after($s,$a)" />
<xsl:with-param name="a" select="$a" />
<xsl:with-param name="b" select="$b" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$s" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I was able to find the issue, which was due to the reference to the current node with the xml. Solution is as below.
<xsl:template match = "ErrorRecord">
<xsl:call-template name="ErrorTable">
<xsl:with-param name="n" select="./Exception" />
</xsl:call-template>
</xsl:template>
<xsl:template name="ErrorTable">
<xsl:param name="n" />
<xsl:for-each select="$n">
<table class="ErrorDetailTable">
<tr>
<th class="Property"> </th>
<th class="Value"> </th>
</tr>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="position() mod 2 = 0">
<tr class="tr-even">
<xsl:call-template name="ErrorCells"/>
</tr>
</xsl:when>
<xsl:otherwise>
<tr class="tr-odd">
<xsl:call-template name="ErrorCells"/>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<tr><td colspan="2"> </td></tr>
</table>
</xsl:for-each>
</xsl:template>
<xsl:template name="ErrorCells">
<td class="Property"><xsl:value-of select ="local-name(.)"/></td>
<td class="Value">
<xsl:choose>
<xsl:when test="count(./*) > 0">
<xsl:call-template name="ErrorTable">
<xsl:with-param name="n" select="." />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="replace_sab">
<xsl:with-param name="s" select="." />
<xsl:with-param name="a" select="'
'" />
<xsl:with-param name="b"><br /></xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:template>
<xsl:template name="replace_sab">
<!-- with string s, replace substring a by string b -->
<!-- s, a and b are parameters determined upon calling -->
<xsl:param name="s" />
<xsl:param name="a" />
<xsl:param name="b" />
<xsl:choose>
<xsl:when test="contains($s,$a)">
<xsl:value-of select="substring-before($s,$a)" />
<xsl:copy-of select="$b" />
<xsl:call-template name="replace_sab">
<xsl:with-param name="s" select="substring-after($s,$a)" />
<xsl:with-param name="a" select="$a" />
<xsl:with-param name="b" select="$b" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$s" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>

xsl for table view in sharepoint

I have DataView web part that get data from two lists in SharePoint. I'm trying to change web part view but i do not know enough the xsl. my code is
<XSL>
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource" version="1.0" exclude-result-prefixes="xsl msxsl ddwrt" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:SharePoint="Microsoft.SharePoint.WebControls" xmlns:ddwrt2="urn:frontpage:internal">
<xsl:output method="html" indent="no"/>
<xsl:decimal-format NaN=""/>
<xsl:param name="dvt_apos">'</xsl:param>
<xsl:param name="ManualRefresh"></xsl:param>
<xsl:param name="dvt_firstrow">1</xsl:param>
<xsl:param name="dvt_nextpagedata" />
<xsl:param name="dvt_groupfield" />
<xsl:variable name="dvt_1_automode">0</xsl:variable>
<xsl:template match="/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:agg="http://schemas.microsoft.com/sharepoint/aggregatesource" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">
<xsl:choose>
<xsl:when test="($ManualRefresh = 'True')">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td valign="top">
<xsl:call-template name="dvt_1"/>
</td>
<td width="1%" class="ms-vb" valign="top">
<img src="/_layouts/images/staticrefresh.gif" id="ManualRefresh" border="0" onclick="javascript: {ddwrt:GenFireServerEvent('__cancel')}" alt="Click here to refresh the dataview."/>
</td>
</tr>
</table>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="dvt_1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="dvt_1">
<xsl:variable name="dvt_StyleName">Table</xsl:variable>
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[#_x041f__x043e__x0442__x0432__x04 = 'Da']"/>
<xsl:variable name="dvt_RowCount" select="count($Rows)"/>
<xsl:variable name="RowLimit" select="10" />
<xsl:variable name="FirstRow" select="$dvt_firstrow" />
<xsl:variable name="LastRow">
<xsl:choose>
<xsl:when test="($FirstRow + $RowLimit - 1) > $dvt_RowCount"><xsl:value-of select="$dvt_RowCount" /></xsl:when>
<xsl:otherwise><xsl:value-of select="$FirstRow + $RowLimit - 1" /></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="IsEmpty" select="$dvt_RowCount = 0" />
<xsl:variable name="dvt_IsEmpty" select="$dvt_RowCount = 0"/>
<xsl:choose>
<xsl:when test="$dvt_IsEmpty">
<xsl:call-template name="dvt_1.empty"/>
</xsl:when>
<xsl:otherwise>
<table border="0" width="100%" cellpadding="0" cellspacing="0">
<tr >
<th style="width: 261px; text-align:center">Sredstvo koje se izdaje</th>
<th style="width: 164px; text-align:center">Izdata sredstva - trenutno stanje</th>
<th style="width: 240px; text-align:center">Količina - početno stanje</th>
</tr>
<xsl:call-template name="dvt_1.body">
<xsl:with-param name="Rows" select="$Rows"/>
<xsl:with-param name="FirstRow" select="$FirstRow" />
<xsl:with-param name="LastRow" select="$LastRow" />
</xsl:call-template>
</table>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="dvt_1.commandfooter">
<xsl:with-param name="FirstRow" select="$FirstRow" />
<xsl:with-param name="LastRow" select="$LastRow" />
<xsl:with-param name="RowLimit" select="$RowLimit" />
<xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />
<xsl:with-param name="RealLastRow" select="number(ddwrt:NameChanged('',-100))" />
</xsl:call-template>
</xsl:template>
<xsl:template name="dvt_1.body">
<xsl:param name="Rows"/>
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:variable name="dvt_Rows"><root>
<xsl:for-each select="$Rows">
<xsl:sort select="#_x0418__x0437__x0434__x0430__x04" order="ascending" />
<xsl:if test="(position() >= $FirstRow and position() <= $LastRow)"><xsl:copy-of select="." /></xsl:if>
</xsl:for-each>
</root></xsl:variable>
<xsl:for-each select="$Rows">
<xsl:sort select="#_x0418__x0437__x0434__x0430__x04" order="ascending" />
<xsl:variable name="NewGroup_0">
<xsl:choose>
<xsl:when test="not ($dvt_groupfield)"><xsl:value-of select="ddwrt:NameChanged(string(#_x0418__x0437__x0434__x0430__x04), 0)" /></xsl:when>
<xsl:otherwise></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:choose>
<xsl:when test="0" />
<xsl:when test="not($dvt_groupfield) and (not($NewGroup_0='') and position() >= $FirstRow and position() <= $LastRow or ($FirstRow = position()))">
<xsl:variable name="groupheader0">
<xsl:choose>
<xsl:when test="not (#_x0418__x0437__x0434__x0430__x04) and (#_x0418__x0437__x0434__x0430__x04) != false()"><xsl:value-of select="' '" /></xsl:when>
<xsl:otherwise><xsl:value-of select="#_x0418__x0437__x0434__x0430__x04" /></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:if test="not ((position()=1) or (position()=$FirstRow))"></xsl:if>
<xsl:call-template name="dvt_1.groupheader0">
<xsl:with-param name="fieldtitle">Sredstvo koje se izdaje</xsl:with-param>
<xsl:with-param name="fieldname">_x0418__x0437__x0434__x0430__x04</xsl:with-param>
<xsl:with-param name="fieldvalue" select="$groupheader0" />
<xsl:with-param name="fieldtype" select="'text'" />
<xsl:with-param name="nodeset" select="msxsl:node-set($dvt_Rows)/root//Row[((#_x0418__x0437__x0434__x0430__x04)=$groupheader0 or ((not(#_x0418__x0437__x0434__x0430__x04) or #_x0418__x0437__x0434__x0430__x04='') and $groupheader0=' '))]" />
<xsl:with-param name="groupid" select="'0'" />
<xsl:with-param name="displaystyle" select="'auto'" />
<xsl:with-param name="imagesrc" select="'/_layouts/images/plus.gif'" />
<xsl:with-param name="alttext" select="'expand'" />
<xsl:with-param name="altname" select="'collapse'" />
<xsl:with-param name="hidedetail" select="true()" />
<xsl:with-param name="showheader" select="true()" />
<xsl:with-param name="showheadercolumn" select="false()" />
</xsl:call-template>
</xsl:when>
</xsl:choose>
<xsl:variable name="BreakOut">
<xsl:choose>
<xsl:when test="not($dvt_groupfield) and position()=$LastRow+1"><xsl:value-of select="ddwrt:NameChanged('', -1)" /></xsl:when>
<xsl:otherwise>BreakOut</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="dvt_KeepItemsTogether" select="false()" />
<xsl:variable name="dvt_HideGroupDetail" select="true()" />
<xsl:if test="(position() >= $FirstRow and position() <= $LastRow) or $dvt_KeepItemsTogether">
<xsl:if test="not($dvt_HideGroupDetail)" ddwrt:cf_ignore="1">
<xsl:call-template name="dvt_1.rowview" />
</xsl:if>
</xsl:if>
<xsl:choose>
<xsl:when test="0" />
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="dvt_1.rowview">
<xsl:variable name="dvt_GroupStyle" select="'none'" />
<tr style="display:{$dvt_GroupStyle}">
<xsl:if test="position() mod 2 = 1">
<xsl:attribute name="class">ms-alternating</xsl:attribute>
</xsl:if><td class="ms-vb">
<xsl:value-of select="#_x0418__x0437__x0434__x0430__x04" disable-output-escaping="yes" /></td>
<xsl:if test="$dvt_1_automode = '1'" ddwrt:cf_ignore="1">
<td class="ms-vb" width="1%" nowrap="nowrap">
<span ddwrt:amkeyfield="" ddwrt:amkeyvalue="string($XPath)" ddwrt:ammode="view"></span>
</td>
</xsl:if><td class="ms-vb">
<xsl:text xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" ddwrt:nbsp-preserve="yes" disable-output-escaping="yes">&nbsp;</xsl:text>
</td><td class="ms-vb">
<xsl:text xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime" ddwrt:nbsp-preserve="yes" disable-output-escaping="yes">&nbsp;</xsl:text>
</td></tr>
</xsl:template>
<xsl:template name="dvt_1.empty">
<xsl:variable name="dvt_ViewEmptyText">There are no items to show in this view.</xsl:variable>
<table border="0" width="100%">
<tr>
<td class="ms-vb">
<xsl:value-of select="$dvt_ViewEmptyText"/>
</td>
</tr>
</table>
</xsl:template>
<xsl:template name="dvt_1.commandfooter">
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:param name="RowLimit" />
<xsl:param name="dvt_RowCount" />
<xsl:param name="RealLastRow" />
<table cellspacing="0" cellpadding="4" border="0" width="100%">
<tr>
<xsl:if test="$FirstRow > 1 or $LastRow < $dvt_RowCount">
<xsl:call-template name="dvt_1.navigation">
<xsl:with-param name="FirstRow" select="$FirstRow" />
<xsl:with-param name="LastRow" select="$LastRow" />
<xsl:with-param name="RowLimit" select="$RowLimit" />
<xsl:with-param name="dvt_RowCount" select="$dvt_RowCount" />
<xsl:with-param name="RealLastRow" select="$RealLastRow" />
</xsl:call-template>
</xsl:if>
</tr>
</table>
</xsl:template>
<xsl:template name="dvt_1.navigation">
<xsl:param name="FirstRow" />
<xsl:param name="LastRow" />
<xsl:param name="RowLimit" />
<xsl:param name="dvt_RowCount" />
<xsl:param name="RealLastRow" />
<xsl:variable name="PrevRow">
<xsl:choose>
<xsl:when test="$FirstRow - $RowLimit < 1">1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$FirstRow - $RowLimit" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="LastRowValue">
<xsl:choose>
<xsl:when test="$LastRow > $RealLastRow">
<xsl:value-of select="$LastRow"></xsl:value-of>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$RealLastRow"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="NextRow">
<xsl:value-of select="$LastRowValue + 1"></xsl:value-of>
</xsl:variable>
<td nowrap="nowrap" class="ms-paging" align="right">
<xsl:if test="$dvt_firstrow > 1" ddwrt:cf_ignore="1">
<a>
<xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent('dvt_firstrow={1}')" />;</xsl:attribute>
Start</a>
<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&nbsp;</xsl:text>
<a>
<xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$PrevRow,'}'))" />;</xsl:attribute>
<img src="/_layouts/images/prev.gif" border="0" alt="Previous" />
</a>
<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes">&nbsp;</xsl:text>
</xsl:if>
<xsl:value-of select="$FirstRow" />
- <xsl:value-of select="$LastRowValue" />
<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime">&nbsp;</xsl:text>
<xsl:if test="$LastRowValue < $dvt_RowCount or string-length($dvt_nextpagedata)!=0" ddwrt:cf_ignore="1">
<a>
<xsl:attribute name="href">javascript: <xsl:value-of select="ddwrt:GenFireServerEvent(concat('dvt_firstrow={',$NextRow,'}'))" />;</xsl:attribute>
<img src="/_layouts/images/next.gif" border="0" alt="Next" />
</a>
</xsl:if>
</td>
</xsl:template>
<xsl:variable name="dvt_2_automode">0</xsl:variable>
<xsl:decimal-format decimal-separator="," grouping-separator="." name="lcid3098" />
<xsl:template name="dvt_1.groupheader0">
<xsl:param name="fieldtitle" />
<xsl:param name="fieldname" />
<xsl:param name="fieldvalue" />
<xsl:param name="fieldtype" />
<xsl:param name="nodeset" />
<xsl:param name="groupid" />
<xsl:param name="displaystyle" />
<xsl:param name="imagesrc" />
<xsl:param name="alttext" />
<xsl:param name="altname" />
<xsl:param name="hidedetail" />
<xsl:param name="showheader" />
<xsl:param name="showheadercolumn" />
<xsl:if test="$showheader" ddwrt:cf_ignore="1">
<tr id="group{$groupid}" style="display:{$displaystyle}">
<td class="ms-gb" colspan="0" style="height: 1px; width: 261px;">
<xsl:if test="not($hidedetail)" ddwrt:cf_ignore="1">
<a href="javascript:" onclick="javascript:ExpGroupBy(this);return false;">
<img src="{$imagesrc}" border="0" alt="{$alttext}" name="{$altname}" /></a>
</xsl:if>
<xsl:text disable-output-escaping="yes" ddwrt:nbsp-preserve="yes" xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime">&nbsp;</xsl:text>
<xsl:choose>
<xsl:when test="$fieldtype='url'">
<a href="{$fieldvalue}">
<xsl:value-of select="$fieldvalue" />
</a>
</xsl:when>
<xsl:when test="$fieldtype='user'">
<xsl:value-of select="$fieldvalue" disable-output-escaping="yes" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$fieldvalue" disable-output-escaping="yes" /> </xsl:otherwise>
</xsl:choose>
</td>
<td style="height: 1px; width: 164px; text-align:center;"><xsl:value-of disable-output-escaping="yes" select="count($nodeset)" /></td>
<!-- <td style="height: 1px"><xsl:for-each select="/dsQueryResponse/Rows/Row"><xsl:value-of select="#_x041a__x043e__x043b__x0438__x04" disable-output-escaping="yes" /></xsl:for-each></td>
--><td style="height: 1px"><xsl:for-each select="/dsQueryResponse/Rows/Row"><xsl:value-of select="#_x041a__x043e__x043b__x0438__x04" /></xsl:for-each></td>
</tr>
</xsl:if>
</xsl:template>
</xsl:stylesheet> </XSL>
list should look like Figure 1, and I get my results as the code in Figure 2.
So, each field in the column kolicina - pocetno stanje get results for all, should be as in Figure 1 in the column Kolicina
Figure1
Figure2

for loop and use the value

I've the below line in XML.
<tb class="3">
<tr>
<td>
<b>English words </b>
</td>
<td>
<b>Arabic </b>
</td>
<td al="r">
<b>Arabic</b>
</td>
</tr>
<tr>
<td>bear </td>
<td>ḍam</td>
<td al="r">new</td>
</tr>
</tb>
Here is my xslt.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#class)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<!-- I want the condition here-->
</colgroup>
</xsl:template>
This gives me output of 33.3. And I want to create 3 cols(the class attribute value). And for each col the name should be increment value. as below.
<col name="1" width="33.3"/>
<col name="2" width="33.3"/>
<col name="3" width="33.3"/>
please let me know, how can i get the above result.
Thanks
Here is my answer.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<!--<xsl:apply-templates/>-->
</table>
</xsl:template>
<xsl:template name="colgroup">
<xsl:param name="count" select="./#cls"/>
<xsl:param name="final" select="1"/>
<xsl:variable name="colcnt" select="format-number(100 div number(./#cls),'##.#')"/>
<col class="colnum-{$final} colname-col{$final} colwidth-{$colcnt}"></col>
<xsl:if test="$final < $count">
<xsl:call-template name="colgroup">
<xsl:with-param name="final" select="$final +1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#cls)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<xsl:call-template name="colgroup"/>
</colgroup>
<xsl:for-each select="tr">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="tr">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="td">
<td>
<xsl:attribute name="align">
<xsl:choose>
<xsl:when test="./#al='r'">
<xsl:text>right</xsl:text>
</xsl:when>
<xsl:when test="./#al='c'">
<xsl:text>center</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>left</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates/>
</td>
</xsl:template>
If you are using XSLT 2.0, then one way to generate a specific number of elements, in your case col elements, is to use a variation of the xsl:for-each to do a specific number of iterations.
So, instead of doing <xsl:call-template name="colgroup"/> to call a recursive template, you could do this:
<colgroup>
<xsl:for-each select="1 to xs:integer($numbr)">
<col name="{.}" width="{$colcnt}"/>
</xsl:for-each>
</colgroup>
Note that you will need to define the xs namespace prefix in your stylesheet as follows
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">

apply- templates select substring after

I've the below XML.
<toc-item>
<toc-title>
6A. <content-style font-style="italic">(Repealed 64 of 1989 s.9)
</content-style>
</toc-title>
<toc-pg>U2/6A</toc-pg>
</toc-item>
and i'm running with the below XSLT.
<xsl:template name="toc" match="toc">
<div class="toc">
<div class="toc-part">
<table class="toc-div">
<tbody>
<tr>
<td>
<xsl:for-each select="toc-part/toc-div/toc-item">
<xsl:call-template name="toc-item"/>
</xsl:for-each>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</xsl:template>
<xsl:template name="toc-item" match="toc-item">
<xsl:variable name="tocpg">
<xsl:value-of select="concat('P',normalize-space(current()/toc-pg/text()))"/>
</xsl:variable>
<xsl:variable name="tocpgtag">
<xsl:choose>
<xsl:when test="contains($tocpg,'.')">
<xsl:value-of select="translate($tocpg,'.', '-')"/>
</xsl:when>
<xsl:when test="contains($tocpg,'/')">
<xsl:value-of select="translate($tocpg,'/', '-')"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="nu">
<xsl:number format="I."/>
</xsl:variable>
<xsl:variable name="Brac">
<xsl:call-template name="get_number_type">
<xsl:with-param name="number_string" select="./#num"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="NewL">
<xsl:value-of select="normalize-space($chapternumber)"/>
</xsl:variable>
<xsl:variable name="size">
<xsl:value-of select="fn:string-length($NewL)"/>
</xsl:variable>
<xsl:variable name="newNum">
<xsl:choose>
<xsl:when test="$size=1">
<xsl:value-of select="concat('0',normalize-space($NewL))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="normalize-space($NewL)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="d">
<xsl:value-of select="concat('toc-item-',$ThisDocument//ntw:nums[#num=1]/#word,'-level')"/>
</xsl:variable>
<xsl:variable name="new">
<xsl:value-of select="concat('er:#HKWBV1_ORD_',$newNum,'/',$tocpgtag)"/>
</xsl:variable>
<table class="toc-item-first-level">
<tbody>
<tr>
<xsl:choose>
<xsl:when test="./toc-pg">
<xsl:choose>
<xsl:when test="fn:contains(./toc-title,'.')">
<td class="toc-item-num">
<xsl:value-of select="concat(substring-before(./toc-title,'.'),'.')"/>
</td>
</xsl:when>
<xsl:otherwise>
<td colspan="2" align="left" class="padtit">
<xsl:value-of select="./toc-title"/>
</td>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="fn:contains(./toc-title,'.')">
<td class="toc-title">
<xsl:apply-templates select="./toc-title" mode="x"/>
</td>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
<td class="toc-pg">
<xsl:choose>
<xsl:when test="contains(./toc-pg,'.')">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</xsl:when>
<xsl:when test="contains(./toc-pg,'/')">
<a href="{$new}">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</a>
</xsl:when>
<xsl:otherwise>
<a href="{concat('#pg_',toc-pg)}">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</a>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:when>
<xsl:otherwise>
<td align="center" colspan="3">
<span class="font-style-bold">
<xsl:apply-templates select="./toc-title"/>
</span>
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</tbody>
</table>
<!--</table>-->
</xsl:template>
<xsl:template match="toc-title/text()" mode="x">
<xsl:analyze-string select="substring-after(.,'.')" regex="(\w)">
<xsl:matching-substring>
<xsl:apply-templates select="regex-group(1)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
here what i'm trying to achieve is in my XML in toc-title, there is a number followed by content-style, here my output is having 2 <td>
the number before .
Content after .
if there is no other tag except text after ., i'm able to get the text correctly, and i want to apply-templates for the content after ., please let me know how i can get this done.
here is the demo
Thanks

How to implement sorting using xslt on href

I am using xslt and I want to implement sorting on my href link.
below is the xslt part where I need to implement sorting.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:tlink="urn:TridionLinking" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:utils="urn:XSLTExtensions" exclude-result-prefixes="xsl xlink tlink msxsl utils">
<xsl:output method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="yes" />
<!--+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Title: View All the Destinations XHTML
Description: Render view all the destinations control
Author: Manoj Singh
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-->
<xsl:include href="dynamic_linking.xslt"/>
<!-- Translations are still loaded here because of XHTML content, research a way around that -->
<xsl:key name="kCityById" match="city" use="#id"/>
<xsl:variable name="vLocations" select="document(concat($publicationPath, /list/resources/#location))/list"/>
<xsl:variable name="destination" select="/list"/>
<xsl:param name="publicationPath"/>
<xsl:param name="pubURL"/>
<xsl:param name="pageURL"/>
<xsl:param name="region"/>
<xsl:param name="country"/>
<!-- offset controls the starting position of the results to show -->
<xsl:param name="offset">0</xsl:param>
<!-- blockSize controls how many results to show on a single page -->
<xsl:param name="blockSize" select="15" />
<!-- Amount of page links to show by default -->
<xsl:param name="pagesShown">20</xsl:param>
<xsl:variable name="totalHits" select="count(/list/destination[contains(concat($pubURL,#url),substring-before($pageURL,'/index.aspx'))])" />
<xsl:template name="calcStart">
<xsl:choose>
<xsl:when test="$offset = 0">1</xsl:when>
<xsl:otherwise>
<xsl:value-of select="($offset * $blockSize) + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="calcEnd">
<xsl:choose>
<xsl:when test="(($offset + 1) * $blockSize) > $totalHits">
<xsl:value-of select="$totalHits"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="($offset + 1) * $blockSize"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="pageNavigation">
<xsl:param name="pageCount"/>
<xsl:param name="currPage"/>
<xsl:param name="showPages">
<xsl:choose>
<xsl:when test="$pagesShown > $pageCount">
<xsl:value-of select="$pageCount"/>
</xsl:when>
<xsl:when test="($pagesShown mod 2) = 0">
<xsl:value-of select="$pagesShown"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pagesShown + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:param name="currEntry" select="1"/>
<xsl:param name="offset">
<xsl:choose>
<xsl:when test="($currPage < $showPages) or ($pageCount = 1)">0</xsl:when>
<xsl:when test="$currPage > ($pageCount - $showPages + 1)">
<xsl:value-of select="$pageCount - $showPages"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$currPage - ($showPages div 2) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<!-- Header Processing -->
<xsl:if test="$currEntry = 1">
<xsl:if test="($pageCount > $showPages) and ($currPage >= $showPages)">
<li>... </li>
</xsl:if>
</xsl:if>
<xsl:if test="not ($currEntry > $showPages)">
<li>
<xsl:choose>
<xsl:when test="($currEntry + $offset) = $currPage">
<strong class="thisPage">
<xsl:value-of select="$currEntry + $offset"/>
</strong>
</xsl:when>
<xsl:otherwise>
<a href="{utils:GetHashedUrl(concat($pageURL,'?offset=',$currEntry + $offset - 1,'&blockSize=',$blockSize,'&pagesShown=',$pagesShown))}">
<xsl:value-of select="$currEntry + $offset"/>
</a>
</xsl:otherwise>
</xsl:choose>
</li>
<xsl:if test="not ($currEntry >= $showPages)">
<li class="separatorLine">|</li>
</xsl:if>
<xsl:call-template name="pageNavigation">
<xsl:with-param name="pageCount" select="$pageCount"/>
<xsl:with-param name="currPage" select="$currPage"/>
<xsl:with-param name="showPages" select="$showPages"/>
<xsl:with-param name="currEntry" select="$currEntry + 1"/>
<xsl:with-param name="offset" select="$offset"/>
</xsl:call-template>
</xsl:if>
<!-- Footer Processing -->
<xsl:if test="$currEntry = 1">
<xsl:if test="($pageCount > $showPages) and (($pageCount - $currPage + 1) >= $showPages)">
<li> ...</li>
</xsl:if>
</xsl:if>
</xsl:template>
<xsl:template name="displayPageNavigation">
<div class="continueBar">
<div class="continueBarLeft">
<xsl:variable name="displayStart">
<xsl:call-template name="calcStart"/>
</xsl:variable>
<xsl:variable name="displayEnd">
<xsl:call-template name="calcEnd"/>
</xsl:variable>
<strong>
<xsl:value-of select="utils:TextFormatted('DisplayingDestinations2Arg', concat($displayStart, '-', $displayEnd), $totalHits)"/>
</strong>
</div>
<div class="continueBarRight">
<ul class="paginationLinks">
<!-- Show a back button when available -->
<xsl:choose>
<xsl:when test="$offset > 0">
<li class="noBorder first">
<a class="iconButtonBackBar" href="{$pageURL}?offset={$offset - 1}&blockSize={$blockSize}&pagesShown={$pagesShown}">
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</a>
</li>
</xsl:when>
<xsl:otherwise>
<li class="noBorder first">
<span class="iconButtonBackBarOff">
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</span>
</li>
</xsl:otherwise>
</xsl:choose>
<!-- Output the page navigation links -->
<xsl:call-template name="pageNavigation">
<xsl:with-param name="pageCount">
<xsl:choose>
<xsl:when test="$blockSize >= $totalHits">1</xsl:when>
<xsl:when test="($totalHits mod $blockSize) != 0">
<xsl:value-of select="ceiling($totalHits div $blockSize)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$totalHits div $blockSize"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="currPage" select="$offset + 1"/>
</xsl:call-template>
<!-- Show a next button when available -->
<xsl:choose>
<xsl:when test="(($offset + 1) * $blockSize) > $totalHits">
<li class="last">
<span class="iconButtonForwardBarOff">
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</span>
</li>
</xsl:when>
<xsl:otherwise>
<li class="last">
<a class="iconButtonForwardBar" href="{$pageURL}?offset={$offset + 1}&blockSize={$blockSize}&pagesShown={$pagesShown}">
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
</a>
</li>
</xsl:otherwise>
</xsl:choose>
</ul>
</div>
<div class="clearBoth">
<xsl:comment/>
</div>
</div>
</xsl:template>
<!-- root match -->
<xsl:template match="/list">
<!--<xsl:value-of select="$publicationPath"/>-->
<div class="brownBarContainer">
<div class="brownBar">
All Destinations
</div>
</div>
<table width="100%" cellspacing="0" cellpadding="0" border="0" class="displayTable">
<tbody>
<tr>
<th scope="col" class="first sortSelected">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconDownSortArrow</xsl:attribute>
</xsl:element>Destination
</div>
</th>
<th scope="col" class="sortHover">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
</xsl:element>Country
</div>
</th>
<th scope="col" class="sortHover">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
</xsl:element>Region
</div>
</th>
</tr>
<xsl:choose>
<xsl:when test="$region='' and $country=''">
<xsl:apply-templates select="destination">
<xsl:sort select="#title" order="ascending" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="$country!=''">
<xsl:apply-templates select="destination[city/#id=$vLocations/region/country[#id=$country]/city/#id]">
<xsl:sort select="#title" order="ascending" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="$region!=''">
<xsl:apply-templates select="destination[city/#id=$vLocations/region[#id=$region]/country/city/#id]">
<xsl:sort select="#title" order="ascending" />
</xsl:apply-templates>
</xsl:when>
</xsl:choose>
</tbody>
</table>
<div class="horRuleWhite">
<hr/>
</div>
<xsl:call-template name="displayPageNavigation" />
</xsl:template>
<xsl:template match="text()"/>
<xsl:template match="destination">
<xsl:variable name="vReverseURL">
<xsl:call-template name="reverse">
<xsl:with-param name="string" select="#url"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="vCountryURL">
<xsl:call-template name="reverse">
<xsl:with-param name="string" select="substring-after($vReverseURL,'/')"/>
</xsl:call-template>
<xsl:text>/index.aspx</xsl:text>
</xsl:variable>
<xsl:variable name="vRegionURL">
<xsl:call-template name="reverse">
<xsl:with-param name="string" select="substring-after(substring-after($vReverseURL,'/'),'/')"/>
</xsl:call-template>
<xsl:text>/index.aspx</xsl:text>
</xsl:variable>
<xsl:variable name="current" select="."/>
<xsl:for-each select="$vLocations">
<tr>
<td class="detail first">
<a class="arrowSmallFront" href="{$current/#url}">
<xsl:value-of select="$current/#title"/>
</a>
</td>
<td class="detail noLeftBorder">
<a class="arrowSmallFront" href="{$vCountryURL}">
<xsl:value-of select="key('kCityById',$current/city/#id)/../#name"/>
</a>
</td>
<td class="detail noLeftBorder">
<a class="arrowSmallFront" href="{$vRegionURL}">
<xsl:value-of select="key('kCityById',$current/city/#id)/../../#name"/>
</a>
</td>
</tr>
</xsl:for-each>
</xsl:template>
<xsl:template name="reverse">
<xsl:param name="string" select="''"/>
<xsl:if test="$string != ''">
<xsl:call-template name="reverse">
<xsl:with-param name="string" select="substring($string,2)"/>
</xsl:call-template>
<xsl:value-of select="substring($string,1,1)"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Now everything is working fine, however I want to implement sorting on the href link in above xslt.
<tr>
<th scope="col" class="first sortSelected">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconDownSortArrow</xsl:attribute>
</xsl:element>Destination
</div>
</th>
<th scope="col" class="sortHover">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
</xsl:element>Country
</div>
</th>
<th scope="col" class="sortHover">
<div class="thPadding">
<xsl:element name="a">
<xsl:attribute name="href"></xsl:attribute>
<xsl:attribute name="class">iconSortArrowOff</xsl:attribute>
</xsl:element>Region
</div>
</th>
</tr>
1) Destinations.xml
<?xml version="1.0"?>
<list type="Destinations">
<resources location="include/xml/locations.xml">
<publication>481</publication>
</resources>
<destination id="594051" title="Sydney" url="/asiapacific/australia/sydney.aspx" >
<city id="192409" />
</destination>
<destination id="594088" title="Brisbane" url="/asiapacific/australia/brisbane.aspx" >
<city id="192397" />
</destination>
<destination id="594579" title="Dubai" url="/middleeast/uae/dubai.aspx" >
<city id="192855" />
</destination>
<destination id="594580" title="Abu Dhabi" url="/middleeast/uae/abudhabi.aspx" >
<city id="192851" />
</destination>
</list>
2) Locations.xml
<?xml version="1.0"?>
<list type="Locations">
<region id="192393" code="ASIA" name="Asia & the Pacific" shortname="Asia & the Pacific">
<country id="192395" code="AU" name="Australia" shortname="Australia">
<city id="192397" code="BNE" name="Brisbane" shortname="Brisbane">
<airport id="192399" code="BNE" name="Brisbane International Airport" shortname="Brisbane"></airport>
</city>
<city id="192409" code="SYD" name="Sydney" shortname="Sydney">
<airport id="192411" code="SYD" name="Kingsford Smith Airport" shortname="Sydney"></airport>
</city>
</country>
</region>
<region id="192847" code="MEAF" name="The Middle East & Africa" shortname="The Middle East & Africa">
<country id="192849" code="AE" name="United Arab Emirates" shortname="United Arab Emirates">
<city id="192851" code="AUH" name="Abu Dhabi" shortname="Abu Dhabi">
<airport id="192853" code="AUH" name="Abu Dhabi" shortname="Abu Dhabi"></airport>
</city>
<city id="192855" code="DXB" name="Dubai" shortname="Dubai">
<airport id="192857" code="DXB" name="Dubai International Airport" shortname="Dubai"></airport>
</city>
</country>
</region>
</list>
Please suggest!
Thanks.
Before each close tag </xsl:apply-templates> you need to include an <xsl:sort>, e.g.
<xsl:when test="$region='' and $country=''">
<xsl:apply-templates select="destination">
<xsl:sort select="#href" />
</xsl:apply-templates>
</xsl:when>
The above code assumes that #href is an attribute of the destination element, but that's just a guess, since you haven't told us where #href appears in the input. Unless I missed something.
If you need further help please post a sample of your input XML.
On second reading, I wonder if you mean that you want to sort based on which of the three a elements is clicked on? Please clarify, and edit your question to include a sample of your input XML.
OK, based on your comment it's clear that you want to sort based on whichever column the user clicked on last.
To expand on what Alejandro was saying, interactive behavior is outside the scope of XSLT. If you want XSLT to sort based on varying columns, you need to pass that column to the XSLT as an initial parameter. If the XSLT is running on the server, the whole page will reload when you change the sort order of the table. Do you want that?
For instant sorting you could call the XSLT within js on the client, but that's a bit hairy. Usually for interactive sorting, people just sort directly in javascript. Here are some tutorials and implementations:
http://www.javascripttoolbox.com/lib/table/
http://neil.fraser.name/software/tablesort/
http://dynamictable.com/