Неправильная группировка в каждой группе - PullRequest
0 голосов
/ 23 марта 2011

У меня есть следующий XML, из которого я пытаюсь сгенерировать HTML-файлы.

<?xml version="1.0" encoding="UTF-8"?>
<text>
    <body>
        <milestone unit="fragment"/>
            <div>

                <p>First line text in FIRST fragment</p>
                <p>Second line <seg>text in FIRST</seg> fragment</p>
                <p>Third line text in FIRST fragment</p>

                <milestone unit="fragment"/>
                <p>First line text in SECOND fragment</p>
                <p>Second line <seg>text in SECOND </seg> fragment</p>
                <p>Third line text in SECOND fragment</p>

                <milestone unit="fragment"/>
                <p>First line text in THIRD fragment</p>
                <p>Second line <seg>text in THIRD </seg> fragment</p>
                <p>Third line text in THIRD fragment</p>

            </div>
    </body>
</text>

Ожидаемый вывод HTML:

HTML 1:
<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<p>Third line text in FIRST fragment</p>


HTML 2:
<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND </span> fragment</p>
<p>Third line text in SECOND fragment</p>

HTML 3:
<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD </span> fragment</p>
<p>Third line text in THIRD fragment</p>

Это XSLT, где я использую for-каждой группе группировать узлы между тегами «вехой», но группировка происходит не так, как ожидалось.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="html" name="html" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" include-content-type="no"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="body">
        <xsl:for-each-group select="descendant::*" group-starting-with="milestone[@unit='fragment']">

            <xsl:variable name="currFragNumber">
                    <xsl:number count="milestone[@unit='fragment']" level="any" from="text"/>
                </xsl:variable>
                                <xsl:result-document href="{$currFragNumber}.html" format="html">
                    <xsl:apply-templates select="current-group()" />
                </xsl:result-document>

        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="p">
        <p>
            <xsl:apply-templates/>
        </p>
    </xsl:template>

    <xsl:template match="seg">
        <span>
            <xsl:apply-templates/>
        </span>
    </xsl:template>
</xsl:stylesheet>

Ниже приведен вывод после преобразования.

HTML 1:
<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<p>Third line text in FIRST fragment</p>

<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND</span>fragment</p>
<p>Third line text in SECOND fragment</p>

<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD</span>fragment</p>
<p>Third line text in THIRD fragment</p>

<p>First line text in FIRST fragment</p>
<p>Second line <span>text in FIRST</span>fragment</p>
<span>text in FIRST</span>
<p>Third line text in FIRST fragment</p>


HTML 2:
<p>First line text in SECOND fragment</p>
<p>Second line <span>text in SECOND </span> fragment</p>
<span>text in SECOND </span>
<p>Third line text in SECOND fragment</p>

HTML 3:
<p>First line text in THIRD fragment</p>
<p>Second line <span>text in THIRD </span> fragment</p>
<span>text in THIRD </span>
<p>Third line text in THIRD fragment</p>

Я пытаюсь понять, почему первая current-group () (т.е. первый «этап») соответствуетвесь документ, а не только узлы между тегами "веха".

Ответы [ 2 ]

1 голос
/ 24 марта 2011

Проблема в том, что вы также выбираете div, как я предложил в комментариях.

Использование:

<xsl:for-each-group select="div/*" 
                    group-starting-with="milestone[@unit='fragment']">

Будет правильно сериализовано три результирующих документа.Обратите внимание, что вы могли бы просто забыть первый milestone, потому что согласно http://www.w3.org/TR/xslt20/#xsl-for-each-group

Если присутствует атрибут group-starting-with, то его значение должно быть шаблоном.В этом случае все элементы в совокупности должны быть узлами.

Узлы в совокупности проверяются в порядке совокупности.Если узел соответствует шаблону или является первым узлом в совокупности *, то создается новая группа, и узел становится ее первым членом.В противном случае узел присваивается той же группе, что и его предыдущий узел в совокупности.

*: акцент мой.

0 голосов
/ 23 марта 2011

Редактировать : В своем первоначальном ответе (ниже) я думал, что значение атрибута select должно быть шаблоном, и теперь я вижу, что спецификация вводит меня в заблуждение.

В этом случае описанное поведение, скорее всего, является ошибкой.

@ Джахангир, поздравляем с обнаружением ошибки по крайней мере в трех процессорах XSLT 2.0.


Спецификация W3C XSLT 2.0 гласит (об атрибуте select xsl:for-each-group):

"• Если присутствует атрибут начального числа группы, то его значение должно бытьpattern. "

А правила для шаблона разрешают использование только осей child:: или attribute:: в шаблоне.

Следовательно, descendant::* не допускается в качестве шаблона .Я полагаю, что процессор XSLT воспринимает это как «исправляемую ошибку» и выполняет свое собственное действие в качестве восстановления.

Решение состоит в том, чтобы поместить первый элемент milestone на его место в качестве ближайшего следующего брата * 1031.* и измените select attribute of xsl: для каждой группы to: div / * `:

<text>
    <body>
        <div>
        <milestone unit="fragment"/>
            <p>First line text in FIRST fragment</p>
            <p>Second line 
                <seg>text in FIRST</seg> fragment
            </p>
            <p>Third line text in FIRST fragment</p>
            <milestone unit="fragment"/>
            <p>First line text in SECOND fragment</p>
            <p>Second line 
                <seg>text in SECOND </seg> fragment
            </p>
            <p>Third line text in SECOND fragment</p>
            <milestone unit="fragment"/>
            <p>First line text in THIRD fragment</p>
            <p>Second line 
                <seg>text in THIRD </seg> fragment
            </p>
            <p>Third line text in THIRD fragment</p>
        </div>
    </body>
</text>

и:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">
    <xsl:output method="html" name="html" encoding="UTF-8" indent="yes" omit-xml-declaration="yes" include-content-type="no"/>

    <xsl:template match="/">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="body">
        <xsl:for-each-group select="div/*" group-starting-with="milestone[@unit='fragment']">

            <xsl:variable name="currFragNumber">
                    <xsl:number count="milestone[@unit='fragment']" level="any" from="text"/>
                </xsl:variable>
                                <xsl:result-document href="{$currFragNumber}.html" format="html">
                    <xsl:apply-templates select="current-group()" />
                </xsl:result-document>

        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="p">
        <p>
            <xsl:apply-templates/>
        </p>
    </xsl:template>

    <xsl:template match="seg">
        <span>
            <xsl:apply-templates/>
        </span>
    </xsl:template>
</xsl:stylesheet>
...