Skip to content Skip to sidebar Skip to footer

Xslt Remove Table Column When All Specific Value

Using XSLT, I need to remove a complete table column (header + body cells) when a column contains only '0.00' or '-'. i.e. If all the values in the cells of one or more columns are

Solution 1:

I have assumed that you mean't to say if all the data cells of the column are 0.00/- then remove it, not just one of them. If I have misunderstood, please advise and I will update the solution style-sheets accordingly.

There are a lot of different ways and options to create tables, and so your solution will need to be adjusted to the type and structure of your table. Shown here is a solution for a simple form of table.

XSLT 1.0 Solution

This XSLT 1.0 style-sheet...

<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:outputmethod="xml"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:templatename="ident"match="@*|node()"><xsl:copy><xsl:apply-templatesselect="@*|node()"/></xsl:copy></xsl:template><xsl:templatematch="td"><xsl:variablename="col"select="count(preceding-sibling::td)+1" /><xsl:iftest="../../tr/td[$col][. != '0.00'][. != '-']"><xsl:call-templatename="ident" /></xsl:if></xsl:template></xsl:stylesheet>

...when applied to this input document...

<table>
  <th>
    <td>Contestant</td><td>Score</td><td>Country</td>
  </th> 
  <tr>
    <td>Jack</td><td>0.00</td><td>AUS</td>
  </tr> 
  <tr>
    <td>Jill</td><td>-</td><td>-</td>
  </tr> 
</table> 

...will yield...

<table>
  <th>
    <td>Contestant</td>
    <td>Country</td>
  </th>
  <tr>
    <td>Jack</td>
    <td>AUS</td>
  </tr>
  <tr>
    <td>Jill</td>
    <td>-</td>
  </tr>
</table>

Only one column is removed - the one with all "empty" non-header cells.

XSLT 2.0 Solution

And here is the XSLT 2.0 equivalent...

<xsl:stylesheetversion="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:outputmethod="xml"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:templatematch="@*|node()"><xsl:copy><xsl:apply-templatesselect="@*|node()"/></xsl:copy></xsl:template><xsl:templatematch="td[ not(
  for $c in count(preceding-sibling::td)+1 return
    ../../tr/td[$c][.!='0.00'][.!= '-']  )]" /></xsl:stylesheet>

Solution 2:

I. A similar but more efficient (O(N)) XSLT 1.0 solution (Sean's XSLT 1.0 solution is O(N^2), where N is the number of columns):

<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:ext="http://exslt.org/common"exclude-result-prefixes="ext"><xsl:outputomit-xml-declaration="yes"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:variablename="vrtfColProps"><xsl:for-eachselect="/*/tr[1]/td"><xsl:variablename="vPos"select="position()"/><colpos="{$vPos}"><xsl:iftest="/*/tr/td[$vPos][not(. = 0.00 or . ='-')]">
           1
          </xsl:if></col></xsl:for-each></xsl:variable><xsl:variablename="vColProps"select="ext:node-set($vrtfColProps)/*"/><xsl:templatematch="node()|@*"name="identity"><xsl:copy><xsl:apply-templatesselect="node()|@*"/></xsl:copy></xsl:template><xsl:templatematch="td"><xsl:variablename="vPos"select="position()"/><xsl:iftest="$vColProps[@pos=$vPos]/node()"><xsl:call-templatename="identity"/></xsl:if></xsl:template></xsl:stylesheet>

when this transformation is applied on the following document:

<tableborder="1"><th><tr><td>Contestant</td><td>Score</td><td>Country</td></tr></th><tr><td>Jack</td><td>0.00</td><td>AUS</td></tr><tr><td>Jill</td><td>-</td><td>-</td></tr></table>

the wanted, correct result is produced:

<tableborder="1"><th><tr><td>Contestant</td><td>Country</td></tr></th><tr><td>Jack</td><td>AUS</td></tr><tr><td>Jill</td><td>-</td></tr></table>

II. More efficient (linear vs Sean's quadratical complexity) XSLT 2.0 solution:

<xsl:stylesheetversion="2.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:outputomit-xml-declaration="yes"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:variablename="vColProps"><xsl:for-eachselect="/*/tr[1]/td"><xsl:variablename="vPos"select="position()"/><colpos="{$vPos}"><xsl:iftest="/*/tr/td[$vPos][not(. = '0.00' or . = '-')]">
           1
          </xsl:if></col></xsl:for-each></xsl:variable><xsl:templatematch="node()|@*"name="identity"><xsl:copy><xsl:apply-templatesselect="node()|@*"/></xsl:copy></xsl:template><xsl:templatematch=
 "td[for $vPos in position()
      return
         not($vColProps/*[@pos=$vPos]/node())
    ]"/></xsl:stylesheet>

When this transformation is applied on the same XML document (above), the same wanted, correct result is produced:

<tableborder="1"><th><tr><td>Contestant</td><td>Country</td></tr></th><tr><td>Jack</td><td>AUS</td></tr><tr><td>Jill</td><td>-</td></tr></table>

Post a Comment for "Xslt Remove Table Column When All Specific Value"