块的动态高度(最小和最大高度)

时间:2013-09-13 11:26:22

标签: xsl-fo

我正在努力克服XSL-FO block element的动态高度。我指定了一个包含三个主表的页面布局。第一个表的大小可能会有所不同。因此,我希望最后一张桌子的高度也不同,因为我想填充页面上可用的所有空间。 我可以指定表#3中包含的块可以占用的最小值和最大值。同时,如果第三个框的内容对于可用空间来说太长,则必须将其删除。

到目前为止我的代码:

<fo:table-row>
    <fo:table-cell xs:use-attribute-sets="cell-style font-size-small">
        <fo:block padding-top="3pt" padding-bottom="3pt">
            <fo:inline font-weight="bold">Label:</fo:inline>
        </fo:block>
    </fo:table-cell>

    <fo:table-cell xs:use-attribute-sets="cell-style font-size-small" >
        <fo:block-container overflow="hidden" min-height="2.1cm" max-height="4cm" padding-top="3pt" padding-bottom="3pt">
            <fo:block height="100%" keep-together.within-page="always">
                <xs:value-of select="$notes"/>
            </fo:block>
        </fo:block-container>
    </fo:table-cell>
</fo:table-row>

不幸的是,它不起作用。我没有设法避免使用此块/表的分页符,同时显示尽可能多的文本($ notes)。

非常感谢您的帮助!

提前致谢!

2 个答案:

答案 0 :(得分:2)

问题在于您在此处说明要求:

  

我想填写页面上可用的所有空间

XSL-FO 1.x中没有这样的概念。没有语义“从这里到页面末尾”。转换没有反馈循环,用于传递页面上剩余房间的长度信息。

使用XSL-FO时,您必须盲目地使用创建XSL-FO文件时可用的XSL-FO语义,将其放在栅栏上格式化,然后让格式化程序处理您的数据和意外事件你已投入数据以适应条件。

如果你只处理一个页面,那么你可以在该页面上放置一个剪切块容器并将表格流入其中,最后一个表格将扩展到页面的底部,但是你不会在底部获得边框边缘,并且块容器不会随表格之前和之后的内容一起流动。

如果你想要的行为与文档的其他内容一起流动,那么我认为你被卡住了。

答案 1 :(得分:2)

虽然这不是纯XSL FO,但我使用RenderX的软件实现了类似的解决方案。该解决方案涉及将页面格式化为区域树,该区域树是XML结构,其中页面的所有细节包括文本位置。使用特殊扩展名(rx:pinpoint元素),源XSL FO包含这些标记,无论您希望在哪里标记内容。

原始文档使用放置在页眉和页脚区域中的颜色来计算页面上的可用空间。

然后,区域树中将显示所有这些信息。使用XSL修改区域树,可以“测量”可用的空白区域,除以羽化针点的数量,然后修改区域树以“移动”内容后期组合但在最终输出之前。大多数格式化程序都允许您修改序列化区域树,然后将其返回给软件以进行最终输出。

下面的关键是知道xep:translate元素,它可用于向下移动区域树中的所有后续内容。因此,为了“轻推”所有区域,只需在每个允许的“轻推”点插入其中一个以将内容向下移动(可用空格/微调点数)。

我不知道您使用的是哪种格式化程序,但如果它不是RenderX,也许您可​​以修改以下内容以满足您的需要。这实际上是在几个应用程序中使用,其目的是“羽化”所有页面,以便页面的文本内容始终在页面的末尾结束。

样本链接:

http://www.tandesa.com/Public/Nudge/sf-orig.pdf(这是在未应用微调的情况下创建的原始文件)

http://www.tandesa.com/Public/Nudge/sf-nofeather.pdf(这显示了如果在轻推之前输出区域树会是什么样子,通常没有完成,但它显示了如何使用红色/蓝色区域来计算可用的微移区域)

http://www.tandesa.com/Public/Nudge/sf-nudged.pdf(轻推的结果)

http://www.tandesa.com/Public/Nudge/nudge.xsl(以下文件为完整性)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xep="http://www.renderx.com/XEP/xep" xmlns:math="http://exslt.org/math"
extension-element-prefixes="math" version="1.0">
<xsl:param name="max-feather-percent">40</xsl:param>
<xsl:param name="body-color" select="'1.0'"/>
<xsl:param name="footer-color" select="'1.0'"/>
<xsl:template match="xep:document">
    <xsl:copy>
        <xsl:apply-templates select="@*" mode="identity-copy"/>
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

<xsl:template match="xep:internal-bookmark">
    <xep:internal-bookmark>
        <xsl:apply-templates select="@*" mode="identity-copy"/>
    </xep:internal-bookmark>
</xsl:template>

<xsl:template match="xep:page">
    <xep:page>
        <xsl:apply-templates select="@*" mode="identity-copy"/>
        <!--
            1) Figure out white space
                a) Extract the y-till of the footer-color rectangle
                b) Find the smallest y-till of the body-color rectangle
                c) (b) - (a) is white space
        -->
        <xsl:variable name="headertop"
            select="number(xep:rectangle[preceding-sibling::xep:rgb-color[1][@red=$footer-color]]/@y-till)"/>
        <xsl:variable name="pagebottom"
            select="math:min(xep:rectangle[preceding-sibling::xep:rgb-color[1][@red=$body-color]]/@y-from)"/>
        <xsl:variable name="whitespace" select="$pagebottom - $headertop"/>
        <!-- 
            2) Count the nudge areas

            The nudge areas are all the pinpoints that start with "feather" *except* the first one on the page
            and possibly the last one (need to determine it a nudge ends the page then exclude it also)
            <xep:pinpoint x="90000" y="966000" value="feathersection"/>

            Current implementation only ignores the first one and not the last
        -->
        <xsl:variable name="nudgepoints"
            select="count(xep:pinpoint[starts-with(@value,'feather')]) - 1"/>
        <!-- 
            3) Calculate the nudge factor for each                
        -->
        <xsl:variable name="nudgefactor" select="$whitespace div $nudgepoints"/>
        <!-- 
            4) Determine whether the page should be feathered at all 
                a) No nudgepoints
                b) Space to compensate for is greater than max-feather-percent
        -->
        <xsl:variable name="apply-nudge">
            <xsl:choose>
                <xsl:when test="$nudgepoints = 0">
                    <xsl:text>false</xsl:text>
                </xsl:when>
                <xsl:when test="($whitespace div @height) > ($max-feather-percent div 100)">
                    <xsl:text>false</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>true</xsl:text>
                </xsl:otherwise>
            </xsl:choose>

        </xsl:variable>
        <xsl:comment> 
            headertop: <xsl:value-of select="$headertop"/>
            pagebottom: <xsl:value-of select="$pagebottom"/>
            nudgepoints: <xsl:value-of select="$nudgepoints"/>
            nudgefactor: <xsl:value-of select="$nudgefactor"/>
            headertop: <xsl:value-of select="$headertop"/>
            pagebottom: <xsl:value-of select="$pagebottom"/>
            applynudge: <xsl:value-of select="$apply-nudge"/>
        </xsl:comment>
        <xsl:apply-templates select="*" mode="identity-copy">
            <xsl:with-param name="nudgepoints" select="$nudgepoints"/>
            <xsl:with-param name="nudgefactor" select="$nudgefactor"/>
            <xsl:with-param name="apply-nudge" select="$apply-nudge"/>
        </xsl:apply-templates>
    </xep:page>
</xsl:template>

<!-- Replace proper pinpoints with xep:transform -->

<xsl:template match="xep:pinpoint[starts-with(@value,'feather')]" mode="identity-copy">
    <xsl:param name="nudgepoints"/>
    <xsl:param name="nudgefactor"/>
    <xsl:param name="apply-nudge"/>
    <xsl:if test="count(preceding-sibling::xep:pinpoint[starts-with(@value,'feather')]) > 0 and $apply-nudge = 'true'">
        <xep:translate x="0">
            <xsl:attribute name="y">
                <xsl:value-of select="-1 * $nudgefactor"/>
            </xsl:attribute>
        </xep:translate>
    </xsl:if>
</xsl:template>

<xsl:template match="xep:pinpoint[starts-with(@value,'dontfeather')]" mode="identity-copy">
    <xsl:param name="nudgepoints"/>
    <xsl:param name="nudgefactor"/>
    <xsl:param name="apply-nudge"/>
    <xsl:if test="count(preceding-sibling::xep:pinpoint[starts-with(@value,'dontfeather')]) = 0 and $apply-nudge = 'true'">
        <xep:translate x="0">
            <xsl:attribute name="y">
                <xsl:value-of select="$nudgepoints * $nudgefactor"/>
            </xsl:attribute>
        </xep:translate>
    </xsl:if>
</xsl:template>

<!-- Strip out the colored boxes -->
<xsl:template match="xep:rgb-color[@red='{$body-color}']" mode="identity-copy"/>
<xsl:template match="xep:rgb-color[@blue='{$footer-color}']" mode="identity-copy"/>
<xsl:template match="xep:rectangle[preceding-sibling::xep:rgb-color[1][@red='{$body-color}']]" mode="identity-copy"/>
<xsl:template match="xep:rectangle[preceding-sibling::xep:rgb-color[1][@blue='{$footer-color}']]" mode="identity-copy"/> 

<!-- identity copy rules -->
<xsl:template match="node() | @*" mode="identity-copy">
    <xsl:copy>
        <xsl:apply-templates select="@*" mode="identity-copy"/>
        <xsl:apply-templates select="node()" mode="identity-copy"/>
    </xsl:copy>
</xsl:template>



</xsl:stylesheet>