it-swarm.com.ru

Проверьте, является ли строка нулевой или пустой в 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>
307
raklos
test="categoryName != ''"

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

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

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

309
steamer25

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

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

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

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

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

Как насчет?

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

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

<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>
9
Aleksandar Borkovac

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

5
DustJones

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

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

4
Abel

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

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

<node>
    <ErrorCode/>
</node>

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

string(/Node/ErrorCode) =''
3
Sanjeev Singh

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

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

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

not(string(categoryName))

Объяснение :

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

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

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

3
Dimitre Novatchev

Как-то так у меня работает

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

2
HSol

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

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

Используйте простой categoryName/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>
0
Jaroslav Kubacek

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

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

0
Pedro Pereira