【问题标题】:XSLT: Combining Muenchian grouping with SVG bar chartXSLT:将 Muenchian 分组与 SVG 条形图相结合
【发布时间】:2015-02-18 19:16:50
【问题描述】:

我正在尝试创建一个显示每日销售额的 SVG 条形图。这意味着下面的 xml 数据必须按属性“日期”分组。由于我必须使用 XSLT 1.0,我必须进行“Muenchian 分组”或其他一些变通方法。

<orders>
    <order id="01" date="2015-01-01">
        <product price="20">Apple</product>
        <product price="5">Pear</product>
    </order>
    <order id="02" date="2015-01-01">
        <product price="20">Pear</product>
        <product price="40">Plum</product>
    </order>
</orders>

我能够在不对条目进行分组的情况下绘制 SVG 条形图。所以绘图部分不是问题。 Stackoverflow 上有很多 Muenchian 分组示例,但我无法使其正常工作。谢谢您的帮助。

XSL:

<xsl:variable name="baseline" select="480"/> 
<xsl:key name="order-by-date" match="order" use="@date" />
<xsl:template match="orders">
    <svg:svg>
        <xsl:apply-templates select="order[generate-id(.)=generate-id(key('order-by-date',@date)[1])]"  />      
    </svg:svg>
</xsl:template>


<xsl:template match="order">    
    <xsl:for-each select="key('order-by-date', @date)">
    <!-- draw the Rectangles (bars) for each group -->
        <xsl:variable name="x-offset" select="40 + position() * 40" />
        <xsl:variable name="y-offset" select="$baseline"/>
        <xsl:variable name="y" select="$y-offset - sum(current()/product/@price)"/>

        <!-- attributes of the rectangle -->

        <svg:path>
            <xsl:attribute name="style">
                <xsl:text>fill:</xsl:text>
                <xsl:value-of select="blue"/>
            </xsl:attribute>

            <xsl:attribute name="d">
                <!-- move to the lower left corner of the rectangle -->
                <xsl:text>M </xsl:text>
                <xsl:value-of select="$x-offset - 10"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$y-offset"/>
                <!-- draw line to the upper left corner of the rectangle -->
                <xsl:text> L </xsl:text>
                <xsl:value-of select="$x-offset - 10"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$y"/>
                <!-- draw line to the upper right corner of the rectangle -->
                <xsl:text> L </xsl:text>
                <xsl:value-of select="$x-offset + 10"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$y"/>
                <!-- draw line to the lower right corner of the rectangle -->
                <xsl:text> L </xsl:text>
                <xsl:value-of select="$x-offset + 10"/>
                <xsl:text> </xsl:text>
                <xsl:value-of select="$y-offset"/>
                <!-- close path and fill the rectangle -->
                <xsl:text> Z</xsl:text>
            </xsl:attribute>
        </svg:path>
        <!-- write Date underneath each bar -->
        <svg:text style="writing-mode:tb" x="{position()*30 + 50}" y="{$baseline + 20}">
            <xsl:value-of select="substring(@datum,9,2)" />
        </svg:text>
    </xsl:for-each>

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

【问题讨论】:

  • 你能在这种情况下显示你期望的输出吗?谢谢!
  • "我正在尝试创建一个显示每日销售额的 SVG 条形图。 在您的示例中,“每日销售额”到底是什么?只是总和当天的所有价格?-- P.S. 如果你想要一个条形图,为什么不使用矩形?

标签: xml xslt svg group-by bar-chart


【解决方案1】:

最好从一个跨越多个日期的示例开始:

XML

<orders>
    <order id="01" date="2015-01-01">
        <product price="20">Apple</product>
        <product price="5">Pear</product>
    </order>
    <order id="02" date="2015-01-01">
        <product price="20">Pear</product>
        <product price="40">Plum</product>
    </order>
    <order id="03" date="2015-01-02">
        <product price="20">Apple</product>
        <product price="40">Plum</product>
    </order>
</orders>

然后您可以按照以下方式构建样式表:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="order-by-date" match="order" use="@date" />

<xsl:template match="/orders">
    <svg version="1.0"> 
        <xsl:apply-templates select="order[generate-id()=generate-id(key('order-by-date',@date)[1])]" />
    </svg>
</xsl:template>

<xsl:template match="order">
    <xsl:variable name="y" select="sum(key('order-by-date',@date)/product/@price)"/>
    <!-- create a svg object here, using the y dimension -->
</xsl:template>

</xsl:stylesheet>

我自己的偏好是使用矩形作为创建对象,例如:

<rect x="{40 * position()}" width="30" height="{$y}"/>

另请参阅: Using XSLT to create SVG

【讨论】:

  • 嗨,迈克尔。感谢您的帮助!这正是我想要实现的目标。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 2021-11-04
  • 2014-03-19
  • 1970-01-01
  • 1970-01-01
  • 2021-11-20
相关资源
最近更新 更多