XSLT мюнхенская сортировка

Я пытаюсь лучше понять мюнхенскую группировку. Я ограничен XSL 1.0. Я был в состоянии сделать группировку по атрибутам, но я не могу заставить работать группировку по значению элемента.

Мой XML выглядит так:

<?xml version="1.0"?>
<orders>
    <order date="2015-01-01">
        <product amount="8">Apple</product>
        <product amount="1">Pear</product>
    </order>
    <order date="2015-01-01">
        <product amount="1">Plum</product>
        <product amount="5">Pear</product>
    </order>
    <order id="01" date="2015-01-03">
        <product amount="10">Pear</product>
        <product amount="4">Plum</product>
    </order>
</orders>

Я пытаюсь создать диаграмму SVG, которая показывает, сколько было заказано каждого фрукта. Таким образом, можно легко увидеть, какой фрукт является самым продаваемым в каждом примере. Это будет выглядеть следующим образом (ЗАМЕТИТЕ, что количество чисел не похоже на приведенный выше XML):

диаграмма: группа по продукту

Код, который я придумал, следующий:

<xsl:stylesheet version="1.0" 
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:svg="http://www.w3.org/2000/svg" >


<xsl:variable name="baseline" select="480"/> 

<xsl:key name="group-by-product" match="product" use="." />

<xsl:template match="/orders">
    <svg:svg > 
        <svg:g>
            <xsl:apply-templates select="order/product[generate-id(.)=generate-id(key('group-by-product',.)[1])]" />

            <!-- draw x- axis and y - axis -->
            <svg:path style="stroke-width:2; stroke:black" >
                <xsl:attribute name="d">
                    <xsl:text>M 40 100 L 40 </xsl:text>
                    <xsl:value-of select="480"/>
                    <xsl:text> L </xsl:text>
                    <xsl:value-of select="2* count(order) * 40 + 80" />
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="$baseline"/>
                    <xsl:text> L 40 </xsl:text>                 
                    <xsl:value-of select="$baseline"/>
                    <xsl:text> Z</xsl:text>
                </xsl:attribute>
            </svg:path>
        </svg:g>
    </svg:svg>
</xsl:template>

<xsl:template match="order">
    <xsl:variable name="y" select="sum(key('order-by-product',product)/@amount)"/>
    <svg:rect x="{40 * position()+20}" y="{$baseline - $y}" width="30" height="{$y}" style="fill:blue"/>
    <svg:text style="writing-mode:tb" x="{41 * position()+20}" y="{$baseline - $y - 10}">
        <xsl:value-of select="$y" />   
    </svg:text>
    <svg:text style="writing-mode:tb" x="{41 * position()+15}" y="{$baseline + 20}">
        <xsl:value-of select="product" />   
    </svg:text>                        
</xsl:template>
</xsl:stylesheet>

Я чувствую, что у меня есть некоторые несоответствия в моем коде, и я запутался во всех различных примерах, которые я уже рассмотрел. Если возможно, я бы хотел избежать "для каждого" и использовать вместо этого "применить-шаблон".

Спасибо за помощь!

1 ответ

Решение

Вы правильно поняли логику мюнхенской группировки, но шаблон неверен - ваш apply-templates выбирает product элементы:

<xsl:apply-templates select="order/product[generate-id(.)=generate-id(key('group-by-product',.)[1])]" />

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

<xsl:template match="product">
    <xsl:variable name="y" select="sum(key('order-by-product',.)/@amount)"/>
    <svg:rect x="{40 * position()+20}" y="{$baseline - $y}" width="30" height="{$y}" style="fill:blue"/>
    <svg:text style="writing-mode:tb" x="{41 * position()+20}" y="{$baseline - $y - 10}">
        <xsl:value-of select="$y" />   
    </svg:text>
    <svg:text style="writing-mode:tb" x="{41 * position()+15}" y="{$baseline + 20}">
        <xsl:value-of select="." />   
    </svg:text>                        
</xsl:template>
Другие вопросы по тегам