XSL-FO: принудительное наложение на таблицы - PullRequest
3 голосов
/ 04 декабря 2010

У меня возникла проблема, когда я публикую свои моды в формате pdf (XSL-FO).В моих таблицах возникают проблемы, когда содержимое ячейки переполняет свой столбец в следующий.Как принудительно сделать разрыв текста, чтобы вместо него была создана новая строка?

Я не могу вручную вставить символы пробела, так как записи таблицы вводятся программно.Я ищу простое решение, которое я могу просто добавить в docbook_pdf.xsl (как xsl: param или xsl: attribute)

EDIT: Здесь яна данный момент:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:import href="urn:docbkx:stylesheet"/>
...(the beginning of my stylesheet for pdf generation, e.g. header and footer content stuff)
<xsl:template match="text()">
    <xsl:call-template name="intersperse-with-zero-spaces">
        <xsl:with-param name="str" select="."/>
    </xsl:call-template>
</xsl:template>
<xsl:template name="intersperse-with-zero-spaces">
    <xsl:param name="str"/>
    <xsl:variable name="spacechars">
        &#x9;&#xA;
        &#x2000;&#x2001;&#x2002;&#x2003;&#x2004;&#x2005;
        &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x200B;
    </xsl:variable>

    <xsl:if test="string-length($str) &gt; 0">
        <xsl:variable name="c1" select="substring($str, 1, 1)"/>
        <xsl:variable name="c2" select="substring($str, 2, 1)"/>

        <xsl:value-of select="$c1"/>
        <xsl:if test="$c2 != '' and
            not(contains($spacechars, $c1) or
            contains($spacechars, $c2))">
            <xsl:text>&#x200B;</xsl:text>
        </xsl:if>

        <xsl:call-template name="intersperse-with-zero-spaces">
            <xsl:with-param name="str" select="substring($str, 2)"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

При этом длинные слова успешно разбиваются в ячейках таблицы!К сожалению, побочным эффектом является то, что обычный текст в другом месте (например, в нижнем разделе X) теперь разбивает слова так, что они появляются в отдельных строках.Есть ли способ изолировать вышеуказанный процесс только от таблиц?

Ответы [ 2 ]

17 голосов
/ 26 декабря 2010

В длинных словах попробуйте вставить символ пробела нулевой ширины между символами, где допускается разрыв.

5 голосов
/ 13 ноября 2015

Поскольку вы используете XSLT 2.0:

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

При этом используется экранирование категории (http://www.w3.org/TR/xmlschema-2/#nt-catEsc), а не явный список символов для сопоставления, но вместо этого вы можете сделать это таким образом. Ему нужны два replace(), потому что внутренний replace() может вставить только символ между каждым вторым символом. Внешние replace() соответствуют символам, которые не являются ни пробелами, ни символами, добавленными внутренним replace().


Вставка после каждого тринадцатого непробельного символа:

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

Внутренний replace() вставляет символ после каждых 13 непробельных символов, а внешний replace() исправляет его, если 14-й символ был пробелом.


Если вы используете AH Formatter, то вы можете использовать axf:word-break="break-all", чтобы позволить AH Formatter разрываться в любом месте слова. Смотри https://www.antennahouse.com/product/ahf64/ahf-ext.html#axf.word-break.

...