【问题标题】:No hyphenation in hyphenated block连字符块中没有连字符
【发布时间】:2020-01-21 16:26:36
【问题描述】:

是否有可能禁用 fo:block 中文本 sn-p 的连字符? 我的问题是无法设置 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 发布的解决方案,因为所有解决方案都无法正常工作。这似乎是一种解决方法,但仍然没有提供我想要的输出。

我使用这个模板:

<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,'(.)','$1\\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 输出如下所示:

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

<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,'(.)','$1\\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

【问题讨论】:

    标签: xsl-fo apache-fop hyphenation


    【解决方案1】:

    我找到了解决方案(已针对 FOP 2.2 进行了验证)。代码“禁用”连字符并将内联内容保持在同一行。这当然是一个 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>
    

    “禁用”连字符并使文本内容保持在同一行(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,'(.)','$1\\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,'(.)','$1\\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 上轻松找到一次解析文本一个字符的代码。

    【讨论】:

    • 哇,如果这行得通,那就太好了。我会尽快尝试这个。谢谢!
    • 好的,我现在按照你说的尝试了。可悲的是,它并没有真正为我解决问题。我的 .fo 输出如下:xml &lt;fo:block hyphenate="true" xml:lang="de"&gt; &lt;fo:block&gt;Die Entwicklung der folgenden Jahre bestätigte unsere Auffassung. Nicht nur erwiesen sich die &lt;fo:inline&gt; &lt;fo:inline keep-with-next.within-line="always"&gt;T&lt;fo:character font-size="0pt"&gt; &lt;/fo:character&gt; &lt;/fo:inline&gt; &lt;fo:inline keep-with-next.within-line="always"&gt;r&lt;fo:character font-size="0pt"&gt; &lt;/fo:character&gt; &lt;/fo:inline&gt; &lt;/fo:inline&gt; von gestern... &lt;/fo:block&gt; &lt;/fo:block&gt;
    • 我会尽快检查您的 fo 代码。希望我能找到一些明显的东西。
    • 我用新的 XSLT 更新了我的评论。请参阅“更新 XSLT 2.0”。它似乎工作得更好。可以试试吗?
    • @CrazyEight 你看到我更新了 XSLT 了吗?我是 Stack Overflow 上的新手,没有足够的代表将 cmets 添加到您的原始问题中,但您可以在更新的答案中看到新的 XSLT。
    【解决方案2】:

    应该做到这一点的功能是:

    <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 版本,你可以试试。

    【讨论】:

    • 但是如果行的宽度只够“这个文本应该连字符这个”?
    • 也试过了。我正在使用 fop2.3。我认为这是最新版本?
    • 我的版本现在是 fop 2.1,它也不适合我。对不起。
    • fop 的最新版本是 2.4。
    【解决方案3】:

    我认为唯一的解决方案是这样的 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 上设置断字,必须在指定的行(逐字)中保持在一起。现在,考虑到什么是单词边界以及什么是标点符号等,您如何使用一些模板可能并不直接。

    这需要一些测试。您可能还需要在带有空格字符的单词之间添加换行符或其他内联元素。

    更新 1

    我使用上面的方法创建了一个简单的 FO。使用 RenderX 进行格式化我得到了我所期望的结果,即使更改了 spome 边距,我也可以在未标记的区域获得连字符,而在设置了保留的区域则没有。

    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>
    

    【讨论】:

    • 问题是一旦 fop-hyphenation 决定对一个词进行连字,是否有keep-together.within-line="always" 就无关紧要了。我认为唯一的解决方案是设置一个fo:block,你可以设置hyphenate="false",其行为类似于fo:inline
    • 感谢您的麻烦...是否有可能使用 RenderX 或 AHF 的功能在 Apache fop2.3 上设置 fo:inline 的连字符属性?
    • 当然有一个选项,但不是“使用能力”,因为 FOP 是 FOP,其他产品是闭源商业。 Apache FOP 是开源的。您可以下载代码或雇人来做,或向 FOP 团队提交请求。
    【解决方案4】:

    一个技巧是为内部&lt;inline&gt;设置“虚假”语言

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

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

    <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 的问题中; 正确:设置了“虚假”语言

    【讨论】:

    • 试过这个但仍然断字...但我也在外部fo:block上使用wrap-option="wrap"text-align="justify"但仍然与内部&lt;fo:inline wrap-option="no-wrap" text-align="end" keep-together.within-line="always" xml:lang="uk"&gt;断字...
    【解决方案5】:

    应该可以在fo:inline 上设置hyphenate="false"hyphenate 是一个继承属性,它适用于fo:blockfo:character。 (参见https://www.w3.org/TR/xsl11/#fo_characterhttps://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 得到这个结果:

    【讨论】:

    • 我会尝试在我的文本中使用不同的单词。也许这只是一个词的错误。我两种都试过了:hyphenate="false"fo:inline,还有keep-together.within-line...都没有工作
    • 我认为连字符不是 fo:inline 上的有效选项,它仅适用于块级元素。
    • 不适用于fo:inline,但对于fo:inline的文本内容中的每个字符,都应该由名义上的fo:character继承。
    • 好的,谢谢...使用 apache fop 2.3 和 2.4 版它不起作用
    • @TonyGraham,您可能想编辑您的样本以供将来记录,查看结果的人可能会感到困惑。您的第一行 can 有连字符“This text should not be ...”这句话。我知道你的意思,但可能会造成混淆。
    猜你喜欢
    • 2011-12-03
    • 2021-08-02
    • 2017-03-04
    • 2013-09-21
    • 2019-05-14
    • 2021-01-05
    相关资源
    最近更新 更多