XSLTで文字列がnullまたは空かどうかを確認する


325

XSLで値が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>

コード例を拡張できますか?
ニックアレン

ユースケースによっては、おそらくxsl:whenノードテストに使用したくないでしょう。と<xsl:template match="Category[categoryName[not(node())]]">...一緒に検討してください<xsl:template match="Category">...。その後、プロセッサーが正しい決定を行い、ネストされたビジネスロジックを書き出す必要がなくなりxsl:chooseます。多くの場合、一致するテンプレートを使用すると、スタイルシートの記述が簡単になります。
2014

回答:


322
test="categoryName != ''"

編集:これは、私の意見では、疑似コードやXSLTでの私自身の初期の経験など、質問から推測される「[null]または空ではない」の最も可能性の高い解釈をカバーしています。つまり、「次のJavaに相当するものは何ですか?」

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

詳細については、たとえば、nullとemptyを明確に識別するには、以下のjohnveyの回答および/またはその回答から私が適応させたXSLT 'fiddle'を参照してください。これには、Michael Kayのコメントのオプションと6番目の解釈が含まれます。


14
このテストの詳細なセマンティクスは次のとおりです。文字列値が空の文字列であるcategoryName要素が少なくとも1つある場合はtrueを返します。
jelovirt 2009年

14
@jelovirtは、空の文字列ではないcategoryNameが少なくとも1つあるかどうかを言うつもりでしたか?(私はxslの初心者なので、私の質問に潜在的な愚かさを許してください。)
joedevon

10
この回答は、受け入れられ、高い投票が行われていますが、非常に誤解を招く可能性もあります。それは、「nullまたはempty」の意味に本当に依存します。categoryNameが存在しないか、長さがゼロの値で存在する場合に成功するテストが必要な場合は、を使用する必要がありますtest="not(categoryName = '')"。categoryName要素が存在しない場合、指定された回答はfalseを返します。これは、私の質問の解釈では、間違った回答になります。
マイケルケイ

2
@MichaelKay:詳細を提供するために答えを更新しました。コメントとSaxon XSLTプロセッサーをありがとう!
蒸し器25

<xsl:for-each select="root/*[matches(name(.), 'grp')]">VS2010で使用できるように翻訳するにはどうすればよいですか?
Si8、2015年

276

他の情報がない場合は、次の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>

のインスタンスをどのようにテストします</CategoryName>か?、空の文字列テストはこれでは機能しません
ラフィアン

3
各式の結果がどのようになるかを示すために、複数の例が含まれていることがわかります。
doubleJ 2013年

1
@raffian:XSLT、または関連テクノロジ(XQuery、DOM、XDM、スキーマなど)では、終了タグは別個のエンティティとは見なされません。代わりに、ノード、またはこの場合は要素のみを処理します。これは、開始タグと終了タグの間の全体です。つまり、をテストする方法はなく</CategoryName>、必要もありません。
アベル

4
私はこの回答のために特に質問にスターを付けました。質問はかなり古いですが、これは選択された回答であることのほうがはるかに価値があるようです
Patrick

68

空の要素から:

特定のノードの値が空かどうかをテストするには

それはあなたが空で何を意味するかに依存します。

  • 子ノードを含みません: not(node())
  • テキストコンテンツが含まれていません: not(string(.))
  • 空白以外のテキストは含まれません: not(normalize-space(.))
  • コメント以外は何も含まれていません: not(node()[not(self::comment())])

2
+1。いくつかのメモ。最初の箇条書きは、ノードでもあるテキストコンテンツをテストします。2番目の箇条書きは、現在のノードにテキストが含まれていないが、他のノードを含むことができるかどうかを知りたい場合は、任意の深さで任意のテキストノードをテストしますnot(text())。2番目の弾丸の代わりもnot(.//text())です。あなたの最後の弾丸が示すように:「無」を考えるには多くの方法があります;)。
2014

非常に実用的:文字列が空でないかどうかをテストするには、文字列自体をテストするだけです!if ($mystring) then ... else ...
Felix Dombek 2017

22

どうですか?

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

1
これはうまくいきます。内部にコメントが<categoryName> <!-- some comment --> </categoryName>あり、それ以外に意味のあるテキストがない場合でも、評価はtrue
rustyx

9

最初の2つはnull値を扱い、次の2つは空の文字列を扱います。

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

1
怖い。複数のユーザーまたは複数の名がある場合はどうなりますか?xsl:apply-templatesテンプレートを使用して一致させると、必要なものをはるかに簡単に取得できます。
2014

7

場合によっては、値が具体的にnullになるタイミングを知りたいことがあります。これは、.NETオブジェクトからシリアル化されたXMLを使用する場合に特に必要です。受け入れられた答えはこれで機能しますが、文字列が空白または空、つまり ''の場合も同じ結果を返すため、区別できません。

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

したがって、単純に属性をテストできます。

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

時々正確な状態を知る必要があり、CategoryNameがインスタンス化されているかどうかを簡単にチェックすることはできません。

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

null要素の場合はtrueを返します。


6

私はこの質問が古いことを知っていますが、すべての回答の中で、XSLT開発におけるこのユースケースの一般的なアプローチである1つが欠けています。

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-style構成を使用して、つまり、命令的に処理することは、すぐに面倒になります(要素が異なるレベルにある場合はさらにそうです!)。XSLTの典型的なプログラミングイディオムはテンプレートを使用します(したがって、XSLTのTです)。これは宣言型プログラミングであり、必須ではありません(特定の条件が満たされた場合に出力する内容をプロセッサに指示するのではなく、何を出力するかを指示するだけです)。このユースケースでは、次のようになります。

<!-- 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バージョンで)機能します。「フォールスルー」マッチングテンプレート、2番目のテンプレートは、無効なものをすべてキャッチします。3つ目は、categoryNameは適切な方法で値ます。

このシナリオでは、特に指定しない限り、プロセッサが自動的にすべての子を処理するため、categoriesまたはを具体的に一致させる必要がないことに注意してくださいcategory(この例では、2番目と3番目のテンプレートは子をさらに処理しませんxsl:apply-templates。それら)。

このアプローチは複数のカテゴリを自動的に処理し、別の一致するテンプレートを追加するだけで他の要素や例外に拡張できるため、命令型アプローチよりも簡単に拡張できます。if分岐のないプログラミング

注:nullXMLのようなものはありません。xsi:nilがありますが、これはめったに使用されません。特に、ある種のスキーマがない型なしのシナリオではめったに使用されません。


1
if-branchを使用しないプログラミング」について言及していただき、ありがとうございます。これの重要性を理解できない人がいます。それらのすべてのために、ここでこのトピックに関する非常に素晴らしいPluralsightのコースへのリンクは次のとおりです。「戦術デザインパターン.NETで:制御フロー」ゾラン・ホルバートによって:app.pluralsight.com/library/courses/... Aの必見は、読んでください!
Dimitre Novatchev 2016年

5

XSLで値がnullまたは空かどうかを確認するにはどうすればよいですか?

たとえば、categoryName空ですか?

これはおそらく最も単純なXPath式です(受け入れられた答えの1つは、反対のテストを提供し、否定するとより長くなります)。

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>

:条件文はまったく使用されません。この素晴らしいPluralsightコースで条件付き構成を回避することの重要性について詳しく学んでください。

.NETの戦術的なデザインパターン:制御フロー


こんにちは、Dimitreです。1.0のソリューションが必要です。私が持っているすべてのタグにコードを記述する必要がありますか、それとも、XML全体に実装するためのより簡単な方法はありますか?
zyberjock

@zyberjock、何を求めているのか不明確です。質問を投稿し、リンク付きのコメントを送ってください。ガイドラインに従って、適切な質問をしてください。
Dimitre Novatchev 2016

こんにちは@Dimitre、私はここに質問が投稿stackoverflow.com/questions/38150093/...
zyberjock

4

要素がXMLに存在しない可能性がある場合、要素が存在することと、string-lengthがゼロより大きいことの両方をテストします。

<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
空のノードセットの文字列値(現在のコンテキストに子要素categoryNameがない場合にXPath式が提供する値categoryName)は空の文字列として定義されるため、これは冗長です。要素string-length(categoryName)がない場合はゼロですcategoryName
Ian Roberts

3

以下のxpathのように、入力xmlでノードに使用可能な値がない場合、

<node>
    <ErrorCode/>
</node>

string()関数は空の値に変換します。だからこれはうまくいきます:

string(/Node/ErrorCode) =''

2

このようなものが私にとってはうまくいきます:

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

注:null値をチェックしない、またはnull値を処理しない場合、IE7はNaNではなく-2147483648を返します。


1

多くの場合、フィールドはnullではなく空であるので、文字列の長さをテストするだけの方が実際に良いことがわかりました

<xsl:when test = "string-length(field-you-want-to-test)<1">


0

私の経験では、最良の方法は次のとおりです。

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

0

単純な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>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.