【问题标题】:Force line break after string length字符串长度后强制换行
【发布时间】:2016-08-17 01:55:32
【问题描述】:

我想在使用 AH Formatter 生成的 PDF 中的 14 个字符的字符串长度后强制换行。所以这是我的 xsl 代码,没有任何换行尝试:

<xsl:attribute-set name="big" use-attribute-sets="bold">
  <xsl:attribute name="font-size">38pt</xsl:attribute>
  <xsl:attribute name="line-height">28.84pt</xsl:attribute>
  <xsl:attribute name="text-align">center</xsl:attribute>
  <xsl:attribute name="letter-spacing">1mm</xsl:attribute>
</xsl:attribute-set>

<xsl:attribute-set name="small" use-attribute-sets="bold">
  <xsl:attribute name="font-size">27pt</xsl:attribute>
  <xsl:attribute name="line-height">27pt</xsl:attribute>
  <xsl:attribute name="text-align">center</xsl:attribute>
  <xsl:attribute name="letter-spacing">1mm</xsl:attribute>
</xsl:attribute-set>

<xsl:choose>
   <xsl:when test="string-length($count_cover)>=14">
      <fo:block xsl:use-attribute-sets="small">
         <xsl:apply-templates/>
      </fo:block>
    </xsl:when>
    <xsl:otherwise>          
      <fo:block xsl:use-attribute-sets="big">
         <xsl:apply-templates/>
      </fo:block>
   </xsl:otherwise>
</xsl:choose>

是否可以使用 XSL-FO 强制换行?

【问题讨论】:

    标签: xslt xsl-fo antenna-house


    【解决方案1】:

    如果标题可以转成字符串,可以插入&lt;fo:block/&gt;作为换行符。

    <xsl:variable name="cover_title" as="xs:string" select="'Very Long Cover Title! Very Long Cover Title! Very Long Cover Title! '"/>
    <xsl:variable name="count_cover" as="xs:integer" select="string-length($cover_title)"/>
    <xsl:variable name="lf_position" as="xs:integer" select="14"/>
    
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$count_cover gt $lf_position">
                <fo:block xsl:use-attribute-sets="small">
                    <xsl:analyze-string select="$cover_title" regex=".{{1}}">
                        <xsl:matching-substring>
                            <xsl:value-of select="."/>
                            <xsl:if test="position() eq $lf_position">
                                <fo:block/>
                            </xsl:if>
                        </xsl:matching-substring>
                        <xsl:non-matching-substring/>
                    </xsl:analyze-string>
                </fo:block>
            </xsl:when>
            <xsl:otherwise>
                <fo:block xsl:use-attribute-sets="big">
                    <xsl:value-of select="$cover_title"/>
                </fo:block>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    

    结果:

    <fo:block font-weight="bold" font-size="27pt" line-height="27pt" text-align="center" letter-spacing="1mm">Very Long Cove<fo:block/>r Title! Very Long Cover Title! Very Long Cover Title! </fo:block>
    

    但是,此方法忽略了单词边界和连字符控制。如果您打算制作书籍封面标题,最好使用 fo:block-container 引入 AH Formatter 扩展。

    1. 使用 fo:block-container 在封面中固定位置和大小的标题。
    2. 用@axf:overflow-condense=”font-size”设置属性@overflow="condense"。 https://www.antennahouse.com/product/ahf60/docs/ahf-ext.html#axf.overflow-condense
    3. 在 fo:block-container 中,放置存储标题内容的 fo:block。
    4. AH Formatter 会根据内容体积自动调整字体大小,因此您可以得到想要的结果。

    [示例]

    <fo:block-container position="absolute" top="..." left="..." width="..." height="..." overflow="condense" axf:overflow-condense="font-size" font-size="27pt" text-align="center">
        <fo:block>
           <fo:inline>Very Long Cover Title! Very Long Cover Title! Very Long Cover Title!</fo:inline>
        </fo:block>
    </fo:block-container>
    

    【讨论】:

      【解决方案2】:
      1. 如果您尝试打断单词(而不是部件号等),那么启用断字可能比在固定数量的字符后打断更好。

      2. 您可以使用linefeed-treatment="preserve" 并插入&amp;#xA; 而不是fo:block,正如Inserting a line break in a PDF generated from XSL FO using <xsl:value-of> 的答案所述。您可以使用&lt;xsl:value-of select="replace(., '(.{14})', '$1&amp;#xA;')" /&gt;

      3. 您可以改为在每 14 个字符之后插入一个零宽度空格 &amp;#x200B;,然后让 AH Formatter 在零宽度空格处中断:

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

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

        如果您使用的是比例宽度字体,则某些 14 个字符的序列(例如,不包括 14 个等宽行号)的宽度会比其他的多或少,因此您可能需要在两者之间插入 &amp;#x200B;更多字符,以便 AH Formatter 可以在中断之前尽最大努力填充行。

      4. 您可以使用axf:word-break="break-all" 在单词内启用换行。见https://www.antennahouse.com/product/ahf63/ahf-ext.html#axf.word-break

      【讨论】:

        【解决方案3】:

        您不能在 FO 中强制换行,但可以将字符串拆分为单独的 FO 块。

        <xsl:choose>
          <xsl:when test="string-length($count_cover) &gt;= 14">
            <fo:block><xsl:value-of select="substring($count_cover, 1, 13)"/></fo:block>
            <fo:block><xsl:value-of select="substring($count_cover, 14)"/></fo:block>
          </when>
          <xsl:otherwise>
            <fo:block>
              <xsl:value-of select="$count_cover"/>
            </fo:block>
          </xsl:otherwise>
        </xsl:choose>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-09-20
          • 1970-01-01
          • 1970-01-01
          • 2012-12-27
          • 1970-01-01
          • 2010-12-09
          • 1970-01-01
          相关资源
          最近更新 更多