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

Как я могу проверить, является ли значение пустым или пустым с помощью 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>

Ответ 1

.

test="categoryName != ''"

.

Изменить. Это относится к наиболее вероятной интерпретации, на мой взгляд, "[не] нулевой или пустой", как это было сделано из вопроса, включая его псевдокод и мой собственный ранний опыт работы с XSLT, I.e., "Что эквивалентно следующей Java?":

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

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

Ответ 2

Отсутствие какой-либо другой информации, я буду считать следующий 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>

Ответ 3

От Пустой элемент:

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

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

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

Ответ 4

Как насчет?

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

Ответ 5

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

<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>

Ответ 6

В некоторых случаях вам может понадобиться знать, когда значение имеет значение 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 для нулевого элемента.

Ответ 7

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

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

<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>

I.e. Я предполагаю, что могут быть нулевые, пустые, одиночные или несколько элементов categoryName. Чтобы справиться со всеми этими случаями, используя конструкторы xsl:choose -style, или, другими словами, настоятельно, быстро становится беспорядочным (тем более, если элементы могут быть на разных уровнях!). Типичная идиома программирования в 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, потому что процессор будет автоматически обрабатывать все дочерние элементы, если мы не скажем иначе (в этом примере второй и третий шаблоны обрабатывать детей, потому что в них нет xsl:apply-templates).

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

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

Ответ 8

Что-то вроде этого работает для меня:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) = 'NaN'"> - </xsl:when> 
  <xsl:otherwise> 
    <xsl:number value="categoryName" />
  </xsl:otherwise>
</xsl:choose>

Или наоборот:

<xsl:choose>
  <xsl:when test="string(number(categoryName)) != 'NaN'">
    <xsl:number value="categoryName" />
  </xsl:when> 
  <xsl:otherwise> - </xsl:otherwise>
</xsl:choose>

Примечание. Если вы не проверяете нулевые значения или обрабатываете нулевые значения, IE7 возвращает -2147483648 вместо NaN.

Ответ 9

Если существует вероятность того, что элемент не существует в 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>

Ответ 10

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

<node>
    <ErrorCode/>
</node>
Функция

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

string(/Node/ErrorCode) =''

Ответ 11

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

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

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

not(string(categoryName))

Объяснение

Аргумент функции not() выше равен false() точно, когда нет элемента categoryName child ( "null" ) элемента контекста, или (один такой) 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:

" Тактические шаблоны проектирования в .NET: поток управления"

Ответ 12

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

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

Ответ 13

Используйте простую категориюName/text(). Такой тест отлично работает на <categoryName/>, а также <categoryName></categoryName>.

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

Ответ 14

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

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