XSL-FO:对表条目强制换行

时间:2010-12-03 23:17:26

标签: xml xslt pdf xsl-fo

当我将modspecs发布到pdf(XSL-FO)时,我遇到了一个问题。我的表存在问题,其中单元格的内容会将其列溢出到下一个列中。如何强制中断文本以便创建新行?

由于以编程方式输入表条目,因此无法手动插入零空格字符。我正在寻找一个简单的解决方案,我只需添加到docbook_pdf.xsl(作为xsl:param或xsl:属性)

修改 这是我目前所处的位置:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="urn:docbkx:stylesheet"/>
...(the beginning of my stylesheet for pdf generation, e.g. header and footer content stuff)
<xsl:template match="text()">
    <xsl:call-template name="intersperse-with-zero-spaces">
        <xsl:with-param name="str" select="."/>
    </xsl:call-template>
</xsl:template>
<xsl:template name="intersperse-with-zero-spaces">
    <xsl:param name="str"/>
    <xsl:variable name="spacechars">
        &#x9;&#xA;
        &#x2000;&#x2001;&#x2002;&#x2003;&#x2004;&#x2005;
        &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x200B;
    </xsl:variable>

    <xsl:if test="string-length($str) &gt; 0">
        <xsl:variable name="c1" select="substring($str, 1, 1)"/>
        <xsl:variable name="c2" select="substring($str, 2, 1)"/>

        <xsl:value-of select="$c1"/>
        <xsl:if test="$c2 != '' and
            not(contains($spacechars, $c1) or
            contains($spacechars, $c2))">
            <xsl:text>&#x200B;</xsl:text>
        </xsl:if>

        <xsl:call-template name="intersperse-with-zero-spaces">
            <xsl:with-param name="str" select="substring($str, 2)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

这样,长单词在表格单元格中成功分解!不幸的是,副作用是其他地方的正常文本(比如在性别不足的X中)现在分解单词,以便它们出现在单独的行上。有没有办法将上述流程与表格隔离开来?

2 个答案:

答案 0 :(得分:17)

长话说,尝试在允许休息的字符之间插入zero-width space character

答案 1 :(得分:5)

因为您正在使用XSLT 2.0:

<xsl:template match="text()">
  <xsl:value-of
      select="replace(replace(., '(\P{Zs})(\P{Zs})', '$1&#x200B;$2'),
                      '([^\p{Zs}&#x200B;])([^\p{Zs}&#x200B;])',
                      '$1&#x200B;$2')" />
</xsl:template>

这是使用类别转义(http://www.w3.org/TR/xmlschema-2/#nt-catEsc)而不是要匹配的明确字符列表,但您可以这样做。它需要两个replace(),因为内部replace()只能在每个第二个字符之间插入字符。外部replace()匹配不是空格字符的字符或内部replace()添加的字符。

在每第十三个非空格字符后插入:

<xsl:template match="text()">
  <xsl:value-of
      select="replace(replace(., '(\P{Zs}{13})', '$1&#x200B;'),
                      '&#x200B;(\p{Zs})',
                      '$1')" />
</xsl:template>

内部replace()在每13个非空格字符后面插入字符,如果第14个字符是空格字符,外部replace()会修复它。

如果您正在使用AH Formatter,那么您可以使用axf:word-break="break-all"来允许AH Formatter在单词中的任何位置中断。请参阅https://www.antennahouse.com/product/ahf64/ahf-ext.html#axf.word-break