我正在尝试创建一个SVG条形图,其中显示每日销售额。这意味着下面的xml数据必须按属性“date”分组。由于我必须使用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>
答案 0 :(得分: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}"/>