鉴于
<root>
<item>
<detail>100</detail>
<detail>200</detail>
</item>
<item>
<detail>50</detail>
<detail>100</detail>
</item>
</root>
如何将此数据转换为简单的SVG条形图? (没什么好看的,只有四个条形代表数字之间的关系)
这样的事情: (我知道这两个项目之间没有分离,但我只想说我会让它们变成不同的颜色,前两个条形蓝色是第二个红色)
我想我不确定xsl:template中的语法是什么来生成SVG代码?最佳答案被接受!
答案 0 :(得分:13)
这是一个带有更多铃声的例子。口哨:
输入此代码:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
>
<xsl:output indent="yes" cdata-section-elements="style" />
<xsl:param name="width" select="40" /><!-- width of bars -->
<xsl:param name="space" select="10" /><!-- space between bars and items -->
<xsl:variable name="max-y" select="//detail[not(//detail > .)][1]" />
<xsl:template match="root">
<svg>
<defs>
<style type="text/css"><![CDATA[
g.bar text {
font-family: Arial;
text-anchor: middle;
fill: white;
}
g.bar rect {
fill: black;
}
]]></style>
</defs>
<g transform="translate(10, 10)">
<xsl:apply-templates select="item" />
</g>
</svg>
</xsl:template>
<xsl:template match="item">
<xsl:variable name="prev-item" select="preceding-sibling::item" />
<g class="item" id="item-{position()}" transform="translate({
count($prev-item/detail) * ($width + $space)
+ count($prev-item) * $space
})">
<xsl:apply-templates select="detail" />
</g>
</xsl:template>
<xsl:template match="detail">
<xsl:variable name="idx" select="count(preceding-sibling::detail)" />
<xsl:variable name="pos" select="$idx * ($width + $space)" />
<g class="bar">
<rect x="{$pos}" y="{$max-y - .}" height="{.}" width="{$width}" />
<text x="{$pos + $width div 2.0}" y="{$max-y - $space}">
<xsl:value-of select="."/>
</text>
</g>
</xsl:template>
</xsl:stylesheet>
产生
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<style type="text/css"><![CDATA[
g.bar text {
font-family: Arial;
text-anchor: middle;
fill: white;
}
g.bar rect {
fill: black;
}
]]></style>
</defs>
<g transform="translate(10, 10)">
<g class="item" id="item-1" transform="translate(0)">
<g class="bar">
<rect x="0" y="100" height="100" width="40"/>
<text x="20" y="190">100</text>
</g>
<g class="bar">
<rect x="50" y="0" height="200" width="40"/>
<text x="70" y="190">200</text>
</g>
</g>
<g class="item" id="item-2" transform="translate(110)">
<g class="bar">
<rect x="0" y="150" height="50" width="40"/>
<text x="20" y="190">50</text>
</g>
<g class="bar">
<rect x="50" y="100" height="100" width="40"/>
<text x="70" y="190">100</text>
</g>
</g>
</g>
</svg>
,像这样呈现
在我的机器上。
答案 1 :(得分:6)
SVG只是一种特殊的xml,请查看http://www.w3.org/TR/SVG/intro.html
处的参考您从<svg>
标记开始并开始嵌套。
XSL是一个完全不同的世界。我在http://www.carto.net/svg/samples/xslt/#basic使用了一个参考示例并对其进行了修改以使用xml来演示如何将xsl用于嵌套数据。基本上,我只是添加了一个内部for-each循环。
以下是一个示例起点:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="root">
<svg width="200px" height="500px" xmlns="http://www.w3.org/2000/svg">
<g id="bar" transform="translate(0,200)">
<xsl:for-each select="item">
<xsl:variable name="item_position" select="(position()-1) * 100"/>
<xsl:for-each select="detail">
<xsl:variable name="val" select="."/>
<rect x="{$item_position + position()*40}" y="-{$val}" height="{$val}" width="35" style="fill:{@fill};"/>
<text x="{$item_position + position()*40 + 15}" y="-{($val div 2.0) - 5}" style="font-family:arial;text-anchor:middle;baseline-shift:-15;fill:white">
<xsl:value-of select="."/>
</text>
</xsl:for-each>
</xsl:for-each>
</g>
</svg>
</xsl:template>
</xsl:transform>