我需要通过xsl将xml属性中的值转换为svg rect pos x和y
因此需要从进行解析
示例
<item value="20 10 40" />
<item value="200 0 100" />
<item value="2666 10 40 95" />
按照一些规则解析每个项目值属性(这是我不确定的部分,如何将数字提取到单独的变量中)
像
<item value="20 10 40" />
X Z Y
提取var1中的X(20)和var2 中的Y(40)
进入
<rect x="{$var1}" y="{$var2}" />
(如果在这种情况下我想要第一个和第三个值)
基本上,我需要了解如何解析属性VALUE中包含的一系列多个值中的任意两个,并将它们分别作为var1和var2传递到rect vars中。
从我迄今为止的研究来看,我已经找到了2种方法,但不确定如何在这种情况下应用,无论是前后子串还是标记化,请注意,这需要直接在浏览器中加载。
第1版
到目前为止,我发现了一个丑陋的解决方案来提取3个数字的数据
Xml
<item value="20 10 40" />
Xsl
Value 1 <xsl:value-of select="substring-before (@value, ' ')"/>
Value 2 <xsl:value-of select="substring-before(substring-after (@value, ' '), ' ')"/>
Value 3 <xsl:value-of select="substring-after(substring-after (@value, ' '), ' ')"/>
结果
Value 1 20
Value 2 10
Value 3 40
因此,寻找更干净的东西,也许是递归的,可以接受字符串中的任意数量的数字并解析所有数字。
在XSLT1.0中从分隔列表中提取值很困难,因为它没有tokenize()
函数。
如果列表中的值数量较少(如您的示例中所示),则可以使用嵌套的substring-before()
和substring-after()
调用,如您的问题中所示(现在)。
更通用的解决方案也更适合处理较大的列表,它将使用递归命名模板,例如:
<xsl:template name="get-Nth-value">
<xsl:param name="list"/>
<xsl:param name="N"/>
<xsl:param name="delimiter" select="' '"/>
<xsl:choose>
<xsl:when test="$N = 1">
<xsl:value-of select="substring-before(concat($list, $delimiter), $delimiter)"/>
</xsl:when>
<xsl:when test="contains($list, $delimiter) and $N > 1">
<!-- recursive call -->
<xsl:call-template name="get-Nth-value">
<xsl:with-param name="list" select="substring-after($list, $delimiter)"/>
<xsl:with-param name="N" select="$N - 1"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
呼叫示例:
<xsl:template match="item">
<rect>
<xsl:attribute name="x">
<xsl:call-template name="get-Nth-value">
<xsl:with-param name="list" select="@value"/>
<xsl:with-param name="N" select="1"/>
</xsl:call-template>
</xsl:attribute>
<xsl:attribute name="y">
<xsl:call-template name="get-Nth-value">
<xsl:with-param name="list" select="@value"/>
<xsl:with-param name="N" select="2"/>
</xsl:call-template>
</xsl:attribute>
</rect>
</xsl:template>
演示:http://xsltransform.net/ncdD7mh
下面是一个使用EXSLT扩展的示例,在线http://xsltransform.net/bnnZW2,代码为
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exsl="http://exslt.org/common" xmlns:str="http://exslt.org/strings" exclude-result-prefixes="exsl str">
<xsl:include href="http://exslt.org/str/functions/tokenize/str.tokenize.template.xsl"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:variable name="tokens-rtf">
<xsl:call-template name="str:tokenize">
<xsl:with-param name="string" select="@value"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="tokens" select="exsl:node-set($tokens-rtf)/token"/>
<x>
<xsl:value-of select="$tokens[1]"/>
</x>
<y>
<xsl:value-of select="$tokens[2]"/>
</y>
</xsl:copy>
</xsl:template>
</xsl:transform>
输入是
<root>
<item value="20 10 40" />
<item value="200 0 100" />
<item value="2666 10 40 95" />
</root>
输出是
<root>
<item><x>20</x><y>10</y></item>
<item><x>200</x><y>0</y></item>
<item><x>2666</x><y>10</y></item>
</root>
应该清楚如何通过位置访问其他代币,当然你也可以通过$tokens
访问for-each
或apply-templates
。
请注意,浏览器中的XSLT处理器可能不允许您从其他域导入或包含样式表模块,因此您需要确保将引用的样式表模块(str.tokenize.template.xsl
)放在自己的服务器上,并从那里引用它。