Sprawdź, czy łańcuch znaków jest null lub pusty w XSLT

Jak mogę sprawdzić, czy wartość jest null lub empty z XSL ?

Na przykład, jeśli categoryName jest pusty? Używam przy wyborze konstrukcji.

Na przykład:

<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>
Author: Isaac G Sivaa, 2009-05-05

14 answers

test="categoryName != ''"

Edit : dotyczy to najbardziej prawdopodobnej interpretacji, moim zdaniem, "[not] null or empty", jak wynika z pytania, włączając w to pseudo-kod i moje wczesne doświadczenia z XSLT. Czyli " co jest odpowiednikiem poniższej Javy?":

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

Aby uzyskać więcej szczegółów, np. wyraźnie identyfikujące null vs. empty, zobacz odpowiedź johnveya poniżej i/lub XSLT 'fiddle' zaadaptowałem z tej odpowiedzi, która zawiera opcję w Michael Kay ' s komentarz oraz szósta możliwa interpretacja.

 300
Author: steamer25,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-10 10:33:31

Brak jakichkolwiek innych informacji, zakładam następujący 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>
Przykładowy przypadek użycia wygląda następująco:
<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>
 250
Author: johnvey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-06 18:01:05

Od Pusty Element:

Aby sprawdzić, czy wartość pewnego węzła jest pusta

To zależy co masz na myśli mówiąc pusty.

  • nie zawiera węzłów potomnych: not(node())
  • nie zawiera treści tekstowej: not(string(.))
  • nie zawiera tekstu innego niż spacja: not(normalize-space(.))
  • nie zawiera nic oprócz komentarzy: not(node()[not(self::comment())])
 58
Author: Chris Doggett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-08 13:49:52

O czym?

test="not(normalize-space(categoryName)='')"
 19
Author: helcim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-02 15:05:30

Pierwsze dwie zajmują się wartością null, a drugie dwie zajmują się pustym łańcuchem znaków.

<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
Author: Aleksandar Borkovac,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-08-10 12:58:34

W niektórych przypadkach możesz chcieć wiedzieć, kiedy wartość jest konkretnie null, co jest szczególnie konieczne, gdy używasz XML, który został serializowany z obiektów. NET. Podczas gdy akceptowana odpowiedź działa na to, zwraca również ten sam wynik, gdy łańcuch jest pusty lub pusty, np.", więc nie można rozróżnić.

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

Więc możesz po prostu przetestować atrybut.

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

Czasami trzeba znać dokładny stan i nie można po prostu sprawdzić, czy nazwa kategorii jest instantiated, ponieważ w przeciwieństwie do say Javascript

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

Zwróci true dla elementu null.

 5
Author: DustJones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-12 08:26:09

Wiem, że to pytanie jest stare, ale pomiędzy wszystkimi odpowiedziami brakuje mi jednej, która jest powszechnym podejściem do tego przypadku użycia w rozwoju XSLT.

Wyobrażam sobie, że brakujący kod z OP wygląda mniej więcej tak:

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

I że wejście wygląda mniej więcej tak:

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

Tzn. zakładam, że może być zero, pusty, jeden lub Wiele categoryName elementów. Aby poradzić sobie ze wszystkimi tymi przypadkami za pomocą xsl:choose-style konstruktów, lub innymi słowy, imperatywnie, jest szybko coraz bałagan(tym bardziej, jeśli elementy mogą być na różnych poziomach!). Typowym idiomem programistycznym w XSLT jest używanie szablonów (stąd T w XSLT), co jest programowaniem deklaratywnym, a nie imperatywnym (nie mówi się procesorowi, co ma robić, po prostu mówi się, co ma być wykonane, jeśli spełnione są określone warunki). Dla tego przypadku użycia, który może wyglądać mniej więcej tak:

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

To działa (z dowolną wersją XSLT), ponieważ pierwsza z powyższych ma wyższy priorytet (ma predykat). Drugi szablon dopasowania" fall-through " wychwytuje wszystko, co nie jest poprawne. Trzeci zajmuje się następnie wyprowadzaniem wartości categoryName we właściwy sposób.

Zauważ, że w tym scenariuszu nie ma potrzeby dokładnego dopasowania categories lub category, ponieważ procesor automatycznie przetworzy wszystkie dzieci, chyba że powiemy inaczej (w tym przykładzie drugi i trzeci szablon nie przetwarzają dalej dzieci, ponieważ nie ma w nich xsl:apply-templates).

To podejście jest łatwiejsze do rozszerzenia niż podejście imperatywne, ponieważ automatycznie zajmuje się wieloma kategoriami i może być rozszerzone o inne elementy lub wyjątki, po prostu dodając kolejny pasujący szablon. Programowanie bez gałęzi if .

Uwaga: w XML nie ma czegoś takiego jak null. Istnieje xsi: nil , ale jest to rzadko używane, szczególnie rzadko w nietypowych scenariuszach bez jakiegoś schematu.

 4
Author: Abel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 02:56:57

Jeśli istnieje możliwość, że element nie istnieje w XML, przetestowałbym ZARÓWNO, że element jest obecny, jak i że długość łańcucha jest większa niż zero:

<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>
 3
Author: Marie Taylor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-14 15:47:53

Jeśli węzeł nie ma wartości dostępnej w wejściowym xml, jak poniżej xpath,

<node>
    <ErrorCode/>
</node>

Funkcja String () zamienia na pustą wartość. Więc to działa dobrze:

string(/Node/ErrorCode) =''
 2
Author: Sanjeev Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-23 09:35:26

Coś takiego działa u mnie:

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

Lub odwrotnie:

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

Uwaga: Jeśli nie sprawdzasz wartości null lub nie obsługujesz wartości null, IE7 zwraca -2147483648 zamiast NaN.

 2
Author: HSol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-23 10:10:14

Jak mogę sprawdzić, czy wartość jest NULL lub empty w XSL?

Na przykład, jeśli categoryName jest pusty?

Jest to prawdopodobnie najprostsze wyrażenie XPath (to w zaakceptowanej odpowiedzi daje test na przeciwne i byłoby dłuższe, jeśli zostanie zanegowane):

not(string(categoryName))

Wyjaśnienie :

Argumentem do powyższej funkcji not() jest false() dokładnie wtedy, gdy nie ma categoryName potomka ("null") elementu kontekstowego, lub) categoryName potomek ma wartość string -- pusty łańcuch.

Używam przy wyborze konstrukcji.

Na przykład:

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

W XSLT 2.0 użyj :

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

Oto pełny przykład :

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

Jeśli transformacja ta jest zastosowana w następującym dokumencie XML:

<categoryName>X</categoryName>

Poszukiwany, poprawny wynik jest produkowany :

X

Po zastosowaniu na tym XML dokument :

<categoryName></categoryName>

Lub na tym:

<categoryName/>

Lub na tym

<somethingElse>Y</somethingElse>

Powstaje prawidłowy wynik :

Other

Podobnie, użyj transformacji 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>

Uwaga: w ogóle nie są używane żadne warunki. Dowiedz się więcej o znaczeniu unikania konstruktów warunkowych w tym miłym kursie liczby mnogiej: {]}

"taktyczne wzorce projektowe w. NET: przepływ sterowania"

 2
Author: Dimitre Novatchev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-21 03:02:47

Z mojego doświadczenia wynika, że najlepszym sposobem jest:

<xsl:when test="not(string(categoryName))">
    <xsl:value-of select="other" />
</xsl:when>
<otherwise>
    <xsl:value-of select="categoryName" />
</otherwise>
 0
Author: dr_leevsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-29 07:46:02

Użyj prostej categoryName / text () taki test działa dobrze na <categoryName/>, a także <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
Author: Jaroslav Kubacek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-10 13:00:03

Faktycznie uważam, że lepiej jest po prostu sprawdzać Długość łańcucha, ponieważ wiele razy Pole nie jest null, tylko puste

 0
Author: Pedro Pereira,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-23 08:54:53