null - Проверьте, является ли строка пустой или пустой в XSLT




xslt-1.0 xslt-2.0 (13)

В некоторых случаях вам может понадобиться знать, когда значение имеет значение null, что особенно необходимо при использовании XML, который был сериализован из объектов .NET. Хотя принятый ответ работает на это, он также возвращает тот же результат, когда строка пуста или пуста, т. Е. '', Поэтому вы не можете различать.

<group>
    <item>
        <id>item 1</id>
        <CategoryName xsi:nil="true" />
    </item>
</group>

Таким образом, вы можете просто проверить атрибут.

<xsl:if test="CategoryName/@xsi:nil='true'">
   Hello World.
</xsl:if>

Иногда необходимо знать точное состояние, и вы не можете просто проверить, было ли создано экземпляр CategoryName, потому что в отличие от Javascript

<xsl:if test="CategoryName">
   Hello World.
</xsl:if>

Вернет true для нулевого элемента.

Как я могу проверить, является ли значение значением null или пустым с помощью XSL ?

Например, если categoryName пуст? Я использую при выборе конструкции.

Например:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

test="categoryName != ''"

Edit : Это, по-моему, относится к наиболее вероятной интерпретации «[не] нулевой или пустой», как это было сделано из вопроса, включая его псевдокод и мой собственный ранний опыт работы с XSLT. Т.е. «Что эквивалентно следующей Java?»:

!(categoryName == null || categoryName.equals(""))

Для более подробной информации, например, с явным определением нулевого и пустого, см . Ответ johnvey ниже и / или скрипт XSLT, который я адаптировал из этого ответа, который включает в себя комментарий Майкла Кэя, а также шестую возможную интерпретацию.


При отсутствии какой-либо другой информации я возьму следующий XML:

<group>
    <item>
        <id>item 1</id>
        <CategoryName>blue</CategoryName>
    </item>
    <item>
        <id>item 2</id>
        <CategoryName></CategoryName>
    </item>
    <item>
        <id>item 3</id>
    </item>
    ...
</group>

Пример использования будет выглядеть так:

<xsl:for-each select="/group/item">
    <xsl:if test="CategoryName">
        <!-- will be instantiated for item #1 and item #2 -->
    </xsl:if>
    <xsl:if test="not(CategoryName)">
        <!-- will be instantiated for item #3 -->
    </xsl:if>
    <xsl:if test="CategoryName != ''">
        <!-- will be instantiated for item #1 -->
    </xsl:if>
    <xsl:if test="CategoryName = ''">
        <!-- will be instantiated for item #2 -->
    </xsl:if>
</xsl:for-each>

Если у узла нет значения, доступного во входном xml, как показано ниже xpath,

<node>
    <ErrorCode/>
</node>

Функция string () преобразуется в пустое значение. Так что это прекрасно работает:

string(/Node/ErrorCode) =''

Если существует вероятность того, что элемент не существует в XML, я бы проверил, что этот элемент присутствует, и длина строки больше нуля:

<xsl:choose>
    <xsl:when test="categoryName and string-length(categoryName) &gt; 0">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

Как насчет?

test="not(normalize-space(categoryName)='')"

Первые две имеют нулевое значение, а во втором - дело с пустой строкой.

<xsl:if test="USER/FIRSTNAME">
    USERNAME is not null
</xsl:if>
<xsl:if test="not(USER/FIRSTNAME)">
    USERNAME is null
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME=''">
     USERNAME is empty string
 </xsl:if>
 <xsl:if test="USER/FIRSTNAME!=''">
     USERNAME is not empty string
 </xsl:if>

По моему опыту, лучший способ:

<xsl:when test="not(string(categoryName))">
    <xsl:value-of select="other" />
</xsl:when>
<otherwise>
    <xsl:value-of select="categoryName" />
</otherwise>

Я знаю, что этот вопрос устарел, но между всеми ответами я пропустил один из них, который является общим подходом к этому варианту использования в XSLT-разработке.

Я представляю, что недостающий код из ОП выглядит примерно так:

<xsl:template match="category">
    <xsl:choose>
        <xsl:when test="categoryName !=null">
            <xsl:value-of select="categoryName " />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="other" />
        </xsl:otherwise>
    </xsl:choose>
</category>

И что вход выглядит примерно так:

<categories>
    <category>
       <categoryName>Books</categoryName>
    </category>
    <category>
       <categoryName>Magazines</categoryName>
       <categoryName>Periodicals</categoryName>
       <categoryName>Journals</categoryName>
    </category>
    <category>
        <categoryName><!-- please fill in category --></categoryName>
    </category>
    <category>
        <categoryName />
    </category>
    <category />
</categories>

Т.е. я предполагаю, что могут быть нулевые, пустые, одиночные или несколько элементов categoryName . Чтобы справиться со всеми этими случаями, используя xsl:choose select -style constructs, или, другими словами, настоятельно, быстро становится беспорядочным (тем более, если элементы могут быть на разных уровнях!). Типичная идиома программирования в XSLT использует шаблоны (следовательно, T в XSLT), который является декларативным программированием, а не императивным (вы не говорите процессору, что делать, вы просто говорите, что вы хотите выводить, если выполняются определенные условия). Для этого прецедента, который может выглядеть примерно так:

<!-- positive test, any category with a valid categoryName -->
<xsl:template match="category[categoryName[text()]]">
    <xsl:apply-templates />
</xsl:template>

<!-- any other category (without categoryName, "null", with comments etc) -->
<xsl:template match="category">
    <xsl:text>Category: Other</xsl:text>
</xsl:template>

<!-- matching the categoryName itself for easy handling of multiple names -->
<xsl:template match="categoryName">
    <xsl:text>Category: </xsl:text>
    <xsl:value-of select="." />
</xsl:template>

Это работает (с любой версией XSLT), потому что первый из них имеет более высокий приоритет (у него есть предикат). Шаблон сопоставления «провал», второй, позволяет получить недопустимое значение. Третья задача позаботится о правильном выводе значения categoryName .

Обратите внимание: в этом случае нет необходимости специфицировать categories или category , потому что процессор будет автоматически обрабатывать все дочерние элементы, если мы не скажем об этом иначе (в этом примере второй и третий шаблоны не обрабатывают детей далее, поскольку no xsl:apply-templates в них).

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

Примечание: в XML нет такой вещи, как null . Существует xsi:nil , но это редко используется, особенно редко в нетипизированных сценариях без какой-либо схемы.


Из пустого элемента :

Чтобы проверить, пусто ли значение определенного узла

Это зависит от того, что вы подразумеваете под пустым.

  • Не содержит дочерних узлов: not(node())
  • Не содержит текстового содержимого: not(string(.))
  • Не содержит текст, кроме пробела: not(normalize-space(.))
  • Не содержит ничего, кроме комментариев: not(node()[not(self::comment())])

Я на самом деле нашел, что лучше просто тестировать длину строки, так как много раз это поле не пустое, просто пустое

<xsl: when test = "длина строки (поле-вы-хотите-тест) <1">


Как я могу проверить, является ли значение значением null или пустым с помощью XSL?

Например, если categoryName пуст?

Это, вероятно, самое простое выражение XPath (тот, в принятом ответе, дает тест на противоположность и будет длиннее, если будет отрицаться):

not(string(categoryName))

Объяснение :

Аргумент функции not() приведенной выше, является false() , когда нет дочернего элемента categoryName ("null") элемента контекста, или дочернего ( categoryName ) этого типа categoryName имеет строковое значение - пустую строку.

Я использую при выборе конструкции.

Например:

<xsl:choose>
    <xsl:when test="categoryName !=null">
        <xsl:value-of select="categoryName " />
    </xsl:when>
    <xsl:otherwise>
        <xsl:value-of select="other" />
    </xsl:otherwise>
</xsl:choose>

В XSLT 2.0 используйте :

<xsl:copy-of select="concat(categoryName,  $vOther[not(string(current()/categoryName))])"/>

Вот полный пример :

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vOther" select="'Other'"/>

 <xsl:template match="/">
  <xsl:copy-of select="concat(categoryName,$vOther[not(string(current()/categoryName))])"/>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к следующему XML-документу:

<categoryName>X</categoryName>

получается желаемый, правильный результат :

X

При применении к этому XML-документу :

<categoryName></categoryName>

или по этому поводу:

<categoryName/>

или по этому

<somethingElse>Y</somethingElse>

получается правильный результат :

Other

Аналогичным образом, используйте это преобразование XSLT 1.0 :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vOther" select="'Other'"/>

  <xsl:template match="/">
    <xsl:copy-of select=
    "concat(categoryName,  substring($vOther, 1 div not(string(categoryName))))"/>
  </xsl:template>
</xsl:stylesheet>

Обратите внимание : никаких условностей не используется вообще. Узнайте больше о важности избегания условных конструкций в этом хорошем курсе Pluralsight:

app.pluralsight.com/library/courses/…


Это не будет работать в случае булевых значений, поступающих из БД для ex:

 value = false

 if(!value) {
   // it will change all false values to not available
   return "not available"
 }




xslt null xslt-1.0 xslt-2.0