Номер XSLT учитывает только экземпляры в текущем файле многофайлового документа. - PullRequest
6 голосов
/ 10 февраля 2011

Мне было поручено собрать книгу (с использованием XSL FO) из нескольких XML-файлов, сейчас я пытаюсь нумеровать цифры в этой книге (простая нумерация, без перезагрузки в главах или что-то в этом роде), мой наивный подход был сделать это

<xsl:template match="figure">
  <fo:block xsl:use-attribute-sets="figure">
    .. stuff to deal with images ..
    <fo:block xsl:use-attribute-sets="figure-caption">
      Figure <xsl:number level="any"/>: <xsl:apply-templates/>
    </fo:block>
  <fo:block xsl:use-attribute-sets="figure-caption">
</xsl:template>

У меня есть сводный XML-файл, который выбирает файлы для использования с помощью функции document() следующим образом:

<xsl:template match="include">
  <xsl:apply-templates select="document(@src)"/>
</xsl:template>

Теперь моя проблема в том, что number, кажется, всегда считает только экземпляры в текущем файле, а это не то, что я хочу (в настоящее время в файле есть только одно или два изображения, в результате чего все цифры равны 'Рисунок 1 или рисунок 2).

Я рассмотрел два подхода, оба по сути двухпроходные XSLT. Во-первых, простой подход - создать промежуточный XML-файл, содержащий всю книгу, используя преобразование личности, что я неохотно делаю по другим причинам.

Во-вторых, используя расширение node-set(), которое я пробовал вот так

<xsl:template match="include">
  <xsl:apply-templates select="ext:node-set(document(@src))"/>
</xsl:template>

но это дало тот же результат.

Есть идеи? Возможно что-то, что не является двухпроходным преобразованием? Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

3 голосов
/ 10 февраля 2011

Двухпроходный подход является более логичным и надежным.

Однопроходный подход очень сложен.Один может предоставить выражение в атрибуте value, равное <xsl:number>, и его можно использовать для суммирования "локального номера" с максимальным накопленным числом, что далеко от всех предыдущих документов.

Однако для этого требуется упорядочить документы (что плохо на функциональном языке), и это работает только для плоской схемы нумерации.В случае использования иерархической нумерации (3.4.2) я не вижу простого способа продолжить с максимального номера предыдущего документа.

В связи с этим я определенно объединю все документы в одиндо нумерации.

2 голосов
/ 10 февраля 2011

Я также буду использовать двухфазное преобразование. Но просто для удовольствия, с одним уровнем include и без повторений, эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="vIncludes" select="//include"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="include">
        <xsl:apply-templates select="document(@src)"/>
    </xsl:template>
    <xsl:template match="picture">
        <xsl:variable name="vRoot" select="generate-id(/)"/>
        <xsl:variable name="vInclude"
                      select="$vIncludes[
                                 $vRoot = generate-id(document(@src))
                              ]"/>
        <xsl:copy>
            <xsl:value-of
                 select="count(
                            document(
                               (.|$vInclude)/preceding::include/@src
                            )//picture |
                            (.|$vInclude)/preceding::picture
                         ) + 1"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

С этим входом:

<master>
    <include src="child3.xml"/>
    <block>
        <include src="child1.xml"/>
        <picture/>
    </block>
    <include src="child2.xml"/>
    <picture/>
</master>

И 'child1.xml'

<child1>
    <picture/>
</child1>

И 'child2.xml'

<child2>
    <picture/>
</child2>

И 'child3.xml'

<child3>
    <picture/>
</child3>

Выход:

<master>
    <child3>
        <picture>1</picture>
    </child3>
    <block>
        <child1>
            <picture>2</picture>
        </child1>
        <picture>3</picture>
    </block>
    <child2>
        <picture>4</picture>
    </child2>
    <picture>5</picture>
</master>
0 голосов
/ 10 февраля 2011

Я думаю, что я сделал бы предварительный анализ, который выводит сводную информацию обо всех документах в одном XML-файле, а затем использовал бы ее в качестве вторичного ввода для вычисления числа.Сводная информация в вашем случае может быть просто подсчетом того, сколько цифр содержит каждый документ, но во многих случаях может быть полезно хранить другую информацию, такую ​​как идентификаторы разделов, которые будут служить целью для гиперссылок.

0 голосов
/ 10 февраля 2011

Вы можете использовать вспомогательный XML-документ, чтобы отслеживать последний номер рисунка и загружать этот файл как документ из таблицы стилей. Или, если вы не хотите управлять двумя выходными файлами из одной и той же таблицы стилей («реальный» вывод FOP и счетчик рисунков), вы можете просто загрузить файл FOP предыдущей главы и найти МАКС. Заголовка рисунка.

Или вы можете передать номер последней цифры в качестве параметра с нулем по умолчанию и передать параметр в командной строке. Значение этого параметра, полученное в результате синтаксического анализа предыдущего в порядке возрастания результирующего документа.

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

Более структурированное и надежное решение состояло бы в управлении поперечными разделами документов, такими как индексы, оглавление и таблица рисунков, в максимально возможном количестве отдельных документов FO, которые будут сгенерированы при втором проходе с использованием их собственного XSLT.

...