唯一的问题是如何从Listing A 过渡到Figure A ?这个则需要XSLT和XLink。XSLT用于从XML输入产生SVG,而XLink用于单个SVG元素之间产生链接。最终结果是XSL字体报表,显示在Listing B中。
Listing B: XSL 字体报表
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
?<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" doctype-public="text/svg"/>
?<xsl:param name="offsetY" select="10"/>
?<xsl:param name="rectX" select="7"/>
?<xsl:param name="rectY" select="5"/>
?<xsl:param name="rectStroke" select="'black'"/>
?<xsl:param name="rectStrokeWidth" select="1"/>
?<xsl:param name="lineStroke" select="'black'"/>
?<xsl:param name="lineStrokeWidth" select="1"/>
?<xsl:param name="textY" select="16"/>
?<xsl:param name="fontFamily" select="'tahoma'"/>
?<xsl:param name="fontSize" select="10"/>
?<xsl:param name="fontWeight" select="'bold'"/>
?<xsl:template match="/">
?<svg xmlns:svg="http://www.w3.org/2000/svg">
?<xsl:comment>SVG tree generated from XML using tree.xslt</xsl:comment>
<xsl:attribute name="width">100%</xsl:attribute>
<xsl:attribute name="height">100%</xsl:attribute>
<xsl:element name="defs">
<xsl:comment>Shape definition(s)</xsl:comment>
<xsl:call-template name="rect"/>
<xsl:comment>Text definition(s)</xsl:comment>
<xsl:apply-templates mode="text"/>
<xsl:comment>Graphic definition(s)</xsl:comment>
<xsl:apply-templates mode="rect"/>
<xsl:element>
<xsl:element name="g">
<xsl:comment>Graphic reference(s)</xsl:comment>
<xsl:apply-templates select="*" mode="g">
<xsl:with-param name="offsetLeft" select="0"/>
<xsl:with-param name="offsetRight" select="100"/>
<xsl:with-param name="parentX" select="0"/>
<xsl:with-param name="parentY" select="0"/>
</xsl:apply-templates>
</xsl:element>
</svg>
?</xsl:template>
?<xsl:template match="*" mode="text">
?<xsl:apply-templates select="." mode="def_text"/>
?<xsl:if test="count(./child::*) != 0">
?<xsl:apply-templates mode="text"/>
?</xsl:if>
?</xsl:template>
?<xsl:template match="*" mode="rect">
?<xsl:apply-templates select="." mode="def_g"/>
?<xsl:if test="count(./child::*) != 0">
?<xsl:apply-templates mode="rect"/>
?</xsl:if>
?</xsl:template>
?<xsl:template name="rect">
?<xsl:element name="rect">
?<xsl:attribute name="x">0</xsl:attribute>
?<xsl:attribute name="y">0</xsl:attribute>
?<xsl:attribute name="width">
?<xsl:value-of select="concat(string($rectX),'%')"/>
?</xsl:attribute>
?<xsl:attribute name="height">
?<xsl:value-of select="concat(string($rectY),'%')"/>
?lt;/xsl:attribute>
?<xsl:attribute name="rx">5</xsl:attribute>
?<xsl:attribute name="ry">5</xsl:attribute>
?<xsl:attribute name="fill">white</xsl:attribute>
?<xsl:attribute name="stroke">
?<xsl:value-of select="$rectStroke"/>
</xsl:attribute>
?<xsl:attribute name="stroke-width">
?<xsl:value-of select="$rectStrokeWidth"/>
?</xsl:attribute>
?<xsl:attribute name="id">rect</xsl:attribute>
?</xsl:element>
?</xsl:template>
?<xsl:template match="*" mode="def_text">
?<xsl:element name="text">
<xsl:attribute name="font-family">
<xsl:value-of select="$fontFamily"/>
</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$fontSize"/>
</xsl:attribute>
<xsl:attribute name="font-weight">
<xsl:value-of select="$fontWeight"/>
</xsl:attribute>
<xsl:attribute name="style">text-anchor: middle</xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="concat('t',string(generate-id(.)))"/></xsl:attribute>
<xsl:value-of select="name(.)"/>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="def_g">
<xsl:element name="g">
<xsl:attribute name="id"><xsl:value-of select="concat('g',string(generate-id(.)))"/></xsl:attribute>
<xsl:element name="use">
<xsl:attribute name="xlink:href">#rect</xsl:attribute>
<xsl:attribute name="x">0</xsl:attribute>
<xsl:attribute name="y">0</xsl:attribute>
</xsl:element>
<xsl:element name="use">
<xsl:attribute name="xlink:href"><xsl:value-of select="concat('#t',string(generate-id(.)))"/></xsl:attribute>
<xsl:attribute name="x">
<xsl:value-of select="concat(string($rectX div 2),'%')"/>
</xsl:attribute>
<xsl:attribute name="y">
<xsl:value-of select="$textY"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="*" mode="g">
<xsl:param name="offsetLeft"/>
<xsl:param name="offsetRight"/>
<xsl:param name="parentX"/>
<xsl:param name="parentY"/>
<xsl:variable name="width" select="$offsetRight - $offsetLeft"/>
<xsl:variable name="center" select="$width div 2"/>
<xsl:variable name="ancestors" select="count(./ancestor::*)"/>
<xsl:variable name="preceding" select="count(./preceding-sibling::*)"/>
<xsl:variable name="following" select="count(./following-sibling::*)"/>
<xsl:variable name="siblings" select="$preceding + $following + 1"/>
<xsl:variable name="area" select="$width div $siblings"/>
<xsl:variable name="x">
<xsl:choose>
<xsl:when test="$preceding = $following">
<xsl:choose>
<xsl:when test="$parentX = 0">
<xsl:value-of select="$center - $rectX div 2"/>
</xsl:when>
?<xsl:otherwise>
<xsl:value-of select="$parentX"/>
?</xsl:otherwise>
?</xsl:choose>
?</xsl:when>
?<xsl:otherwise>
?<xsl:value-of select="$area * ($preceding + 0.5) + $offsetLeft"/>
?</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="y" select="($ancestors + 1) * $offsetY"/>
<xsl:element name="use">
<xsl:attribute name="xlink:href"><xsl:value-of select="concat('#g',string(generate-id(.)))"/></xsl:attribute>
<xsl:attribute name="x">
?<xsl:value-of select="concat(string($x),'%')"/>
</xsl:attribute>
<xsl:attribute name="y">
?<xsl:value-of select="concat(string($y),'%')"/>
</xsl:attribute>
</xsl:element>
<xsl:call-template name="line">
?<xsl:with-param name="x" select="$x"/>
?<xsl:with-param name="y" select="$y"/>
?<xsl:with-param name="parentX" select="$parentX"/>
?<xsl:with-param name="parentY" select="$parentY"/>
</xsl:call-template>
<xsl:if test="count(./child::*) != 0">
<xsl:apply-templates mode="g">
?<xsl:with-param name="offsetLeft" select="$x - $area div 2"/>
?<xsl:with-param name="offsetRight" select="$x + $area div 2"/>
?<xsl:with-param name="parentX" select="$x"/>
?<xsl:with-param name="parentY" select="$y"/>
</xsl:apply-templates>
</xsl:if>
?</xsl:template>
?<xsl:template name="line">
<xsl:param name="x"/>
<xsl:param name="y"/>
<xsl:param name="parentX"/>
<xsl:param name="parentY"/>
<xsl:if test="($parentX + $parentY) != 0">
<xsl:comment>
?<xsl:value-of select="concat('Line from (',string($parentX),'%,',string($parentY),'%) to (',string($x),'%,',string($y),'%).')"/>
</xsl:comment>
<xsl:element name="line">
?<xsl:attribute name="x1">
?<xsl:value-of select="concat(string($parentX + $rectX div 2),'%')"/>
?</xsl:attribute>
?<xsl:attribute name="y1">
?<xsl:value-of select="concat(string($parentY + $rectY),'%')"/>
?</xsl:attribute>
?<xsl:attribute name="x2">
?<xsl:value-of select="concat(string($x + $rectX div 2),'%')"/>
?</xsl:attribute>
?<xsl:attribute name="y2">
?<xsl:value-of select="concat(string($y),'%')"/>
?</xsl:attribute>
?<xsl:attribute name="stroke">
?<xsl:value-of select="$lineStroke"/>
?</xsl:attribute>
?<xsl:attribute name="stroke-width">
?<xsl:value-of select="$lineStrokeWidth"/>
?</xsl:attribute>
</xsl:element>
</xsl:if>
?</xsl:template>
</xsl:stylesheet>
Listing B中显示了字体报表,有很多用于调整输出的参数。使用这两个文件的转化结果显示于Listing C中
Listing C:SVG结果
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">?<!--SVG tree generated from XML using tree.xslt-->
?<defs> <!--Shape definition(s)-->
<rect x="0" y="0" width="7%" height="5%" rx="5" ry="5" fill="white" stroke="black" stroke-width="1" id="rect"/> ?<!--Text definition(s)-->
<text font-family="tahoma" font-size="10" font-weight="bold" style="text-anchor: middle" id="tidroot46943992">root</text>
<text font-family="tahoma" font-size="10" font-weight="bold" style="text-anchor: middle" id="tidchild64287488">child</text>
<text font-family="tahoma" font-size="10" font-weight="bold" style="text-anchor: middle" id="tidgrandchild47649632">grandchild</text>
<text font-family="tahoma" font-size="10" font-weight="bold" style="text-anchor: middle" id="tidchild47755280">child</text> <!--Graphic definition(s)-->
<g id="gidroot46943992">
<use xlink:href="#rect" x="0" y="0"/>
<use xlink:href="#tidroot46943992" x="3.5%" y="16"/>
</g>
<g id="gidchild64287488">
<use xlink:href="#rect" x="0" y="0"/>
<use xlink:href="#tidchild64287488" x="3.5%" y="16"/>
</g>
<g id="gidgrandchild47649632">
<use xlink:href="#rect" x="0" y="0"/>
<use xlink:href="#tidgrandchild47649632" x="3.5%" y="16"/>
</g>
<g id="gidchild47755280">
<use xlink:href="#rect" x="0" y="0"/>
<use xlink:href="#tidchild47755280" x="3.5%" y="16"/>
</g>
?</defs>
?<g> ?<!--Graphic reference(s)-->
<use xlink:href="#gidroot46943992" x="46.5%" y="10%"/>
<use xlink:href="#gidchild64287488" x="21.5%" y="20%"/>
<!--Line from (46.5%,10%) to (21.5%,20%).-->
<line x1="50%" y1="15%" x2="25%" y2="20%" stroke="black" stroke-width="1"/>
<use xlink:href="#gidgrandchild47649632" x="21.5%" y="30%"/>?<!--Line from (21.5%,20%) to (21.5%,30%).-->
<line x1="25%" y1="25%" x2="25%" y2="30%" stroke="black" stroke-width="1"/>
<use xlink:href="#gidchild47755280" x="71.5%" y="20%"/> <!--Line from (46.5%,10%) to (71.5%,20%).-->
<line x1="50%" y1="15%" x2="75%" y2="20%" stroke="black" stroke-width="1"/>
?</g>
</svg>
极端范围
虽然这是对开发者定位极端范围避免特殊工作的粗略描述,而我却以不同的态度来看待这个问题。我的朋友Dave很喜欢说如果数据被曲解,也终有一天会了解真相的。从我工作的经验来看,这是正确的。
责任编辑:张琎
用户评论