xslt: назначение переменных, равных одному из двух случаев
Я хочу использовать атрибут @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 -->
проблема в том, что я получаю ошибку (это использование JAXP в Java):
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, '.')" />
но я все еще хочу знать, как решить мою оригинал вопрос, на будущее.
2 ответов
просто использовать (никаких условий не требуется):
<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 = ""
объяснение: ненужная логика избегается путем размещения страж.
сравните это с гораздо более подробным условным синтаксис:
<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 = ""
Это больше похоже на это:
<xsl:variable name="srcgroup">
<xsl:choose...>
...
</xsl:choose>
</xsl:variable>