Frage

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

Zum Beispiel, wenn categoryName ist leer? Ich verwende eine bei der Auswahl konstruieren.

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>
War es hilfreich?

Lösung

test="categoryName != ''"

Bearbeiten : Dies umfasst die wahrscheinlichste Interpretation, meiner Meinung nach, von „[nicht] null oder leer“, wie er von der Frage zu entnehmen, einschließlich es ist Pseudo-Code und meine eigenen frühen Erfahrungen mit XSLT . Das heißt: „Was ist das Äquivalent der folgenden Java?“:

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

Für weitere Informationen zB deutlich null vs. leer Identifizierung finden Sie unter johnvey unter und / oder der XSLT ‚Geige‘ ich aus dieser Antwort angepasst haben, die auch die Möglichkeit, in Michael Kay Kommentar enthält als sechstes möglich Interpretation.

Andere Tipps

Absent keine anderen Informationen, ich werde das folgende XML annehmen:

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

Eine Probe Anwendungsfall würde wie folgt aussehen:

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

Von leeres Element :

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

Es hängt davon ab, was Sie mit leeren bedeuten.

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

Was?

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

Die ersten zwei Abkommen mit Nullwert und der zweite zwei Abkommen mit leeren String zurück.

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

In einigen Fällen möchten Sie vielleicht wissen, wann der Wert speziell null ist, was insbesondere dann notwendig ist, wenn unter Verwendung von XML, die von .NET-Objekten serialisiert wurde. Während die akzeptierte Antwort für das funktioniert, es gibt auch das gleiche Ergebnis, wenn die Zeichenfolge leer oder leer ist, das heißt ‚‘, so dass Sie nicht unterscheiden können.

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

So können Sie einfach das Attribut testen.

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

Manchmal ist es notwendig, den genauen Zustand zu wissen, und man kann nicht einfach überprüfen, ob Kategorie instanziert wird, denn im Gegensatz zu sagen Javascript

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

Wird return true für ein Null-Element.

Wenn es eine Möglichkeit gibt, dass das Element nicht in der XML existiert würde ich beide testen, ob das Element vorhanden ist, und dass die String-Lä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>

Ich weiß, diese Frage ist alt, aber zwischen all den Antworten, ich vermisse eine, die ein gemeinsames Konzept für diesen Anwendungsfall in XSLT Entwicklung.

Ich stelle mir vor, dass der fehlende Code aus dem OP etwas wie folgt 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 sieht wie folgt aus:

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

d., Nehme ich es Null sein kann, leer, einzelne oder mehrere categoryName Elemente. Um mit all diesen Fällen xsl:choose-Stil Konstrukte verwenden, oder in anderen Worten, imperativ, wird schnell immer chaotisch (umso mehr, wenn Elemente auf verschiedenen Ebenen sein können!). Eine typische Programmierung Idiom in XSLT-Templates verwenden (daher der T in XSLT), die deklarative Programmierung ist nicht zwingend notwendig (Sie den Prozessor nicht sagen, was Sie gerade zu tun, sagen, was Sie ausgeben möchten, wenn bestimmte Bedingungen erfüllt sind). Für diesen Anwendungsfall, das kann in etwa wie folgt 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

(egal mit welcher XSLT-Version), da die erste über eine höhere Priorität hat (er hat ein Prädikat). Der „Fall-through“ passende Vorlage, die zweite, fängt alles, was nicht gültig ist. Die dritte nimmt dann den categoryName Wert in geeigneter Weise auszugeben.

Beachten Sie, dass es nicht notwendig ist in diesem Szenario specifially categories oder category übereinstimmen, da der Prozessor automatisch alle Kinder verarbeiten wird, wenn wir es nicht anders sagen (in diesem Beispiel die zweite und dritte Vorlage weiter die Kinder nicht verarbeiten, weil es keine xsl:apply-templates in ihnen).

Dieser Ansatz ist leichter ausfahrbaren dann der Imperativ Ansatz, weil es automically mit mehreren Kategorien beschäftigt und es kann nur für andere Elemente oder Ausnahmen erweitert wird durch eine andere passende Vorlage hinzufügen. Programmierung ohne wenn Zweige .

Hinweis: Es gibt nicht so etwas wie null in XML. Es gibt xsi: nil , aber das wird selten verwendet, besonders selten in nicht typisierten Szenarien ohne ein Schema von einer Art.

  

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

     

Zum Beispiel, wenn categoryName ist leer?

Dies ist wahrscheinlich der einfachste XPath-Ausdruck (die in akzeptierter Antwort liefert einen Test für das Gegenteil, und mehr wäre, wenn negiert):

not(string(categoryName))

Erklärung :

Das Argument der not() Funktion oben genau ist false(), wenn kein categoryName Kind ist ( „Null“) des Kontextelements, oder das (einzige solche) categoryName Kind hat String-Wert -. Die leere Zeichenfolge

  

Ich verwende eine bei der Auswahl konstruieren.

     

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>

In XSLT 2.0 Verwendung :

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

Hier ist ein komplettes 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 Transformation auf das folgende XML-Dokument angewendet wird:

<categoryName>X</categoryName>

das wollte, ist richtige Ergebnis erzeugt :

X

Wenn Sie auf diesem XML-Dokument angewandt :

<categoryName></categoryName>

oder auf diese:

<categoryName/>

oder auf diesem

<somethingElse>Y</somethingElse>

das richtige Ergebnis erzeugt :

Other

In ähnlicher Weise verwenden 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>

Hinweis: : Keine conditionals sind überhaupt verwendet. Erfahren Sie mehr über die Bedeutung bedingte Konstrukte zu vermeiden in diesem schönen Plural Kurs:

"< strong> Tactical Design Patterns in .NET: Kontrollfluss "

Wenn ein Knoten keinen Wert in der XML-Eingabe hat wie unter XPath,

<node>
    <ErrorCode/>
</node>

string () konvertiert in leeren Wert. So funktioniert das gut:

string(/Node/ErrorCode) =''

So etwas wie das funktioniert für mich:

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

Oder andersrum:

<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 Nullwerte verarbeiten, IE7 gibt -2147483648 statt NaN

Ich fand es eigentlich besser, nur für String-Länge testet das Feld, da oft nicht null ist, nur leere

  

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>

Verwenden Sie einfache category / text () Ein solcher Test auf <categoryName/> gut funktioniert 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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top