Отсутствие переносов в блоке переносов - PullRequest
2 голосов
/ 21 января 2020

Есть ли возможность отключить перенос текста для фрагмента текста внутри блока 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, потому что ни одно из решений не работает должным образом. Кажется, это своего рода обходной путь, но я все еще не могу получить желаемый результат.

Я использую этот шаблон:

<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

Ответы [ 5 ]

3 голосов
/ 03 февраля 2020

Я нашел решение для этого (проверено для 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 для вас, можно легко найти в Интернете код, который анализирует текст по одному символу за раз.

1 голос
/ 03 февраля 2020

Один трюк состоит в том, чтобы установить «поддельный» язык для внутреннего <inline>:

Здесь я установил внутренний блок на украинский, поэтому форматировщик пытается использовать Украинские правила переноса слов, которые, очевидно, не применимы.

На самом деле, я нашел этот трюк, потому что мне понадобилось *1009* Украинский перенос слов для одного из моих документов, и он не применялся, если вы явно не укажете язык.

<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; вправо: с установленным "поддельным" языком

1 голос
/ 22 января 2020

Я думаю, что единственным решением будет разметка 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 Я получаю то, что ожидал, даже меняя поля спома, я могу получить переносы в областях, где он не отмечен, и ни в области, где установлены хранилища.

Вывод 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

1 голос
/ 21 января 2020

Функция, которая должна сделать трюк:

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

, но, как сообщалось, глючит несколько лет go. Так что, если у вас достаточно свежая версия fop, вы можете попробовать ее.

0 голосов
/ 21 января 2020

Должно быть возможно установить hyphenate="false" на fo:inline. hyphenate является унаследованным свойством и применяется как к fo:block, так и к fo:character. (См. https://www.w3.org/TR/xsl11/#fo_character и 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:

enter image description here

...