代码之家  ›  专栏  ›  技术社区  ›  l0b0

XSLT输出纯文本表

  •  4
  • l0b0  · 技术社区  · 14 年前

    我正在使用XSL模板将XHTML/hResume文档转换为纯文本,但我在表布局(不,不是布局表)方面遇到了问题。目前,我有以下几点,使用优秀的戴夫帕森的 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 回复  |  直到 7 年前
        1
  •  4
  •   user357812 user357812    14 年前

    带有“全局”(表中的每个单元格) $maxWith

    <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