XSLT 慕尼黑排序
XSLT Muenchian sorting
我正在尝试更好地了解 Muenchian 分组。我仅限于 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>
我觉得我的代码中存在一些不一致之处,并且将自己与我已经看过的所有不同示例混淆了。
如果可能的话,我想避免 "for-each" 并使用 "apply-template" 代替。
感谢您的帮助!
您的 Muenchian 分组逻辑正确,但模板错误 - 您的 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>
我正在尝试更好地了解 Muenchian 分组。我仅限于 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>
我觉得我的代码中存在一些不一致之处,并且将自己与我已经看过的所有不同示例混淆了。 如果可能的话,我想避免 "for-each" 并使用 "apply-template" 代替。
感谢您的帮助!
您的 Muenchian 分组逻辑正确,但模板错误 - 您的 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>