wake-up-neo.com

Überprüfen Sie, ob eine Zeichenfolge in XSLT null oder leer ist

Wie kann ich mit XSL prüfen, ob ein Wert null oder leer ist?

Wenn beispielsweise categoryName leer ist? Ich benutze ein , wenn ich ein Konstrukt wähle.

Zum Beispiel:

<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>
315
raklos
test="categoryName != ''"

Bearbeiten : Dies deckt meiner Meinung nach die wahrscheinlichste Interpretation von "[nicht] null oder leer" ab, wie aus der Frage abgeleitet, einschließlich ihrer Pseudo- Code und meine eigenen frühen Erfahrungen mit XSLT. D. h. "Was ist das Äquivalent des folgenden Java?":

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

Weitere Einzelheiten, z. B. die eindeutige Identifizierung von null und leer, finden Sie unter Johnveys Antwort unten und/oder die XSLT-Geige Ich habe diese Antwort angepasst, einschließlich der Option in Michael Kays Kommentar sowie der sechsten möglichen Interpretation.

315
steamer25

Ohne weitere Informationen gehe ich von folgendem XML aus:

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

Ein Beispiel für einen Anwendungsfall sieht folgendermaßen aus:

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

Von leeres Element:

Um zu testen, ob der Wert eines bestimmten Knotens leer ist

Es kommt darauf an, was du mit leer meinst.

  • Enthält keine untergeordneten Knoten: not(node())
  • Enthält keinen Textinhalt: not(string(.))
  • Enthält keinen anderen Text als Leerzeichen: not(normalize-space(.))
  • Enthält nichts außer Kommentare: not(node()[not(self::comment())])
63
Chris Doggett

Wie wäre es mit?

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

Die ersten beiden befassen sich mit dem Nullwert und die zweiten beiden befassen sich mit der leeren Zeichenfolge.

<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

In einigen Fällen möchten Sie möglicherweise wissen, wann der Wert speziell null ist. Dies ist insbesondere dann erforderlich, wenn XML verwendet wird, das aus .NET-Objekten serialisiert wurde. Während die akzeptierte Antwort dafür funktioniert, gibt sie auch das gleiche Ergebnis zurück, wenn die Zeichenfolge leer oder leer ist, d. H. '', Sodass Sie nicht unterscheiden können.

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

Sie können das Attribut also einfach testen.

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

Manchmal ist es notwendig, den genauen Status zu kennen, und Sie können nicht einfach überprüfen, ob CategoryName instanziiert ist, da im Gegensatz zu Javascript

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

Gibt true für ein Nullelement zurück.

6
DustJones

Wie kann ich mit XSL prüfen, ob ein Wert null oder leer ist?

Wenn zum Beispiel categoryName leer ist?

Dies ist wahrscheinlich der einfachste XPath-Ausdruck .

not(string(categoryName))

Erklärung :

Das Argument für die Funktion not() ist false() genau dann, wenn es kein categoryName untergeordnetes Element ("null") des Kontextelements oder das (einzelne solche) categoryName untergeordnete Element gibt hat einen Zeichenkettenwert - die leere Zeichenkette.

Ich benutze ein , wenn ich ein Konstrukt wähle.

Zum Beispiel:

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

Verwenden Sie in XSLT 2.0 :

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

Hier ist ein vollständiges Beispiel :

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

Wenn diese Umwandlung auf das folgende XML-Dokument angewendet wird:

<categoryName>X</categoryName>

das gewünschte, korrekte Ergebnis wird erzeugt :

X

Bei Anwendung auf dieses XML-Dokument :

<categoryName></categoryName>

oder dazu:

<categoryName/>

oder dazu

<somethingElse>Y</somethingElse>

das richtige Ergebnis wird erzeugt :

Other

Verwenden Sie in ähnlicher Weise diese XSLT 1.0 -Transformation:

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

Beachten Sie : Es werden überhaupt keine Bedingungen verwendet. Erfahren Sie in diesem Nice Pluralsight-Kurs, wie wichtig es ist, bedingte Konstrukte zu vermeiden:

" Taktische Entwurfsmuster in .NET: Kontrollfluss "

4

Ich weiß, dass diese Frage alt ist, aber zwischen all den Antworten vermisse ich eine, die für diesen Anwendungsfall in der XSLT-Entwicklung üblich ist.

Ich stelle mir vor, dass der fehlende Code aus dem OP ungefähr so ​​aussieht:

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

Und dass die Eingabe ungefähr so ​​aussieht:

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

Ich gehe also davon aus, dass es null, leere, einzelne oder mehrere categoryName Elemente geben kann. Um mit all diesen Fällen fertig zu werden, müssen Konstrukte im xsl:choose -Stil verwendet werden, oder mit anderen Worten, es wird schnell chaotisch (umso mehr, wenn sich die Elemente auf verschiedenen Ebenen befinden können!). Eine typische Programmiersprache in XSLT ist die Verwendung von Vorlagen (daher das T in XSLT). Dabei handelt es sich um deklarative und nicht um zwingende Programmierung. Für diesen Anwendungsfall kann das ungefähr so ​​aussehen:

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

Dies funktioniert (mit jeder XSLT-Version), da die erste übergeordnete Version eine höhere Priorität hat (sie hat ein Prädikat). Die passende "Fall-Through" -Vorlage, die zweite, fängt alles ab, was nicht gültig ist. Der dritte sorgt dann für die ordnungsgemäße Ausgabe des Wertes categoryName.

Beachten Sie, dass in diesem Szenario keine spezifische Übereinstimmung mit categories oder category erforderlich ist, da der Prozessor automatisch alle untergeordneten Elemente verarbeitet, sofern nicht anders angegeben (in diesem Beispiel ist dies bei der zweiten und dritten Vorlage nicht der Fall) die Kinder weiterverarbeiten, weil sie keinen xsl:apply-templates enthalten).

Dieser Ansatz ist einfacher erweiterbar als der imperative Ansatz, da er automatisch mehrere Kategorien behandelt und für andere Elemente oder Ausnahmen erweitert werden kann, indem nur eine weitere passende Vorlage hinzugefügt wird. Programmierung ohne if-Äste .

Hinweis: In XML gibt es kein null. Es gibt xsi: nil , aber das wird selten verwendet, besonders selten in untypisierten Szenarien ohne irgendein Schema.

4
Abel

Wenn die Möglichkeit besteht, dass das Element im XML nicht vorhanden ist, würde ich sowohl prüfen, ob das Element vorhanden ist als auch ob die Zeichenfolgenlänge größer als Null ist:

<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

Wenn für einen Knoten kein Wert in der Eingabe-XML verfügbar ist (siehe xpath),

<node>
    <ErrorCode/>
</node>

die Funktion string () konvertiert in einen leeren Wert. Das funktioniert also gut:

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

So etwas funktioniert bei mir:

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

Oder umgekehrt:

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

Hinweis: Wenn Sie keine Nullwerte überprüfen oder keine Nullwerte verarbeiten, gibt IE7 -2147483648 anstelle von NaN zurück.

2
HSol

Ich fand es eigentlich besser, nur auf String-Länge zu testen, da das Feld oft nicht null ist, sondern nur leer

<xsl: when test = "Zeichenfolgenlänge (Feld, das Sie testen möchten) <1">

1
Pedro Pereira

Nach meiner Erfahrung ist der beste Weg:

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

Verwenden Sie einfach categoryName/text (). Ein solcher Test funktioniert gut mit <categoryName/> und auch <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