XSLT输出纯文本表

时间:2010-08-17 17:09:28

标签: xslt plaintext xmltable

我正在使用XSL模板将XHTML / hResume文档转换为纯文本,而我遇到了表布局问题(不,不是布局表)。目前我得到了以下内容,使用优秀的Dave Pawson padding template

<variable name="newline" select="'&#10;'"/>
<template match="xhtml:table">
    <variable name="maxWidth">
        <for-each select="xhtml:tr/xhtml:th | xhtml:tr/xhtml:td">
            <sort select="string-length(child::text()|child::node())" order="descending" data-type="number"/>
            <if test="position() = 1">
                <value-of select="string-length(child::text()|child::node())"/>
            </if>
        </for-each>
    </variable>
    <for-each select="xhtml:tr">
        <for-each select="xhtml:th|xhtml:td">
            <variable name="string">
                <for-each select="child::text()|child::node()">
                    <value-of select="."/>
                </for-each>
            </variable>
            <value-of select="$string"/>
            <call-template name="append-pad">
                <with-param name="length" select="$maxWidth - string-length($string)"/>
            </call-template>
            <text>&#32;</text>
        </for-each>
        <value-of select="$newline"/>
    </for-each>
    <value-of select="$newline"/>
</template>

这会产生相等宽度的列,但我想以几种方式改进它:

  • 查找并使用每列的最大宽度。为此,需要存储灵活数量的值。我可以在简单的情况下更改maxWidth来执行此操作,但是如何处理生成列?
  • 将生成列的内容居中。

有没有模板可以做这样的事情?

1 个答案:

答案 0 :(得分:4)

使用“全局”(对于表格中的每个单元格)$maxWith,您可以处理类似此样式表的colspans(保留您自己的逻辑):

<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <output method="text"/>
    <variable name="newline" select="'&#10;'"/>
    <template match="xhtml:table">
        <variable name="maxWidth">
            <for-each select="xhtml:tr/xhtml:th | xhtml:tr/xhtml:td">
                <sort select="string-length(child::text()|child::node())" order="descending" data-type="number"/>
                <if test="position() = 1">
                    <value-of select="string-length(child::text()|child::node())"/>
                </if>
            </for-each>
        </variable>
        <for-each select="xhtml:tr">
            <for-each select="xhtml:th|xhtml:td">
                <variable name="string">
                    <for-each select="child::text()|child::node()">
                        <value-of select="."/>
                    </for-each>
                </variable>
                <variable name="padding">
                    <choose>
                        <when test="@colspan">
                            <value-of select="$maxWidth * @colspan + @colspan - 1 - string-length($string)"/>
                        </when>
                        <otherwise>
                            <value-of select="$maxWidth - string-length($string)"/>
                        </otherwise>
                    </choose>
                </variable>
                <value-of select="$string"/>
                <call-template name="append-pad">
                    <with-param name="length" select="$padding"/>
                </call-template>
                <text>&#32;</text>
            </for-each>
            <value-of select="$newline"/>
        </for-each>
        <value-of select="$newline"/>
    </template>
    <template name="append-pad">
        <param name="length" select="0"/>
        <if test="$length != 0">
            <value-of select="'&#32;'"/>
            <call-template name="append-pad">
                <with-param name="length" select="$length - 1"/>
            </call-template>
        </if>
    </template>
</stylesheet>

输入:

<table xmlns="http://www.w3.org/1999/xhtml">
    <tr>
        <th>First</th>
        <th>Second</th>
        <th>Third</th>
    </tr>
    <tr>
        <td>One</td>
        <td>Two</td>
        <td>Three</td>
    </tr>
    <tr>
        <td colspan="2">Uno</td>
        <td>Tres</td>
    </tr>
</table>

输出:

First  Second Third  
One    Two    Three  
Uno           Tres   

编辑:为了使细胞与colspan居中,请使用此样式表(现在使用我自己的逻辑):

<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <output method="text"/>
    <variable name="newline" select="'&#10;'"/>
    <template match="xhtml:table">
        <apply-templates>
            <with-param name="maxWidth">
                <for-each select="xhtml:tr/xhtml:th | xhtml:tr/xhtml:td">
                    <sort select="string-length(.)" order="descending" data-type="number"/>
                    <if test="position() = 1">
                        <value-of select="string-length(.)"/>
                    </if>
                </for-each>
            </with-param>
        </apply-templates>
        <value-of select="$newline"/>
    </template>
    <template match="xhtml:tr">
        <param name="maxWidth"/>
        <apply-templates>
            <with-param name="maxWidth" select="$maxWidth"/>
        </apply-templates>
        <value-of select="$newline"/>
    </template>
    <template match="xhtml:th|xhtml:td">
        <param name="maxWidth"/>
        <variable name="string">
            <for-each select="child::text()|child::node()">
                <value-of select="."/>
            </for-each>
        </variable>
        <variable name="padding">
            <choose>
                <when test="@colspan">
                    <value-of select="($maxWidth * @colspan + @colspan - 1 - string-length($string)) div 2"/>
                </when>
                <otherwise>
                    <value-of select="$maxWidth - string-length($string)"/>
                </otherwise>
            </choose>
        </variable>
        <if test="@colspan">
            <call-template name="append-pad">
                <with-param name="length" select="floor($padding)"/>
            </call-template>
        </if>
        <value-of select="$string"/>
        <call-template name="append-pad">
            <with-param name="length" select="ceiling($padding)"/>
        </call-template>
        <text>&#32;</text>
    </template>
    <template name="append-pad">
        <param name="length" select="0"/>
        <if test="$length != 0">
            <value-of select="'&#32;'"/>
            <call-template name="append-pad">
                <with-param name="length" select="$length - 1"/>
            </call-template>
        </if>
    </template>
</stylesheet>

输出:

First  Second Third  
One    Two    Three  
     Uno      Tres