XSL-диапазон чисел

Во-первых, я должен признать, что я новичок в XML, так что простите меня за глупые вопросы.

Моя цель - получить значение $majorGoal.

<xsl:variable name="variable">
  <xsl:value-of select="(../@attribute) * 100 />
</xsl:variable>
<xsl:variable name="minorGoal1">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">25</xsl:when>
    <xsl:when test="$variable &gt;= -2">20</xsl:when>
  <xsl:choose>
</xsl:variable>
<xsl:variable name="minorGoal2">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">40</xsl:when>
    <xsl:when test="$variable &gt;= -2">24</xsl:when>
  <xsl:choose>
</xsl:variable>
<xsl:variable name="minorGoal3">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">55</xsl:when>
    <xsl:when test="$variable &gt;= -2 and &lt; 4">50</xsl:when>
    <xsl:when test="$variable &gt;= 4">50</xsl:when>
  <xsl:choose>
<xsl:variable name="minorGoal4">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">80</xsl:when>
    <xsl:when test="$variable &gt;= -2 and &lt; 4">70</xsl:when>
    <xsl:when test="$variable &gt;= 4">60</xsl:when>
  <xsl:choose>
</xsl:variable>

<!-- I have 10 more similar variables  -->

<xsl:variable name="minorGoal">
<xsl:choose>
  <xsl:when test="$anotherVariable = 30">
    <xsl:value-of select="$minorGoal1"/>
  </xsl:when>
  <xsl:when test="$anotherVariable = 40">
    <xsl:value-of select="$minorGoal2"/>
  </xsl:when>
  <xsl:when test="$anotherVariable = 50">
    <xsl:value-of select="$minorGoal3"/>
  </xsl:when>
  <xsl:when test="$anotherVariable = 60">
    <xsl:value-of select="$minorGoal4"/>
  </xsl:when>

<!-- Another 10 more similar variables  -->

</xsl:choose>
</xsl:variable>

<xsl:variable name="majorGoal">
  <xsl:value-of select="$minorGoal"/>
</xsl:variable>

@attribute относится к исходному XML-файлу. $anotherVariable определяется как глобальная переменная в том же файле xsl и является константой.

Проблема в том, что парсер возвращает ошибку:

Ожидаемое выражение. $переменная >= -2 и -->‹‹-- 4

Я могу предположить, что проблема вызвана:

<xsl:when test="$variable &gt;= -2 and &lt; 4">50</xsl:when>

а как еще описать диапазон чисел?


person Netop    schedule 27.01.2014    source источник


Ответы (3)


Как уже объяснил Матиас, чтобы проверить, находится ли переменная в диапазоне от -2 до 4, вам нужно сделать:

 test="$variable &gt;= -2 and $variable &lt; 4"

Однако идея с choose заключается в том, что первый тест, возвращающий true, завершает процесс и возвращает соответствующий результат. Это означает, что вместо:

<xsl:variable name="minorGoal4">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">80</xsl:when>
    <xsl:when test="$variable &gt;= -2 and $variable &lt; 4">70</xsl:when>
    <xsl:when test="$variable &gt;= 4">60</xsl:when>
  <xsl:choose>
</xsl:variable>

можно написать просто:

<xsl:variable name="minorGoal4">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">80</xsl:when>
    <xsl:when test="$variable &lt; 4">70</xsl:when>
    <xsl:otherwise>60</xsl:otherwise>
  <xsl:choose>
</xsl:variable>

который и легче читать, и более эффективно выполнять.

person michael.hor257k    schedule 27.01.2014

Вам действительно нужно пометить вопросы XSLT как XSLT 1.0 или 2.0, так как ответы очень часто отличаются.

В XSLT 2.0 вы можете сказать

test="$var = (25 to 40)"

хотя это предъявляет некоторые требования к оптимизатору, поэтому

test="$var ge 25 and $var le 40"

может быть безопаснее.

Также в XSLT 2.0 вы можете упростить это

<xsl:variable name="minorGoal4">
  <xsl:choose>
    <xsl:when test="$variable &lt; -2">80</xsl:when>
    <xsl:when test="$variable &gt;= -2 and $variable &lt; 4">70</xsl:when>
    <xsl:when test="$variable &gt;= 4">60</xsl:when>
  <xsl:choose>
</xsl:variable>

к этому:

<xsl:variable name="minorGoal4" select="
    if ($variable lt -2) then 80
    else if ($variable lt 4) then 70
    else 60"/>

с дополнительным бонусом, что результатом является число, а не фрагмент дерева результатов, что, вероятно, будет намного эффективнее.

person Michael Kay    schedule 27.01.2014

Попробуйте упомянуть $variable в обеих частях И. Также убедитесь, что $variable действительно является числом, а не строкой или нетипизированным атомом.

Кроме того, если вы используете XSLT 2.0, первое выражение можно сократить до ge, что означает «равно или больше».

<xsl:when test="number($variable) ge -2 and number($variable) lt 4">
70
</xsl:when>

Пример, иллюстрирующий это:

Ввод XML

<?xml version="1.0" encoding="utf-8"?>
<root>
   <number>6</number>
   <number>3</number>
</root>

Таблица стилей

<?xml version="1.0" encoding="utf-8"?>

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/root">
      <xsl:copy>
         <xsl:apply-templates/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="number">
      <xsl:copy>
         <xsl:choose>
            <xsl:when test="number(.) ge -2 and number(.) lt 4">
               <xsl:text>YES</xsl:text>
            </xsl:when>
            <xsl:otherwise>
               <xsl:text>NO</xsl:text>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

Вывод

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number>NO</number>
   <number>YES</number>
</root>
person Mathias Müller    schedule 27.01.2014
comment
ОП не сказал, является ли это XSLT 1.0 или 2.0 - ge и lt предназначены только для 2.0, тогда как операторы >= и <, используемые в вопросе, будут работать в обеих версиях. - person Ian Roberts; 27.01.2014
comment
Спасибо Ян, я скажу это явно. - person Mathias Müller; 27.01.2014