连字符块中没有连字符

No hyphenation in hyphenated block

提问人:CrazyEight 提问时间:1/22/2020 最后编辑:CrazyEight 更新时间:2/7/2020 访问量:1373

问:

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

Fo-Example(示例):

<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 输出如下所示:

"Treiber" is still some sort of hyphenated

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

<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 断字

评论


答:

1赞 Pierre François 1/22/2020 #1

应该解决问题的功能是:

<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 版本,您可以尝试一下。

评论

0赞 Tony Graham 1/22/2020
但是,如果该行的宽度仅足以用于“此文本应连字符此”?
0赞 CrazyEight 1/22/2020
也试过了。我正在使用 fop2.3。我认为这是最新版本?
0赞 Pierre François 1/22/2020
我的版本现在是 fop 2.1,它也不适合我。不好意思。
0赞 Pierre François 1/23/2020
fop 的最新版本是 2.4。
0赞 Tony Graham 1/22/2020 #2

应该可以在 上设置 . 是继承属性,它适用于 和 。(见 https://www.w3.org/TR/xsl11/#fo_characterhttps://www.w3.org/TR/xsl11/#hyphenate。XSL-FO 文档文本中的每个字符都被解释为 ,因此它应该可以正常工作。hyphenate="false"fo:inlinehyphenatefo:blockfo:characterfo: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 得到这个结果:

enter image description here

评论

0赞 CrazyEight 1/22/2020
我将在我的文本中尝试使用不同的词。也许只是这个词有问题。我尝试了两种方法:在 上,但也......他们都没有工作hyphenate="false"fo:inlinekeep-together.within-line
0赞 Kevin Brown 1/22/2020
我不认为连字符是 fo:inline 上的有效选项,它仅适用于块级元素。
0赞 Tony Graham 1/22/2020
它不适用于 ,但应由文本内容中每个字符的名义继承。fo:inlinefo:characterfo:inline
0赞 CrazyEight 1/22/2020
好的,谢谢。。。使用 Apache FOP 2.3 和版本 2.4 它不起作用
0赞 Kevin Brown 1/24/2020
@TonyGraham,您可能希望编辑您的样本以备将来记录,但查看结果的人可能会感到困惑。可以连字符的第一行有句子“此文本不应该是......”。我知道你的意思,但这可能会令人困惑。
1赞 Kevin Brown 1/22/2020 #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 输出:

enter image description here

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

FOP输出:

enter image description here

结论是,使用 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>

enter image description here

评论

0赞 CrazyEight 1/22/2020
问题是,一旦 fop-hyphenation 决定对一个词进行催眠,是否有 .我认为唯一的解决方案是设置一个 twhere,您可以设置它的行为类似于keep-together.within-line="always"fo:blockhyphenate="false"fo:inline
0赞 CrazyEight 1/23/2020
感谢您的困扰...是否有可能使用 RenderX 或 AHF 在 Apache fop2.3 上设置连字属性的功能?fo:inline
0赞 Kevin Brown 1/24/2020
当然有一个选项,但不是“使用能力”,因为 FOP 是 FOP,而其他产品是闭源商业产品。Apache FOP 是开源的。您可以下载代码或雇用人员来做,或者向 FOP 团队提交请求。
1赞 Be Brave Be Like Ukraine 2/3/2020 #4

一个诀窍是为内部<内联>设置一个“虚假”语言

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

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

<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 的结果:

enter image description here
左:如OP的问题;右图:设置了“虚假”语言

评论

0赞 CrazyEight 2/5/2020
试过这个,但仍然连字符......但我也在使用和在外部,但仍然与内部连字符......wrap-option="wrap"text-align="justify"fo:block<fo:inline wrap-option="no-wrap" text-align="end" keep-together.within-line="always" xml:lang="uk">
3赞 Daniel Norberg 2/3/2020 #5

我找到了一个解决方案(针对 FOP 2.2 进行了验证)。该代码“禁用”连字,并将内联内容保持在同一行上。这当然是一个不能保证在以后的版本中起作用的黑客,但它对我的目的有效,也许它也可以帮助你。

示例 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 上轻松找到一次分析一个字符的文本的代码。

评论

0赞 CrazyEight 2/4/2020
哇,如果这可行,那就太好了。我会尽快尝试。谢谢!
0赞 CrazyEight 2/5/2020
好的,我现在按照你说的尝试了。可悲的是,它并没有真正为我解决问题。我的 .fo 输出如下:xml <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> <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> von gestern... </fo:block> </fo:block>
1赞 Daniel Norberg 2/5/2020
我会尽快检查你的 fo 代码。希望我能找到一些明显的东西。
1赞 Daniel Norberg 2/5/2020
我用新的 XSLT 更新了我的评论。请参阅“更新 XSLT 2.0”。它似乎效果更好。你能试试吗?
1赞 Daniel Norberg 2/6/2020
@CrazyEight 你看到我更新了 XSLT 了吗?我是 Stack Overflow 的新手,没有足够的代表来为您的原始问题添加评论,但您可以在更新的答案中看到新的 XSLT。