Intershop: проверка на ненулевое значение в шаблоне.isml

Я не нахожу функцию для проверки существования значения в коде шаблона ISML. Есть isDefined, но не isNull.

isDefined возвращает true для нулевых значений:

      <isset name="woot" value="" scope="request">

       <isif condition="#isDefined(woot)#">
           <h1>woot</h1>
       </isif>

Сейчас я использую:

 <isif condition="#woot EQ null#">

или же

 <isif condition="#woot EQ ''#">

Я не знаю, будет ли это работать для логических значений.

1 ответ

Решение

isDefined - это способ проверки нулевого значения. В AbstractTemplate у вас есть метод isDefined(Object anObject), который вызывается. Проверьте скомпилированные версии jsp и java вашего шаблона isml.

В AbstractTemplate

public Boolean isDefined(Object anObject){
    ...
    return anObject != null ? Boolean.TRUE : Boolean.FALSE;
}

Код в вашем примере немного вводит в заблуждение, он фактически не проверяет нулевую ссылку. Потерпите меня.

Первое утверждение:

<isset name="woot" value="" scope="request">

Компилируется в:

Object temp_obj = (""); 
getPipelineDictionary().put("woot", temp_obj);

Это просто устанавливает переменную woot в пустую строку. Если вы добавите следующий скриптлет в свой isml, вы увидите, что он действительно не равен нулю.

Отказ от ответственности: не используйте скриптлеты в производственном коде, это только для демонстрации точки

<%
    Object woot = getPipelineDictionary().get("woot");
    out.print(woot == null); //print false
%>

Вторая линия:

<isif condition="#isDefined(woot)#">

Оценивает, существует ли переменная и существует ли она. Он имеет пустую строку в качестве значения, а не NULL, как вы могли подумать.

Так что же здесь происходит?

<isif condition="#woot EQ null#">

Глядя на скомпилированную версию:

context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue(getObject("null"),null))

context.getFormattedValue(getObject("null"),null) это важный бит здесь. Он пытается получить переменную с именем null, она не существует, поэтому возвращает null. Затем метод getFormattedValue возвращает пустую строку для нулевого аргумента (см. TemplateExecutionConfig::getFormattedValue). Все утверждение тогда становится правдой. Не потому, что woot имеет значение null, а потому, что вы сравниваете его с переменной, которая не существует, поэтому вы случайно оцениваете две пустые строки. Такое поведение согласуется с оператором EQ, поскольку он используется для сравнения строк.

Вы бы получили тот же результат, если бы вы тоже использовали это утверждение.

<isif condition="#woot EQ iDontExistButImAlsoNotNull#"> //true

Третье утверждение сравнивает переменную woot с пустым строковым значением, которое возвращает true.

<isif condition="#woot EQ ''#">

Скомпилированная версия:

context.getFormattedValue(getObject("woot"),null).equals(context.getFormattedValue("",null))

Так что реальная проблема в том, что woot не имеет буквального значения null. Смотрите следующий код:

<isset name="foo" value="#IDontExitPrettySureAboutThat#" scope="request">
<%
    Object foo = getPipelineDictionary().get("foo");
    out.print("foo is null? ");
    out.print(foo == null);
    //prints : foo is null? true
%>
<isif condition="#isDefined(foo)#">
    <h1>foo1</h1> //is never printed
</isif>

Я злоупотребляю тем фактом, что IDontExitPrettySureAboutThat не существует для установки нулевого значения в foo. Затем isDefined начинает работать так, как вы ожидаете. Это происходит до тех пор, пока кто-то не инициализирует мою переменную чем-то отличным от нуля

Однако я бы не стал пропагандировать, что вы используете этот метод. Я думаю, что лучший совет - не использовать null для представления отсутствующего значения или неверного состояния. Эта тема посвящена некоторым деталям по этой теме.

Другие вопросы по тегам