XSLT 1.0 Group and Sum Items - Получить список элементов комнаты на уровень - PullRequest
0 голосов
/ 26 июня 2018

На каждом уровне есть список комнат.
В каждой комнате есть список экземпляров.
В экземпляре есть ссылка на статью и ее количество в комнате.
В статье есть код истоимость.

Как получить список статей, сгруппированных по коду для суммирования количества / стоимости, для каждого уровня?

XML:

<planning>
<articles>
    <article id="1" code="C12" name="chair" cost="20"/>
    <article id="2" code="T1" name="table" cost="31"/>
    <article id="3" code="L10" name="lamp" cost="10"/>
    <article id="4" code="TA2" name="tap" cost="5"/>
    <article id="5" code="B20" name="bed" cost="12"/>
</articles>
<rooms>
    <room id="1" name="A1">
        <occurrence-list>
            <occurrence id="1" article-ref="1" qty="3"/>
            <occurrence id="2" article-ref="4" qty="2"/>
            <occurrence id="3" article-ref="5" qty="4"/>
        </occurrence-list>
    </room>
    <room id="2" name="A2">
        <occurrence-list>
            <occurrence id="4" article-ref="1" qty="2"/>
            <occurrence id="5" article-ref="2" qty="3"/>
        </occurrence-list>
    </room>
    <room id="3" name="B1">
        <occurrence-list>
            <occurrence id="6" article-ref="1" qty="1"/>
            <occurrence id="7" article-ref="3" qty="2"/>
            <occurrence id="8" article-ref="4" qty="4"/>
        </occurrence-list>
    </room>
    <room id="4" name="B2">
        <occurrence-list>
            <occurrence id="9" article-ref="2" qty="2"/>
            <occurrence id="10" article-ref="5" qty="5"/>
        </occurrence-list>
    </room>
    <room id="5" name="C1">
        <occurrence-list>
            <occurrence id="10" article-ref="1" qty="2"/>
            <occurrence id="11" article-ref="3" qty="2"/>
            <occurrence id="12" article-ref="4" qty="1"/>
        </occurrence-list>
    </room>
</rooms>
<level id="1" name="Level 1">
    <level-room room-ref="1"/>
    <level-room room-ref="3"/>
    <level-room room-ref="5"/>
</level>
<level id="2" name="Level 2">
    <level-room room-ref="2"/>
    <level-room room-ref="4"/>
</level>

Пока это мой XSL:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" encoding="utf-8" indent="no"/>
<xsl:key name="articles" match="article" use="@id"/>
<xsl:key name="room" match="room" use="@id"/>
<xsl:key name="room-occurrences" match="occurrence" use="../../@id"/>
<xsl:key name="level-rooms" match="level-room" use="../@id"/>
<xsl:template match="/">
    <html>
        <body>
            <h2>Items per level</h2>
            <table border="1">
                    <tr>
                        <td>Level</td>
                        <td>Article</td>
                        <td>Cost</td>
                        <td>Qty</td>
                        <td>Total</td>
                    </tr>
                <xsl:for-each select="/planning/level">
                    <tr>
                        <td><xsl:value-of select="@name"/></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>
                  <xsl:for-each select="key('room-occurrences', key('level-rooms', @id)/@room-ref)">
                    <xsl:sort select="key('articles', @article-ref)/@code" order="ascending"/>
                    <tr>  
                      <td></td>
                      <td><xsl:value-of select="key('articles', @article-ref)/@code"/></td>
                      <td><xsl:value-of select="key('articles', @article-ref)/@cost"/></td>
                      <td><xsl:value-of select="@qty"/></td>
                      <td><xsl:value-of select="@qty * key('articles', @article-ref)/@cost"/></td>
                    </tr>  
                   </xsl:for-each>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

И вот такой HTML-код, который я получаю:

+---------+------+-----+-------+  
| Article | Cost | Qty | Total |  
+---------+------+-----+-------+  
| Level 1                      |  
+------------------------------+  
| B20     | 12   | 4   | 48    |  
+---------+------+-----+-------+  
| C12     | 20   | 3   | 60    |  
+---------+------+-----+-------+  
| C12     | 20   | 1   | 20    |  
+---------+------+-----+-------+  
| C12     | 20   | 2   | 40    |  
+---------+------+-----+-------+  
| L10     | 10   | 2   | 20    |  
+---------+------+-----+-------+  
| L10     | 10   | 2   | 20    |  
+---------+------+-----+-------+  
| TA2     | 5    | 2   | 10    |  
+---------+------+-----+-------+  
| TA2     | 5    | 4   | 20    |  
+---------+------+-----+-------+  
| TA2     | 5    | 1   | 5     |  
+---------+------+-----+-------+  
| Level 2                      |  
+------------------------------+  
| B20     | 12   | 5   | 60    |  
+---------+------+-----+-------+  
| C12     | 20   | 2   | 40    |  
+---------+------+-----+-------+  
| T1      | 31   | 3   | 93    |  
+---------+------+-----+-------+  
| T1      | 31   | 2   | 62    |  
+---------+------+-----+-------+  

Но я бы хотел получитьстатьи, сгруппированные по коду, как показано ниже:

+---------+------+-----+-------+  
| Article | Cost | Qty | Total |  
+---------+------+-----+-------+  
| Level 1                      |  
+------------------------------+  
| B20     | 12   | 4   | 48    |
+---------+------+-----+-------+
| C12     | 20   | 6   | 120   |
+---------+------+-----+-------+
| L10     | 10   | 4   | 40    |
+---------+------+-----+-------+
| TA2     | 5    | 7   | 35    |
+---------+------+-----+-------+
| Level 2                      |
+------------------------------+
| B20     | 12   | 5   | 60    |
+---------+------+-----+-------+
| C12     | 20   | 2   | 40    |
+---------+------+-----+-------+
| T1      | 31   | 5   | 155   |
+---------+------+-----+-------+

1 Ответ

0 голосов
/ 26 июня 2018

Поскольку у вас есть отдельные элементы article, я думаю, что один из способов - просто выбрать их с помощью ключей, которые вы установили (хотя я немного сократил это, просто используя дочерние элементы, где это возможно), а затем обработать ссылочные элементы.article, оглядываясь назад на сумму величин:

<xsl:key name="articles" match="article" use="@id"/>
<xsl:key name="room" match="room" use="@id"/>

<xsl:template match="/">
    <html>
        <body>
            <h2>Items per level</h2>
            <table border="1">
                    <tr>
                        <td>Level</td>
                        <td>Article</td>
                        <td>Cost</td>
                        <td>Qty</td>
                        <td>Total</td>
                    </tr>
                <xsl:for-each select="/planning/level">
                    <tr>
                        <td><xsl:value-of select="@name"/></td>
                        <td></td>
                        <td></td>
                        <td></td>
                        <td></td>
                    </tr>

                  <xsl:variable name="level-occs" select="key('room', level-room/@room-ref)/occurrence-list/occurrence"/>
                  <xsl:for-each select="key('articles', $level-occs/@article-ref)">
                    <xsl:sort select="@code" order="ascending"/>
                    <xsl:variable name="qty" select="sum($level-occs[@article-ref = current()/@id]/@qty)"/>
                    <tr>  
                      <td></td>
                      <td><xsl:value-of select="@code"/></td>
                      <td><xsl:value-of select="@cost"/></td>
                      <td><xsl:value-of select="$qty"/></td>
                      <td><xsl:value-of select="$qty * @cost"/></td>
                    </tr>  
                   </xsl:for-each>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>

https://xsltfiddle.liberty -development.net / 6qVRKwc / 2

...