xslt: присваивание переменных, равных одному из двух случаев - PullRequest
6 голосов
/ 31 января 2012

Я хочу использовать атрибут @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 ]

5 голосов
/ 31 января 2012

Просто используйте (без условий):

  <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 = ""
5 голосов
/ 31 января 2012

Это больше похоже на:

<xsl:variable name="srcgroup">
 <xsl:choose...>
  ...
 </xsl:choose>
</xsl:variable>
...