группировка следующих братьев и сестер с одинаковыми именами и одинаковыми атрибутами вызывает исключение в saxon

У меня есть XML-документы (похожие на docbook), которые нужно преобразовать в xsl-fo. Некоторые документы содержат стихи, и строки стихов написаны отдельными тегами p. Стихи разделены тегами br. Есть теги "страницы", которые не имеют отношения к делу, и их следует игнорировать.

Типичный пример кода:

<h4>Headline</h4>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
<h4>Other headline</h4>

Для вывода xsl-fo я хотел бы собрать весь текст стиха в один блок fo: block. Сейчас механизм работает для структур кода, как указано выше, но есть некоторые исключения. Фактический способ сделать это - решить для каждого тега p: - Я первая строка стиха? - Если да: соберите весь текст этого стиха и запишите его в блок fo: block, используйте атрибуты фактического (первого) тега p для установки форматирования блока - Если no: contents обрабатывались раньше, ничего не делать.

Первая строка - это тег p, которому непосредственно предшествует тег h4 или br (или тег страницы, которому непосредственно предшествует тег br). Это было легко развить.

Собрать текст стиха для данного примера было легко: сгруппируйте всех следующих братьев и сестер, определив группы, заканчивающиеся тегами h4 или br, затем я беру первую группу и использую все теги p (игнорируйте между тегами страницы или окончание h4 или br тег).

В коде:

<xsl:for-each-group select="following-sibling::*" group-ending-with="br|h4">
    <xsl:if test="position()=1">
        <xsl:for-each select="current-group()[not(self::h4) and not(self::br) and not(self::page)]">
            <xsl:apply-templates/>&crt;
        </xsl:for-each>
    </xsl:if>
</xsl:for-each-group>

Теперь к аналогичному примеру кода:

<h4>Headline</h4>
<p class="center">1</p>
<p>1st line of 1st verse</p>
<p>2nd line of 1st verse</p>
<br/>
<p class="center">2</p>
<p>1st line of 2nd verse</p>
<p>2nd line of 2nd verse</p>
<page n="100"/>
<p>3rd line of 2nd verse</p>
<h4>Other headline</h4>

Теперь центрированная буква p похожа на подзаголовок следующих стихов. На самом деле это не стих, но для моих целей было бы достаточно, если бы он был отделен от текста настоящего стиха. Таким образом, немного измененное правило для получения всего текста текущего стиха: Группируйте всех следующих братьев и сестер, определяя группы, заканчивая тегами h4 или br или тегом ap, у которого есть другой класс, чем текущий тег p. , затем я беру первую группу и использую все теги p (игнорируя промежуточные теги страницы или конечный тег h4 или br).

Поэтому я сохранил значение атрибута class текущего тега p в переменной с именем attributes и определил правило группы как:

<xsl:for-each-group select="following-sibling::*" group-ending-with="br|h4|p[normalize-space(@class) != $attributes]">

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

Теперь это отлично работает в моей тестовой среде в Oxygen с использованием Saxon-B9.1.0.6. Но преобразование должно выполняться в java с использованием Saxon9.jar, и там использование переменной внутри атрибута group-end-with xsl: for-each-group вызывает исключение.

А теперь я застрял.

Могли ли условия группировки быть определены лучше? Или, может быть, это вообще следует делать не с группировкой, а с совершенно другим подходом?

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

Любая помощь будет принята с благодарностью.

С наилучшими пожеланиями,

Кристиан Кирхгоф


person Christian Kirchhoff    schedule 29.09.2010    source источник


Ответы (1)


Эта таблица стилей:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="div[@class='poem']">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:for-each-group select="*" group-ending-with="br|h4">
                <div class="strophe">
                    <xsl:copy-of select="current-group()/self::p[not(@class)]"/>
                </div>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

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

<div class="poem">
    <h4>Headline</h4>
    <p>1st line of 1st verse</p>
    <p>2nd line of 1st verse</p>
    <br/>
    <p>1st line of 2nd verse</p>
    <p>2nd line of 2nd verse</p>
    <page n="100"/>
    <p>3rd line of 2nd verse</p>
</div>

Выход:

<div class="poem">
    <div class="strophe">
        <p>1st line of 1st verse</p>
        <p>2nd line of 1st verse</p>
    </div>
    <div class="strophe">
        <p>1st line of 2nd verse</p>
        <p>2nd line of 2nd verse</p>
        <p>3rd line of 2nd verse</p>
    </div>
</div>

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

<div class="poem">
    <h4>Headline</h4>
    <p class="center">1</p>
    <p>1st line of 1st verse</p>
    <p>2nd line of 1st verse</p>
    <br/>
    <p class="center">2</p>
    <p>1st line of 2nd verse</p>
    <p>2nd line of 2nd verse</p>
    <page n="100"/>
    <p>3rd line of 2nd verse</p>
</div>

Выход:

<div class="poem">
    <div class="strophe">
        <p>1st line of 1st verse</p>
        <p>2nd line of 1st verse</p>
    </div>
    <div class="strophe">
        <p>1st line of 2nd verse</p>
        <p>2nd line of 2nd verse</p>
        <p>3rd line of 2nd verse</p>
    </div>
</div>

Итак, эта таблица стилей:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="div[@class='poems']">
        <xsl:copy>
            <xsl:copy-of select="@*"/>
            <xsl:for-each-group select="*[preceding-sibling::h4]"
                                group-starting-with="h4">
                <div class="poem">
                    <xsl:for-each-group select="current-group()"
                                        group-ending-with="br">
                        <div class="strophe">
                            <xsl:copy-of select="current-group()
                                                  /self::p[not(@class)]"/>
                        </div>
                    </xsl:for-each-group>
                </div>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

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

<div class="poems">
    <h3>Poems</h3>
    <h4>Headline</h4>
    <p>1st line of 1st verse</p>
    <p>2nd line of 1st verse</p>
    <br/>
    <p>1st line of 2nd verse</p>
    <p>2nd line of 2nd verse</p>
    <page n="100"/>
    <p>3rd line of 2nd verse</p>
    <h4>Headline</h4>
    <p class="center">1</p>
    <p>1st line of 1st verse</p>
    <p>2nd line of 1st verse</p>
    <br/>
    <p class="center">2</p>
    <p>1st line of 2nd verse</p>
    <p>2nd line of 2nd verse</p>
    <page n="100"/>
    <p>3rd line of 2nd verse</p>
</div>

Выход:

<div class="poems">
    <div class="poem">
        <div class="strophe">
            <p>1st line of 1st verse</p>
            <p>2nd line of 1st verse</p>
        </div>
        <div class="strophe">
            <p>1st line of 2nd verse</p>
            <p>2nd line of 2nd verse</p>
            <p>3rd line of 2nd verse</p>
        </div>
    </div>
    <div class="poem">
        <div class="strophe">
            <p>1st line of 1st verse</p>
            <p>2nd line of 1st verse</p>
        </div>
        <div class="strophe">
            <p>1st line of 2nd verse</p>
            <p>2nd line of 2nd verse</p>
            <p>3rd line of 2nd verse</p>
        </div>
    </div>
</div>
person Community    schedule 29.09.2010