为了方便起见,我想以下列方式使用属性@sourcename
:
如果@sourcename
中有一个点,则第一个点之前的部分应分配给$srcgroup
,第一个点之后的部分应分配给$srcword
。
否则$srcgroup
应设置为@sourcename
,$srcword
应为空字符串。
在这两种情况下,我都希望使用$srcgroup
和$srcword
执行相同的操作。
我用以下片段尝试了这个:
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:variable name="srcgroup" select="substring-before(@sourcename, '.')"/>
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="srcgroup" select="@sourcename" />
<xsl:variable name="srcword" />
</xsl:otherwise>
</xsl:choose>
<foo group="{$srcgroup}" word="{$srcword}" />
<!-- there's some other more complicated users of $srcgroup and $srcword -->
问题是我收到错误(这是在Java中使用JAXP):
ERROR: [my xsl file]: line 35: Variable or parameter 'srcgroup' is undefined.'
FATAL ERROR: 'Could not compile stylesheet'
Exception in thread "main" javax.xml.transform.TransformerConfigurationException: Could not compile stylesheet
at com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.newTemplates(TransformerFactoryImpl.java:825)
如果我理解这一点,我猜测变量只包含<xsl:choose>
块中特定情况的范围。有没有办法解决这个问题?我不想两次重复我的其他代码。
P.S。我找到了一个解决方法:
<xsl:variable name="srcgroup" select="substring-before(concat(@sourcename, '.'), '.')" />
<xsl:variable name="srcword" select="substring-after(@sourcename, '.')" />
但我仍然想知道如何解决我原来的问题,以备将来参考。
答案 0 :(得分:5)
更像这样:
<xsl:variable name="srcgroup">
<xsl:choose...>
...
</xsl:choose>
</xsl:variable>
答案 1 :(得分:5)
只需使用(无需条件限制):
<xsl:variable name="srcgroup" select=
"substring-before(concat(@sourcename, '.'), '.')"/>
<xsl:variable name="srcword" select=
"substring-after(@sourcename, '.')"/>
完整示例:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x|y">
<xsl:variable name="srcgroup" select=
"substring-before(concat(@sourcename, '.'), '.')"/>
<xsl:variable name="srcword" select=
"substring-after(@sourcename, '.')"/>
$srcgroup = "<xsl:value-of select="$srcgroup"/>"
$srcword = "<xsl:value-of select="$srcword"/>"
</xsl:template>
</xsl:stylesheet>
应用于此XML文档时:
<t>
<x sourcename="a.b.c"/>
<y sourcename="noDots"/>
</t>
在两种情况下都会产生想要的结果:
$srcgroup = "a"
$srcword = "b.c"
$srcgroup = "noDots"
$srcword = ""
解释:通过放置 sentinel 来避免不必要的逻辑。
将此与更详细的条件语法进行比较:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="x|y">
<xsl:variable name="srcgroup">
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:value-of select="substring-before(@sourcename, '.')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@sourcename"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="srcword">
<xsl:choose>
<xsl:when test="contains(@sourcename, '.')">
<xsl:value-of select="substring-after(@sourcename, '.')"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:variable>
$srcgroup = "<xsl:value-of select="$srcgroup"/>"
$srcword = "<xsl:value-of select="$srcword"/>"
</xsl:template>
</xsl:stylesheet>
当对同一个XML文档(上面)应用这种更详细的转换时,再次生成相同的正确结果:
$srcgroup = "a"
$srcword = "b.c"
$srcgroup = "noDots"
$srcword = ""