问题
I have a bunch of XML tables marked up using the CALS model and some of them have empty columns that I'd like to strip out. So here would be some example markup
<table frame="none">
<tgroup cols="4" colsep="0" rowsep="0">
<colspec colname="1" colnum="1" colwidth="75pt"/>
<colspec colname="2" colnum="2" colwidth="63pt" align="center"/>
<colspec colname="3" colnum="3" colwidth="63pt" align="center"/>
<colspec colname="4" colnum="4" colwidth="63pt"/>
<thead>
<row valign="bottom">
<entry> </entry>
<entry>No. 9</entry>
<entry>No. 10</entry>
<entry> </entry>
</row>
</thead>
<tbody>
<row>
<entry>Max. size:</entry>
<entry>10.5 m.</entry>
<entry>6.7 m.</entry>
<entry> </entry>
</row>
<row>
<entry>Length:</entry>
<entry>210 m.</entry>
<entry>100 m.</entry>
<entry> </entry>
</row>
<row>
<entry>Depth:</entry>
<entry>11.0</entry>
<entry>7.0</entry>
<entry> </entry>
</row>
</tbody>
</tgroup>
</table>
So it's column 4 in the above example that I would like to delete completely. In many (most?) cases it will be the last column, but it wont always be.
And you will note that column 4 does contain spaces, or possibly &# 160; characters.
So how would I go about removing such entire columns using xslt ?
TIA
Feargal
回答1:
Please give this a try:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<!-- This key will allow us to select all the entries in a column based on their
column number -->
<xsl:key name="kColumn" match="entry"
use="count(. | preceding-sibling::entry)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="tgroup">
<xsl:copy>
<xsl:apply-templates select="@*" />
<!-- Select colspecs whose column isn't all blank -->
<xsl:apply-templates
select="colspec[key('kColumn', position())[normalize-space(.)]]" />
<xsl:apply-templates select="node()[not(self::colspec)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="colspec">
<colspec colname="{position()}" colnum="{position()}">
<xsl:apply-templates
select="@*[local-name() != 'colname' and local-name() != 'colnum']" />
<xsl:apply-templates select="node()" />
</colspec>
</xsl:template>
<!-- Omit entries that belong to all-blank columns -->
<xsl:template match="entry[not(key('kColumn', position())[normalize-space(.)])]" />
</xsl:stylesheet>
In addition to removing blank columns, it also takes care of renumbering the columns that are kept (I assumed you would want this), so with this input, where the second column is blank:
<table frame="none">
<tgroup cols="4" colsep="0" rowsep="0">
<colspec colname="1" colnum="1" colwidth="75pt"/>
<colspec colname="2" colnum="2" colwidth="63pt" align="center"/>
<colspec colname="3" colnum="3" colwidth="63pt" align="center"/>
<colspec colname="4" colnum="4" colwidth="63pt"/>
<thead>
<row valign="bottom">
<entry> </entry>
<entry> </entry>
<entry>No. 9</entry>
<entry>No. 10</entry>
</row>
</thead>
<tbody>
<row>
<entry>Max. size:</entry>
<entry> </entry>
<entry>10.5 m.</entry>
<entry>6.7 m.</entry>
</row>
<row>
<entry>Length:</entry>
<entry> </entry>
<entry>210 m.</entry>
<entry>100 m.</entry>
</row>
<row>
<entry>Depth:</entry>
<entry> </entry>
<entry>11.0</entry>
<entry>7.0</entry>
</row>
</tbody>
</tgroup>
</table>
The result is:
<table frame="none">
<tgroup cols="4" colsep="0" rowsep="0">
<colspec colname="1" colnum="1" colwidth="75pt" />
<colspec colname="2" colnum="2" colwidth="63pt" align="center" />
<colspec colname="3" colnum="3" colwidth="63pt" />
<thead>
<row valign="bottom">
<entry> </entry>
<entry>No. 9</entry>
<entry>No. 10</entry>
</row>
</thead>
<tbody>
<row>
<entry>Max. size:</entry>
<entry>10.5 m.</entry>
<entry>6.7 m.</entry>
</row>
<row>
<entry>Length:</entry>
<entry>210 m.</entry>
<entry>100 m.</entry>
</row>
<row>
<entry>Depth:</entry>
<entry>11.0</entry>
<entry>7.0</entry>
</row>
</tbody>
</tgroup>
</table>
来源:https://stackoverflow.com/questions/14756558/strip-empty-columns-from-calstable-model