Номера страниц в xsl-fo (и apache fop) с несколькими последовательностями страниц

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

1 страница
2-n страниц

Затем следует следующий поддокумент с той же структурой:

1 страница
2 млн страниц

Как я уже сказал, эти вложенные документы объединены в один файл .pdf.

Вот мой шаблон xsl-fo:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
  <xsl:output method="xml" indent="yes" />
  <xsl:template match="/">
    <fo:root font-size="11pt" font-family="serif">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="A4-portrait"
          page-height="29.7cm" page-width="21.0cm" margin-top="1cm"
          margin-left="1.5cm" margin-right="1cm" margin-bottom="1cm">
          <fo:region-body />
          <fo:region-after region-name="footer" extent="15mm"/>
        </fo:simple-page-master>
      </fo:layout-master-set>

      <!-- first sub-document -->
      <fo:page-sequence master-reference="A4-portrait" initial-page-number="1">
      ...........
        <fo:block text-align="center">
            Page <fo:page-number/>/<fo:page-number-citation-last ref-id="end"/>
        </fo:block>
      ...........
      </fo:page-sequence>
      <fo:page-sequence master-reference="A4-portrait" id="end">
      ...........
        <fo:block text-align="center">
            Page <fo:page-number/>/<fo:page-number-citation-last ref-id="end"/>
        </fo:block>
      ...........
      </fo:page-sequence>

      <!-- second sub-document -->
      <fo:page-sequence master-reference="A4-portrait" initial-page-number="1">
      ...........
        <fo:block text-align="center">
            Page <fo:page-number/>/<fo:page-number-citation-last ref-id="end"/>
        </fo:block>
      ...........
      </fo:page-sequence>
      <fo:page-sequence master-reference="A4-portrait" id="end">
      ...........
        <fo:block text-align="center">
            Page <fo:page-number/>/<fo:page-number-citation-last ref-id="end"/>
        </fo:block>
      ...........
      </fo:page-sequence>

    </fo:root>
  </xsl:template>
</xsl:stylesheet>

Итак, у меня есть 2 одинаковых блока, состоящих из 2 последовательностей страниц каждый. В моем примере допустим, что вложенный документ 1 имеет 4 страницы (n = 4), а вложенный документ 2 состоит из 2 страниц (m = 2). Вот номера страниц, которые я получаю:

1/4
2/4
3/4
4/4
1/4
2/2

Все в порядке, кроме первой страницы второго вложенного документа. В этот момент <fo:page-number-citation-last ref-id="end"/> возвращает 4, что является значением из поддокумента 1. Таким образом, вместо 1/2 я получаю 1/4.

Любые предложения, как я могу это исправить?


person user1414745    schedule 26.03.2014    source источник
comment
Вы не показываете достаточно кода XSL-FO для надежной диагностики проблемы. Пожалуйста, добавьте больше контекста и меньше ........   -  person Mathias Müller    schedule 26.03.2014
comment
Может ли проблема заключаться в том, что у меня есть несколько элементов с id="end"?   -  person user1414745    schedule 26.03.2014
comment
Я могу только повториться: вы не показываете достаточно кода XSL-FO для надежной диагностики проблемы. Но, конечно же, идентификаторы, которые не уникальны для всего документа, всегда являются проблемой. FOP иногда выдает предупреждение, если идентификаторы не являются однозначными.   -  person Mathias Müller    schedule 26.03.2014


Ответы (1)


Не могли бы вы написать это как ответ (на оба моих вопроса), чтобы я мог его принять?

Конечно. Предварительным условием ссылки на конкретный элемент в XSL-FO является наличие средства его однозначной идентификации. Лучший способ сделать это — использовать атрибут ID для элемента, который вы хотите идентифицировать.

Идентификатор должен состоять из любой последовательности буквенно-цифровых символов и _ (то есть его значение должно быть допустимым NCName, см. спецификация здесь).

Вы можете ввести каждый идентификатор вручную, но обычно это делается с помощью xsl:generate-id() (это функция XSLT, а не XSL-FO). generate-id() автоматически обеспечивает уникальность идентификаторов во всем документе.

Обратите внимание, что generate-id() фактически генерирует идентификатор либо для текущего совпадения с шаблоном, либо для узла, который обрабатывается в итерации xsl:for-each.

Вы можете присвоить идентификатор каждому элементу в XML, и поэтому ссылка на что-либо по идентификатору возможна для любого элемента в XSL-FO.


Поскольку вы предоставляете здесь больше контекста, я дам более развернутый ответ. Теперь должно быть ясно, как вы можете решить проблему, но все еще неясно, почему проблема возникает в первую очередь.

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

Другими словами, в этой последовательности страниц:

  <!-- second sub-document -->
  <fo:page-sequence master-reference="A4-portrait" initial-page-number="1">
  <!--...-->
    <fo:block text-align="center">
        Page <fo:page-number/>/<fo:page-number-citation-last ref-id="end"/>
    </fo:block>
  <!--...-->
  </fo:page-sequence>

когда вы ссылаетесь на объект по его идентификатору (ref-id="end"), документ XSL-FO ищет объект с этим идентификатором, который встречается до ref-id. Как только узел с соответствующим идентификатором найден, поиск прекращается, и этот узел передается fo:page-number-citation.

В этом случае объект с совпадающим идентификатором перед ref-id представляет собой последовательность страниц первого вложенного документа.

person Mathias Müller    schedule 26.03.2014