连字符块中没有连字符

No hyphenation in hyphenated block

是否可以为 fo:block 中的文本片段禁用连字符? 我的问题是无法设置 hyphenate="false" 在 fo:inline 上,因为它不是 属性。 fo:block 在 fo:block 中创建一个新行...

Fo-示例:

<fo:block hyphenate="true">
This text should be hyphenated <fo:inline hyphenate="false">This text shouldn’t be hyphenated</fo:inline>
</fo:block>

更新:

我尝试了@DanielNorberg 发布的解决方案,因为 none 所有解决方案都可以正常工作。这似乎是一种解决方法,但仍然没有提供我想要的输出。

我使用这个模板:

<xsl:template match="text()[ancestor::span[@class='nobreak']]">
    <xsl:param name="text"><xsl:value-of select="." /></xsl:param>
    <fo:inline hyphenate="false" color="red">
        <xsl:for-each select="tokenize(replace(replace($text,'(.)','\n'),'\n$',''),'\n')">
        <fo:inline keep-with-next.within-line="always">
            <xsl:value-of select="."/>
            <fo:character font-size="0pt">
                <xsl:value-of select="' '" />
            </fo:character>
        </fo:inline>
        </xsl:for-each>
    </fo:inline>
</xsl:template>

fo 部分看起来像这样

<fo:block xmlns:fn="http://www.w3.org/2005/xpath-functions" space-after="14pt">
    <fo:block text-align-last="left" font-size="10pt" color="black" text-align="justify"
        font-family="ITCFranklinGothicStd-Book" line-height="14pt" wrap-option="wrap">
        <fo:block hyphenate="true" xml:lang="de">
            <fo:block>Die Entwicklung der folgenden Jahre bestätigte unsere Auffassung. Nicht nur erwiesen
                sich die <fo:inline hyphenate="false" color="red">
                    <fo:inline keep-with-next.within-line="always">T<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">r<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">e<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">i<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">b<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">e<fo:character font-size="0pt"> </fo:character></fo:inline>
                    <fo:inline keep-with-next.within-line="always">r<fo:character font-size="0pt"> </fo:character></fo:inline>
                </fo:inline>
            </fo:block>
        </fo:block>
    </fo:block>
</fo:block>

所以 "Treiber" 这个词不应该连字符。但 PDF 输出如下所示:

解决方案更新: 对我有用的最终解决方法类似于上面的模板,但在每个字符之间添加了一个不间断的 space (⁠)。

<xsl:template match="text()[ancestor::span[@class='nobreak']]">
    <xsl:param name="text"><xsl:value-of select="replace(., ' ', '&#160;')" /></xsl:param>
    <fo:inline>
        <xsl:for-each select="tokenize(replace(replace($text,'(.)','\n'),'\n$',''),'\n')">
        <fo:inline>
            <xsl:value-of select="."/>
            <!-- non-breaking invisible space after each character-->
            <fo:inline>&#8288;</fo:inline>
        </fo:inline>
        </xsl:for-each>
    </fo:inline>
</xsl:template>

非常感谢@DanielNorberg

应该起作用的特征是:

<fo:block hyphenate="true">
  This text should be hyphenated 
  <fo:inline keep-together.within-line="always">This text shouldn’t be hyphenated</fo:inline>
</fo:block>

但据报道几年前有问题。所以,如果你有足够新的fop版本,你可以试试。

应该可以在 fo:inline 上设置 hyphenate="false"hyphenate 是继承的 属性,它适用于 fo:blockfo:character。 (参见 https://www.w3.org/TR/xsl11/#fo_character and https://www.w3.org/TR/xsl11/#hyphenate。)XSL-FO 文档文本中的每个字符都被解释为 fo:character,因此它应该可以正常工作。


对于此 XSL-FO:

<!-- Without fo:inline/@hyphenate: -->
<fo:block hyphenate="true" color="red">
This text should be hyphenated This text shouldn’t be hyphenated</fo:block>
<!-- With fo:inline/@hyphenate: -->
<fo:block hyphenate="true">
This text should be hyphenated <fo:inline hyphenate="false">This text shouldn’t be hyphenated</fo:inline>
</fo:block>

我用 AH Formatter V6.6 得到了这个结果:

我认为唯一的解决方案是像这样的 XSL FO 标记:

<fo:block hyphenate="true">
<fo:inline>I am some text that can be hyphenated. </fo:inline> 
<fo:inline keep-together.within-line="always">I</fo:inline> <fo:inline keep-together.within-line="always">am</fo:inline> <fo:inline keep-together.within-line="always">text</fo:inline> <fo:inline keep-together.within-line="always">that</fo:inline> <fo:inline keep-together.within-line="always">isn't</fo:inline> <fo:inline keep-together.within-line="always">hyphenated</fo:inline>.
</fo:block>

理论上,在整个块和任何必须在指定行(逐字)中保持在一起的子 fo:inline 上设置断字。现在,考虑到什么可能是单词边界以及什么是标点符号等,您如何使用某些模板到达那里可能不是直截了当的。

这需要一些测试。您可能还需要在具有 space 字符的单词之间放置中断 space 字符或其他内联元素。

更新 1

我使用上面的方法创建了一个简单的 FO。使用 RenderX 格式化我得到了我所期望的结果,即使改变了 spome 的边距,我也可以在未标记的区域和 none 在设置了 keeps 的区域进行连字。

RenderX 输出:

使用完全相同的模板(甚至多次调整边距,因为每个格式化程序在行结束处理方面都不同),我在 FOP 中根本无法使用任何连字符。

FOP 输出:

结论是使用 FOP 并尝试按照我所说的解决方法似乎存在问题。

更新 2

使用如下所述的 RenderX 和 AHF,在 fo:inline 上设置连字符有效。这是 RenderX 的输出:

 <fo:block hyphenate="true">
    <fo:inline>I am some text that can be hyphenated. I am some text that can be hyphenated. I am some text that can be hyphenated. </fo:inline> 
    <fo:inline hyphenate="false">I am some text that cannot be hyphenated. I am some text that cannot be hyphenated. I am some text that cannot be hyphenated. </fo:inline>         
 </fo:block>

一个技巧是为内部<inline>设置"bogus"语言:

在这里,我将内部块设置为乌克兰语,因此格式化程序尝试使用乌克兰语连字符规则,这显然不适用。

事实上,我发现了这个技巧,因为我需要 我的一份文档使用乌克兰语连字符,但除非您明确指定语言,否则它不适用。

<fo:block hyphenate="true">
This text should be hyphenated This text should be hyphenated This text should be
hyphenated <fo:inline  color="green" language="uk">This text shouldn’t be
hyphenated This text shouldn’t be hyphenated This text shouldn’t be
hyphenated </fo:inline>
</fo:block>

使用 RenderX XEP 的结果:


left: 如 OP 的问题; 对: "bogus" 语言设置

我找到了一个解决方案(针对 FOP 2.2 进行了验证)。代码 "disables" 断字并将内联内容保持在同一行。这当然是一个 hack,不能保证在以后的版本中工作,但它对我的目的有用,也许它也可以帮助你。

样本XML:

<block>Lorem ipsum <inline class='nobreak>This is neither hyphenated or line broken</inline>.</block>

XSLT 2.0 解决方案:

创建父内联元素(XSLT 1.0 和 2.0):

<xsl:template match="inline[@class='nobreak"]">
   <fo:inline>
      <xsl:apply-templates />
   </fo:inline>
</xsl:template>

"Disable" 断字并使文本内容保持在同一行 (XSLT 2.0):

<xsl:template match="text()[ancestor::inline[@class='nobreak']]">
    <xsl:param name="text"><xsl:value-of select="." /></xsl:param>
    <xsl:for-each select="tokenize(replace(replace($text,'(.)','\n'),'\n$',''),'\n')">
       <fo:inline keep-with-next.within-line="always">
          <xsl:value-of select="."/>
          <fo:character font-size="0pt">
             <xsl:value-of select="' '" />
          </fo:character>
       </fo:inline>
    </xsl:for-each>
</xsl:template>

更新 XSLT 2.0,这似乎更好:

<xsl:template match="text()[ancestor::phrase[@class='nobreak']]">
    <xsl:param name="text"><xsl:value-of select="replace(., ' ', '&#160;')" /></xsl:param>
    <xsl:for-each select="tokenize(replace(replace($text,'(.)','\n'),'\n$',''),'\n')">
       <fo:inline>
          <xsl:value-of select="."/>
          <fo:inline font-size="0pt">
             <xsl:value-of select="'$'" />
          </fo:inline>
       </fo:inline>
    </xsl:for-each>
</xsl:template>

如果您需要 XSLT 1.0 解决方案,您可以轻松地在 Web 上找到一次解析文本一个字符的代码。