группировка следующих братьев и сестер с одинаковыми именами и одинаковыми атрибутами вызывает исключение в саксонской - PullRequest
0 голосов
/ 29 сентября 2010

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

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

<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: блок.Прямо сейчас механизм работает для структур кода, как указано выше, но есть некоторые исключения.Фактический способ сделать это - решить для каждого тега p: - Я первая строка стиха?- Если да: собрать весь текст этого стиха и записать его в fo: блок, использовать атрибуты фактического (первого) тега p, чтобы установить форматирование блока. - Если нет: содержимое обрабатывалось раньше, ничего не делать.

Первая строка - это тег ap, которому непосредственно предшествует тег 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>

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

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

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

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

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

А теперьЯ немного застрял.

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

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

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

С уважением,

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

1 Ответ

1 голос
/ 29 сентября 2010

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

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