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 для представления отсутствующего значения или неверного состояния. Эта тема посвящена некоторым деталям по этой теме.