Could anyone help me with the following transformation?
Here is the XML
<Chart>
<Chart.Series>
<DataSeries LegendText="Complete On Time" >
<DataSeries.DataPoints>
<DataPoint AxisXLabel="Sep 09" YValue="10" />
<DataPoint AxisXLabel="Oct 09" YValue="11" />
<DataPoint AxisXLabel="Nov 09" YValue="12" />
</DataSeries.DataPoints>
</DataSeries>
<DataSeries LegendText="Complete Overdue" >
<DataSeries.DataPoints>
<DataPoint YValue="1" />
<DataPoint YValue="2" />
<DataPoint YValue="3" />
</DataSeries.DataPoints>
</DataSeries>
</Chart.Series>
</Chart>
and here is the output id like
<table>
<thead>
<tr>
<th></th>
<th>Complete On Time</th>
<th>Complete Overdue</th>
</tr>
</thead>
<tbody>
<tr>
<th>Sep 09</th>
<th>10</th>
<th>1</th>
</tr>
<tr>
<th>Oct 09</th>
<th>11</th>
<th>2</th>
</tr>
<tr>
<th>Nov 09</th>
<th>12</th>
<th>3</th>
</tr>
</tbody>
A more natural solution:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<!-- basic table structure -->
<xsl:template match="Chart">
<table>
<thead>
<xsl:apply-templates select="Chart.Series" mode="thead" />
</thead>
<tbody>
<xsl:apply-templates select="Chart.Series" mode="tbody" />
</tbody>
</table>
</xsl:template>
<!-- table head -->
<xsl:template match="Chart.Series" mode="thead">
<tr>
<th />
<xsl:for-each select="DataSeries">
<th>
<xsl:value-of select="#LegendText" />
</th>
</xsl:for-each>
</tr>
</xsl:template>
<!-- table body -->
<xsl:template match="Chart.Series" mode="tbody">
<xsl:variable name="ds" select="DataSeries" />
<!-- the first data series contains the labels -->
<xsl:for-each select="$ds[1]/*/DataPoint">
<xsl:variable name="pos" select="position()" />
<tr>
<td>
<xsl:value-of select="#AxisXLabel" />
</td>
<!-- process all data points at the current position -->
<xsl:apply-templates select="$ds/*/DataPoint[$pos]" />
</tr>
</xsl:for-each>
</xsl:template>
<!-- data points become a <td> -->
<xsl:template match="DataPoint">
<td>
<xsl:value-of select="#YValue" />
</td>
</xsl:template>
</xsl:stylesheet>
Note that I use template modes to do different things with the same input.
The result is:
<table>
<thead>
<tr>
<th />
<th>Complete On Time</th>
<th>Complete Overdue</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sep 09</td>
<td>10</td>
<td>1</td>
</tr>
<tr>
<td>Oct 09</td>
<td>11</td>
<td>2</td>
</tr>
<tr>
<td>Nov 09</td>
<td>12</td>
<td>3</td>
</tr>
</tbody>
</table>
This is something close. It's been a couple of year for me though that I've done XSLT - ignore bad style.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output indent="yes" omit-xml-declaration="yes" ></xsl:output>
<xsl:template match="/">
<table>
<thead>
<tr>
<th></th>
<xsl:apply-templates select=".//DataSeries" />
</tr>
</thead>
<tbody>
<xsl:apply-templates select="//DataSeries[1]//DataPoint">
<xsl:with-param name="datablock">1</xsl:with-param>
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="DataSeries">
<th>
<xsl:value-of select="#LegendText"></xsl:value-of>
</th>
</xsl:template>
<xsl:template match="DataPoint">
<xsl:param name="datablock" />
<xsl:variable name="posi" select="position()"></xsl:variable>
<xsl:if test="$datablock = 1">
<tr>
<xsl:for-each select="#*">
<th>
<xsl:value-of select="."></xsl:value-of>
</th>
</xsl:for-each>
<xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
<xsl:with-param name="datablock" select="$datablock + 1">
</xsl:with-param>
</xsl:apply-templates>
</tr>
</xsl:if>
<xsl:if test="$datablock != 1">
<xsl:for-each select="#*">
<th>
<xsl:value-of select="."></xsl:value-of>
</th>
</xsl:for-each>
<xsl:apply-templates select="//DataSeries[$datablock+1]//DataPoint[$posi]">
<xsl:with-param name="datablock" select="$datablock + 1">
</xsl:with-param>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
Related
I am trying to write an XSLT template for the following XML structure:
<dealership>
<division>
<division_name>BMW</division_name>
<models>
<model_no>328i</model_no>
<model_no>M3</model_no>
<model_no>X5</model_no>
<model_no>528i</model_no>
</models>
<salesman>
<salesman_name>Bob</salesman_name>
<salesman_name>Jerry</salesman_name>
</salesman>
<mechanics>
<mechanic_name>Greg</mechanic_name>
<mechanic_name>Mike</mechanic_name>
<mechanic_name>Sean</mechanic_name>
</mechanics>
</division>
</dealership>
I need to output it to a HTML table in this format:
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<tr>
<td>BMW</td>
<td>328i</td>
<td>Bob</td>
<td>Greg</td>
</tr>
<tr>
<td></td>
<td>M3</td>
<td>Jerry</td>
<td>Mike</td>
</tr>
<tr>
<td></td>
<td>X5</td>
<td></td>
<td>Sean</td>
</tr>
<tr>
<td></td>
<td>528i</td>
<td></td>
<td></td>
</tr>
</table>
The problem is there can be any number of models, salesman, and mechanics. So somehow I need to get the node with the most children to know how many rows to create in the table, then I need a way to track which cells in the rows are empty. Any help would be greatly appreciated.
The best way I can think of to do it is to call a named template with the row number as a parameter. The template will then check to see if there is any data to output, and if so then build that row of the table and call itself with the next row number as a new parameter value.
This code demonstrates. The output is different from the HTML you show because yours doesn't correspond to the XML data you have given. As far as I can tell this is correct.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes" method="html" />
<xsl:template match="/dealership/division">
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<xsl:call-template name="row" >
<xsl:with-param name="i" select="1" />
</xsl:call-template>
</table>
</xsl:template>
<xsl:template name="row">
<xsl:param name="i"/>
<xsl:if test="models/model_no[$i] |
salesman/salesman_name[$i] |
mechanics/mechanic_name[$i]">
<tr>
<td>
<xsl:value-of select="division_name[$i]"/>
</td>
<td>
<xsl:value-of select="models/model_no[$i]"/>
</td>
<td>
<xsl:value-of select="salesman/salesman_name[$i]"/>
</td>
<td>
<xsl:value-of select="mechanics/mechanic_name[$i]"/>
</td>
</tr>
<xsl:call-template name="row" >
<xsl:with-param name="i" select="$i + 1" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
output
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<tr>
<td>BMW</td>
<td>328i</td>
<td>Bob</td>
<td>Greg</td>
</tr>
<tr>
<td></td>
<td>M3</td>
<td>Jerry</td>
<td>Mike</td>
</tr>
<tr>
<td></td>
<td>X5</td>
<td></td>
<td>Sean</td>
</tr>
</table>
Hear another possible solution.
<xsl:template match="/dealership/division">
<xsl:variable name="maxcnt">
<xsl:for-each select="*" >
<xsl:sort select="count(*)" order="descending"/>
<xsl:if test ="position()=1">
<xsl:value-of select="name(.)"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<table>
<tr>
<th>Division</th>
<th>Models</th>
<th>Salesman</th>
<th>Mechanics</th>
</tr>
<xsl:apply-templates select="*[name()=$maxcnt]/*" mode="row"/>
</table>
</xsl:template>
<xsl:template match="*" mode="row">
<xsl:variable name="pos" select="count(preceding-sibling::*)+1"/>
<tr>
<td>
<xsl:value-of select="../../division_name[$pos]"/>
</td>
<td>
<xsl:value-of select="../../models/model_no[$pos]"/>
</td>
<td>
<xsl:value-of select="../../salesman/salesman_name[$pos]"/>
</td>
<td>
<xsl:value-of select="../../mechanics/mechanic_name[$pos]"/>
</td>
</tr>
</xsl:template>
The first step is to figure out which child of division has the maximum count of children by it self. This is done by an for-each over all children sorted by count of children. Therefore the first on is the one with most children.
<xsl:for-each select="*" >
<xsl:sort select="count(*)" order="descending"/>
<xsl:if test ="position()=1">
<xsl:value-of select="name(.)"/>
</xsl:if>
</xsl:for-each>
This is based on a very good explanation from Dimitre Novatchev(*)
I am creating an fo:table that has 25 columns.
When I am converting to PDF the table is too wide for the size of the page (A4), how can I break the table by column, for example, every 5 columns I want to write on another page?
Thanks
I have taken an example of table which has nine column like:
<Table>
<thead>
<tr>
<td>Head1</td>
<td>Head2</td>
<td>Head3</td>
<td>Head4</td>
<td>Head5</td>
<td>Head6</td>
<td>Head7</td>
<td>Head8</td>
<td>Head9</td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</tr>
<tr>
<td>2-1</td>
<td>2-2</td>
<td>2-3</td>
<td>2-4</td>
<td>2-5</td>
<td>2-6</td>
<td>2-7</td>
<td>2-8</td>
<td>2-9</td>
</tr>
<tr>
<td>3-1</td>
<td>3-2</td>
<td>3-3</td>
<td>3-4</td>
<td>3-5</td>
<td>3-6</td>
<td>3-7</td>
<td>3-8</td>
<td>3-9</td>
</tr>
</tbody>
</Table>
Now, I have created XSLT to break it into multiple table by passing integer value in <xsl:param name="columnNumber"/> param:
<?xml version='1.0' ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output indent="yes"/>
<xsl:param name="columnNumber" select="xs:integer(4)"/>
<xsl:template match="Table">
<xsl:param name="countColumn" select="count(//tbody/tr[1]/td)"/>
<xsl:choose>
<xsl:when test="$countColumn gt $columnNumber">
<xsl:call-template name="divideTable">
<xsl:with-param name="tableToGenerate" select="ceiling($countColumn div $columnNumber)"/>
<xsl:with-param name="orginialTable" select="self::*"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:copy-of select="*"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="divideTable">
<xsl:param name="tableToGenerate"/>
<xsl:param name="orginialTable"/>
<xsl:param name="start" select="xs:integer(1)"/>
<xsl:param name="end" select="$columnNumber"/>
<xsl:param name="counter" select="xs:integer(1)"/>
<xsl:choose>
<xsl:when test="$counter le $tableToGenerate">
<Table>
<thead>
<xsl:copy-of
select="$orginialTable/thead/tr/td[position() le $end and position() ge $start]"/>
</thead>
<tbody>
<xsl:for-each select="$orginialTable/tbody/tr">
<tr>
<xsl:copy-of select="td[position() le $end and position() ge $start]"/>
</tr>
</xsl:for-each>
</tbody>
</Table>
<xsl:call-template name="divideTable">
<xsl:with-param name="start" select="xs:integer(($columnNumber * $counter) + 1)"/>
<xsl:with-param name="end" select="xs:integer(($columnNumber * $counter) + $columnNumber)"/>
<xsl:with-param name="tableToGenerate" select="$tableToGenerate"/>
<xsl:with-param name="orginialTable" select="$orginialTable"/>
<xsl:with-param name="counter" select="xs:integer($counter + 1)"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
It gives me ouput:
<?xml version="1.0" encoding="UTF-8"?>
<Table xmlns:xs="http://www.w3.org/2001/XMLSchema">
<thead>
<td>Head1</td>
<td>Head2</td>
<td>Head3</td>
<td>Head4</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>2-1</td>
<td>2-2</td>
<td>2-3</td>
<td>2-4</td>
</tr>
<tr>
<td>3-1</td>
<td>3-2</td>
<td>3-3</td>
<td>3-4</td>
</tr>
</tbody>
</Table>
<Table xmlns:xs="http://www.w3.org/2001/XMLSchema">
<thead>
<td>Head5</td>
<td>Head6</td>
<td>Head7</td>
<td>Head8</td>
</thead>
<tbody>
<tr>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>2-5</td>
<td>2-6</td>
<td>2-7</td>
<td>2-8</td>
</tr>
<tr>
<td>3-5</td>
<td>3-6</td>
<td>3-7</td>
<td>3-8</td>
</tr>
</tbody>
</Table>
<Table xmlns:xs="http://www.w3.org/2001/XMLSchema">
<thead>
<td>Head9</td>
</thead>
<tbody>
<tr>
<td>9</td>
</tr>
<tr>
<td>2-9</td>
</tr>
<tr>
<td>3-9</td>
</tr>
</tbody>
</Table>
Please have a look on this and check if this example helps
My solution was creating two independent tables.
Then I created two block of xsl templates, to differentiate the first block of the second block I used mode function.
Like this:
Table
....
<xsl:apply-templates select="content[#teste='1']" mode="first" />
....
<xsl:apply-templates select="content[#teste='1']" mode="second" />
....
XSL Templates block
....
<xsl:template match="content[#teste='1']" mode="first">
....
<xsl:template match="content[#teste='1']" mode="second">
....
First XML
<?xml version="1.0"?>
<response>
<status>
<code>0</code>
</status>
<newsList>
<news>
<id>1</id>
<title>some</title>
<date>30.11.2011T00:00.00</date>
<shortText>some short text</shortText>
<important>LOW</important>
</news>
Second XML
<?xml version="1.0"?>
<response>
<status>
<code>0</code>
</status>
<newsList>
<news>
<id>1</id>
<text>
Some text here
</text>
</news>
The result should be dysplaing title date and short Text from the first XML and the text from the second XML.
Below the XSLT I got so far.
<xsl:template match="response">
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">Title</th>
<th align="left">shortText</th>
<th align="left">date</th>
<th align="left">text</th>
</tr>
<xsl:for-each select="newsList/news">
<tr>
<td><xsl:value-of select="title" /></td>
<td><xsl:value-of select="shortText" /></td>
<td><xsl:value-of select="date" /></td>
<td><xsl:value-of select="document('news-details.xml')//news[id=$id_news]/text"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
But this will always show the text from the news number 1.
I know is't not possible to update the vaulue but how can get it done?
Here is an example using a key:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" version="5.0"/>
<xsl:param name="url2" select="'news-details.xml'"/>
<xsl:variable name="doc2" select="document($url2, /)"/>
<xsl:key name="k1" match="news" use="id"/>
<xsl:template match="/">
<html>
<head>
<title>Example</title>
</head>
<body>
<table>
<thead>
<tr>
<th>Title</th>
<th>short text</th>
<th>date</th>
<th>text</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="//news"/>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="news">
<xsl:variable name="id" select="id"/>
<tr>
<td><xsl:value-of select="title"/></td>
<td><xsl:value-of select="shortText"/></td>
<td><xsl:value-of select="date"/></td>
<td>
<xsl:for-each select="$doc2">
<xsl:value-of select="key('k1', $id)/text"/>
</xsl:for-each>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="response">
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th align="left">Title</th>
<th align="left">shortText</th>
<th align="left">date</th>
<th align="left">text</th>
</tr>
<xsl:apply-templates select="newsList/news"/>
</table>
</xsl:template>
<xsl:template match="newsList/news">
<xsl:variable name="id_news" select="ID"/>
<tr>
<td><xsl:value-of select="title" /></td>
<td><xsl:value-of select="shortText" /></td>
<td><xsl:value-of select="date" /></td>
<td>
<xsl:apply-templates select="document('news-details.xml')//news[id=$id_news]/text"/>
</td>
</tr>
</xsl:template>
<xsl:template match="text">
<xsl:value-of select="."/>
</xsl:template>
How to delete an empty column in HTML table using XSLT, and having something like this:
<table id="cas6">
<tr>
<td />
<td>
<table>
<tr>
<td>rechin</td>
<td />
</tr>
<tr>
<td>amarillo</td>
<td />
</tr>
</table>
</td>
</tr>
</table>
<table id="cas7">
<tr>
<td>rechin</td>
<td />
</tr>
<tr>
<td>amarillo</td>
<td />
</tr>
<tr>
<td>this shouldn't been</td>
<td>deleted</td>
</tr>
</table>
To delete the empty column, this being said to remove td's which are empty in all tr's in a Xth position
Here is a very simple solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="td[not(node())]">
<xsl:variable name="vPos" select="position()"/>
<xsl:if test="../../tr/td[position() = $vPos]/node()">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document (made well-formed):
<html>
<table border="1" id="cas6">
<tr>
<td/>
<td>
<table border="1">
<tr>
<td>rechin</td>
<td />
</tr>
<tr>
<td>amarillo</td>
<td />
</tr>
</table></td>
</tr>
</table>
<table border="1" id="cas7">
<tr>
<td>rechin</td>
<td />
</tr>
<tr>
<td>amarillo</td>
<td />
</tr>
<tr>
<td>this shouldn't been</td>
<td>deleted</td>
</tr>
</table>
</html>
The wanted correct result is produced:
<html>
<table border="1" id="cas6">
<tr>
<td>
<table border="1">
<tr>
<td>rechin</td>
</tr>
<tr>
<td>amarillo</td>
</tr>
</table></td>
</tr>
</table>
<table border="1" id="cas7">
<tr>
<td>rechin</td>
<td></td>
</tr>
<tr>
<td>amarillo</td>
<td></td>
</tr>
<tr>
<td>this shouldn't been</td>
<td>deleted</td>
</tr>
</table>
</html>
This is the XSLT that worked for me.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="td[not(node())]">
<xsl:variable name="pos" select="position()" />
<xsl:variable name="emptyTds" select="count(../../tr/td[position() = $pos and not(node())])" />
<xsl:variable name="allTds" select="count(../../tr/td[position() = $pos])" />
<xsl:if test="$emptyTds != $allTds">
<xsl:copy>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
If my understanding of the question is correct, for a given table, if all entries in the nth column are empty, you want to delete that column from the table?
Try this XSLT then
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="td">
<xsl:variable name="columnNumber" select="position()"/>
<xsl:if test="../../tr/td[position()=$columnNumber][* or text()]">
<xsl:copy>
<xsl:value-of select="$columnNumber"/>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is the 'identity' transform, but when it matches a TD element, it first gets the column number, and then checks if any other column in other rows are empty. If it finds any non-empty cells in the same column, it copies the TD element, otherwise it is ignored.
I'm trying to go from this kind of input:
<col title="one">
<cell>a</cell> <cell>b</cell> <cell>c</cell> <cell>d</cell>
</col>
<col title="two">
<cell>e</cell> <cell>f</cell> <cell>g</cell>
</col>
... to this HTML output with XSLT:
<table>
<tr> <th>one</th> <th>two</th> </tr>
<tr> <td>a</td> <td>e</td> </tr>
<tr> <td>b</td> <td>f</td> </tr>
<tr> <td>c</td> <td>g</td> </tr>
<tr> <td>d</td> </tr>
</table>
In other words I want to perform a matrix transposition. I couldn't find a simple way to do that, there probably isn't, I guess; how about a complicated one? While searching on Google I found hints that a way to solve this was through recursion. Any idea appreciated.
One possibility is to find the <col> with the most cells and then iterate over them in a nested loop. This guarantees the generation of a structurally valid HTML table.
<!-- this variable stores the unique ID of the longest <col> -->
<xsl:variable name="vMaxColId">
<xsl:for-each select="/root/col">
<xsl:sort select="count(cell)" data-type="number" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="generate-id()" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- and this selects the children of that <col> for later iteration -->
<xsl:variable name="vIter" select="
/root/col[generate-id() = $vMaxColId]/cell
" />
<xsl:template match="root">
<xsl:variable name="columns" select="col" />
<table>
<!-- output the <th>s -->
<tr>
<xsl:apply-templates select="$columns/#title" />
</tr>
<!-- make as many <tr>s as there are <cell>s in the longest <col> -->
<xsl:for-each select="$vIter">
<xsl:variable name="pos" select="position()" />
<tr>
<!-- make as many <td>s as there are <col>s -->
<xsl:for-each select="$columns">
<td>
<xsl:value-of select="cell[position() = $pos]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="col/#title">
<th>
<xsl:value-of select="." />
</th>
</xsl:template>
Applied to
<root>
<col title="one">
<cell>a</cell> <cell>b</cell> <cell>c</cell> <cell>d</cell>
</col>
<col title="two">
<cell>e</cell> <cell>f</cell> <cell>g</cell>
</col>
</root>
this produces:
<table>
<tr>
<th>one</th> <th>two</th>
</tr>
<tr>
<td>a</td> <td>e</td>
</tr>
<tr>
<td>b</td> <td>f</td>
</tr>
<tr>
<td>c</td> <td>g</td>
</tr>
<tr>
<td>d</td> <td></td>
</tr>
</table>
From Marrow:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="input">
<table border="1">
<xsl:apply-templates select="col[1]/cell"/>
</table>
</xsl:template>
<xsl:template match="cell">
<xsl:variable name="curr-pos" select="position()"/>
<tr>
<td>
<xsl:copy-of select="node()|../following-sibling::col/cell[$curr-pos]/node()"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
I put input tags around your xml to make it closer match an example I found.
(getting closer).
BTW: you can test by adding this as your 2nd line to your xml:
<?xml-stylesheet type="text/xsl" href="NonLinear.xslt"?>