XSLT: промежуточные итоги - PullRequest
       15

XSLT: промежуточные итоги

3 голосов
/ 03 января 2012

Исходный XML:

<Root>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>2</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>5</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>4</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>B</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>A</Code>
        <Value>10</Value>
    </Data>
    <Data>
        <Code>C</Code>
        <Value>5</Value>
    </Data>
....
</Root>

XSL-FO Код:

Мой код (XSL-FO) содержит 3 столбца, где каждый столбец содержит содержимое «A», «B», 'C'

<fo:table-body>
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm">
        <xsl:if test="Code='A'">
        <fo:table-cell>
        <fo:block height="12pt">Value
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt" border="0.1pt solid black" text-align="center">
            <xsl:value-of select="Value" /> 
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt">Points</fo:block> 
        </fo:table-cell>
        </xsl:if>
    </xfd:table-row-repeat>
</fo:table-body>

Один и тот же код для каждого столбца для отображения значений «B» и «C» В нижнем колонтитуле я должен получить эти промежуточные итоги «A», «B», «C '

<fo:table-body>
    <xfd:table-row-repeat xpath="Root/Data" font-family="Arial Narrow" font-size="10pt" padding-after="0.55cm">
        <xsl:if test="Code='A'">
        <fo:table-cell>
        <fo:block height="12pt">SubTotal
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt" border="0.1pt solid black" text-align="center">
            <--Here Sum of first 15 A's. if the A's or B's or C's exceed by 15, then the table flows to 2nd Page. In that case, 1st Page table-footer shows individual subtotals of first 15 A's, 15 B's and C's. In 2nd Page, the subtotals should contain Subtotal of first 15 A's+ Succeeding A's, in the same way B's and C's --> 
        </fo:block>
        </fo:table-cell>
        <fo:table-cell>
        <fo:block height="12pt">Points</fo:block> 
        </fo:table-cell>
        </xsl:if>
    </xfd:table-row-repeat>
</fo:table-body>

Здесь код XSL-FO показан только для одного столбца (для Root / Data / Code =' A '), остальные 2 столбца (' B 'и' C ') состоят изтого же кода.

Подробные условия:

Condition 1): when Root/Data/Code = 'A' or 'B' or 'C'
   i need individual totals of 'A', 'B' and 'C' in Table-Footer individual Column.

Condition 2): inturn if individual count(Root/Data/Code) of 'A', 'B' & 'C' crosses 15.          Then Page flows to 2nd Page then Table-Footer in 2nd Page needs to contains subtotal of first 15 A's + the sum of succeeding A's in the same way for B's And C's

, т. е. если в исходном XML-коде присутствуют 20 A, 10 B и 25 C.

In 1st Page, Table-Footer

SubtotalI(Value of 15 A's)=
SubtotalII(Value 10 B's)=   
SubtotalIII(Value 15 C's)=

In 2nd Page, Table-Footer

SubtotalI(15 A's+ next 5 A's)=   
SubtotalII(Value 10 B's)= <!--No Change as count of B's is less than 15 -->
SubtotalIII(15 C's + next 10 C's)=

Iпытаюсь эту логику, используя xsl: key, группируя через кодовый тег для оценки суммы «A», «B» и «C».Поскольку я новичок в XSLT, мне кажется слишком сложным решить эту логику с помощью xsl: key.Кто-нибудь может помочь в решении этой логики?

Заранее спасибо

1 Ответ

0 голосов
/ 05 января 2012

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

sum(preceding::Value[../Code = 'A'])

Чтобы включить текущее значение, используйте оператор объединения следующим образом:

sum(Value[../Code = 'A'] | preceding::Value[../Code = 'A'])

Более сложная задача - показать разные таблицы «нижний колонтитул» на каждой странице. Заголовки и нижние колонтитулы автоматически повторяются на страницах, но содержимое одинаково для всех страниц, охватываемых таблицей. Единственное решение, которое я вижу, это разбить таблицу самостоятельно, добавляя каждый раз новый нижний колонтитул таблицы.

Безусловно, самый простой способ - просто взять фиксированное количество элементов данных за раз и отобразить их в отдельной таблице. Вы можете циклически проходить по типам A, B и C по одному для каждого, давая каждому значению отдельную строку. Таким образом, таблица всегда имеет одинаковое количество строк. Вы можете поэкспериментировать с числом, которое вы можете включить, чтобы определить, сколько помещается на одной странице.

Следующий код возвращает таблицу с первыми 10 значениями данных. Значения A, B и C расположены прямо друг под другом, но вы можете расположить их слева, в середине и вправо соответственно, если хотите. Внизу таблицы добавлены три строки с промежуточными итогами для A, B и C.

<?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:template match="/">
        <fo:root>
            <fo:layout-master-set>
                <fo:simple-page-master master-name="global">
                    <fo:region-body/>
                </fo:simple-page-master>
            </fo:layout-master-set>

            <fo:page-sequence master-reference="global">
                <fo:flow flow-name="xsl-region-body">

                    <fo:block>
                        <fo:table table-layout="fixed" width="150mm" border-style="solid">
                            <fo:table-column column-width="50mm"/>
                            <fo:table-column column-width="50mm"/>
                            <fo:table-column column-width="50mm"/>

                            <fo:table-body font-size="7pt">
                                <xsl:for-each select="/Root/Data[10 >= position()]">
                                    <fo:table-row border-style="solid">
                                        <fo:table-cell> 
                                            <fo:block height="12pt">
                                                <xsl:value-of select="Code" />
                                            </fo:block> 
                                        </fo:table-cell> 
                                        <fo:table-cell>
                                            <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                <xsl:value-of select="Value" />  
                                            </fo:block> 
                                        </fo:table-cell> 
                                        <fo:table-cell> 
                                            <fo:block height="12pt">Points</fo:block>  
                                        </fo:table-cell> 
                                    </fo:table-row>

                                    <xsl:if test="position() = last()">
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal A</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'A'] | Value[../Code = 'A'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal B</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'B'] | Value[../Code = 'B'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                        <fo:table-row border-style="solid">
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Subtotal C</fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell>
                                                <fo:block height="12pt" border="0.1pt solid black" text-align="center"> 
                                                    <xsl:value-of select="sum(preceding::Value[../Code = 'C'] | Value[../Code = 'C'])" />  
                                                </fo:block> 
                                            </fo:table-cell> 
                                            <fo:table-cell> 
                                                <fo:block height="12pt">Points</fo:block>  
                                            </fo:table-cell> 
                                        </fo:table-row>
                                    </xsl:if>
                                </xsl:for-each>
                            </fo:table-body>
                        </fo:table>
                    </fo:block>

                </fo:flow>
            </fo:page-sequence>

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

</xsl:stylesheet>

Вам все еще нужно что-то определить, сколько таблиц из n элементов данных вам потребуется, а затем выполнить несколько рекурсивных вызовов, чтобы вывести их все. Надеюсь, на данный момент этого достаточно, чтобы вы снова пошли!

PS: я заметил, что вы используете префикс xfd. Похоже, вы работаете с XF Designer от Ecrion. Я не очень знаком с этим. Приведенный выше код представляет собой простое решение XSLT 1.0. Не уверен, что он работает в XF Designer, пожалуйста, дайте мне знать ..

...