RM-BLOG

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【XSL】出力制御の構文メモ

XSLにおける、主にタグ値の取得に関する構文メモ


 

 


(1)タグの値(いわゆる「テキストノード値」)を取得する方法
VALUE」というタグで囲まれた値を取得して出力する。
xsl:value-ofで対象のタグをルート位置から狙い撃ちするかんじ。
最後に「/」はつけない。

XML

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="test_01.xsl"?>
<TEST>
   <VALUE>test</VALUE> ←ここでいう「test」を取得したい
</TEST>


■取得方法

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">
      <html>
         <head>
         </head>
         <body>
            VALUE」タグの値は<xsl:value-of select="/TEST/VALUE" />
         </body>
      </html>
   </xsl:template>
   
</xsl:stylesheet>


■結果

VALUE」タグの値はtest 

 




(2)タグの属性値を取得する方法
VALUE」というタグの値ではなくて、タグに設定された属性値「TEST_ATTR」を取得して出力。
取得するタグ名の後ろに「@」をつけて、その後ろに対象の属性名を記述する。

XML

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="test_02.xsl"?>
<TEST>
   <VALUE TEST_ATTR="TEST ATTRIBUTE">test</VALUE>  ←ここでいう「TEST ATTRIBUTE」(TEST_ATTR属性値)を取得したい
</TEST>


■取得方法

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">

      VALUE」タグの属性値は<xsl:value-of select="/TEST/VALUE/@TEST_ATTR"/>
       
   </xsl:template>
   
</xsl:stylesheet>


■結果

TEST ATTRIBUTE

 




(3)同名タグの特定属性のタグ値を取得する方法
VALUE」タグが複数存在していてそれぞれが異なる属性値「DATA_NO」で管理されている場合に
特定の属性値を持つ「VALUE」タグの値だけを取得して出力。
対象のタグ名まで書いた後に、[@属性名='対象の属性値']で特定の条件を記述する。
これはxsl:apply-templatesのselect、xsl:templateのmatchにも同じ書き方が出来る。

XML

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="test_03.xsl"?>
<TEST>
   <VALUE DATA_NO="TEST1">TEST1 DATA</VALUE>  
   <VALUE DATA_NO="TEST2">テストだよーん</VALUE>  VALUEタグのうちこれに該当する分の値を取得したい
   <VALUE DATA_NO="TEST3">ほげほげ</VALUE>  
</TEST>

■取得方法1

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">

      VALUE」タグのうち、属性「DATA_NO」が2の値は <xsl:value-of select="/TEST/VALUE[@DATA_NO='TEST2']"/>
       
   </xsl:template>
   
</xsl:stylesheet>


■結果1

VALUE」タグのうち、属性「DATA_NO」が2の値は テストだよーん




■取得方法2

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">

      <xsl:apply-templates select="/TEST/VALUE[@DATA_NO='TEST2']" />
       
   </xsl:template>
   
   <xsl:template match="/TEST/VALUE[@DATA_NO='TEST2']">
       VALUE」タグのうち、属性「DATA_NO」が2の値をxsl:tempalteで取るとその値は <xsl:value-of select="." />
   </xsl:template>
   
</xsl:stylesheet>


■結果2

VALUE」タグのうち、属性「DATA_NO」が2の値をxsl:tempalteで取るとその値は テストだよーん

 




(4)複数タグの値取得を一発で指示する方法
例えば検索結果のように、明細的なデータ内容が記述されたXMLの場合、
各明細を示すタグ名は全て同じでそのタグが複数存在する、ということになる((3)と関連)が
それを明細数分XSL側に記述するのはナンセンスだし実装負荷もあがるので
(というか明細によって抜本的に処理変えることなんてほぼないだろう…明細内の項目によってちょっと違う動きするとか、偶数行だけ色変えるとか、そういうのはあるかもしれないけど)
それを一発(?)で指示する方法。

複数存在するタグは参照名の先頭に「//」をつけることで一括処理できる。
「TEST/RESULT//RECORD」なら「TEST/RESULT」までは単一タグだがその配下の「RECORD」タグは複数あるので一括でヨロシク!という意味になる。

XML

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="test_04.xsl"?>
<TEST>
   <RESULT>
      <RECORD NO="1"> ←この「RECORD」タグを、いちいち3回書かずに1回で処理したい
         <NO>1</NO>
         <NAME>テストNo1のレコードです。</NAME>
         <ETC>-</ETC>
      </RECORD>
      
      <RECORD NO="2">
         <NO>2</NO>
         <NAME>テストNo2のレコードです!</NAME>
         <ETC>備考的に使います。</ETC>
     </RECORD>

      <RECORD NO="3">
         <NO>2</NO>
         <NAME>テストNo2のレコードです!!</NAME>
          <ETC>𩸽</ETC>
      </RECORD>
      
   </RESULT>
</TEST>



■取得方法

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">
      <html>
         <head>
         </head>
         <body>
            検索結果を表示します。<br/>
            <table border="1">
               <th>(Attribute 'No')</th><th>No</th><th>Name</th><th>Etc</th>
               <xsl:apply-templates select="/TEST/RESULT//RECORD"/>
            </table>
         </body>
      </html>
       
   </xsl:template>
   
    <xsl:template match="/TEST/RESULT//RECORD">
      <tr>
         <td>
            <xsl:value-of select="@NO"/>
         </td>
         <td>
            <xsl:value-of select="./NO"/>
         </td>
         <td>
            <xsl:value-of select="./NAME"/>
         </td>
         <td>
            <xsl:value-of select="./ETC"/>
         </td>
      </tr>
   </xsl:template>
   
</xsl:stylesheet>



■結果

検索結果を表示します。
            <table border="1">
               <th>(Attribute 'No')</th><th>No</th><th>Name</th><th>Etc</th>
      <tr>
         <td>
            1
         </td>
         <td>
            1
         </td>
         <td>
            テストNo1のレコードです。
         </td>
         <td>
            -
         </td>
      </tr>               
      
      
      <tr>
         <td>
            2
         </td>
         <td>
            2
         </td>
         <td>
            テストNo2のレコードです!
         </td>
         <td>
            備考的に使います。
         </td>
      </tr>               

      <tr>
         <td>
            3
         </td>
         <td>
            3
         </td>
         <td>
            テストNo3のレコードです!!
         </td>
         <td>
            𩸽
         </td>
      </tr>               

      
            </table>

 




(5)あるタグに該当する分の処理を無効化する(無視する)方法
(4)で述べた「複数タグの一括処理」で説明した「//」だが、
これは厳密に言うと、「その配下全て」を指示する意味になる。
これを記述することによって、その配下にどのようなタグが存在するのか意識しなくてもいい、という意味になるので、
実装が楽になる反面、その中にあえて処理したくないタグがある、というような場合は逆に弊害になる。
「//」配下にいると、xsl:templateで個別に編集定義を記述していない場合も対象になるからである。
→//で書いてしまうことで、個別の編集定義の記述を省略する代わりに配下の全タグが問答無用で対象になる

なんかもう少しうまいやり方がありそうなもんだが、
こういう場合は「そのタグに該当する分のtepmpalte定義を無理やりつくって、中で何も書かない」とすれば
XSLの処理の中でそこは通るものの結果として何も出力されないのでシカト扱いになる。

XML

<?xml version="1.0" encoding="UTF-8"?> 
<?xml-stylesheet type="text/xsl" href="test_05.xsl"?>
<TEST>
   <VALUE>100</VALUE>
   <NAME>テスト太郎</NAME>
   <SIKATO_A>ほげほげ</SIKATO_A> ←こいつと
   <SIKATO_B>うんたらかんたら</SIKATO_B>←こいつを変換結果に出したくない
   <AGE>30</AGE>
</TEST>



■取得方法

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

   <xsl:output method="html" encoding="UTF-8"/>

   <xsl:template match="/">
      <html>
         <head>
         </head>
         <body>
            一部シカトして情報を表示します。<br/>
            <hr style="border-style:dashed;"/>
            <xsl:apply-templates select="//TEST" />
         </body>
      </html>
       
   </xsl:template>
   
   <xsl:template match="VALUE">
      値は<xsl:value-of select="."/><br/>
   </xsl:template>
   
   <xsl:template match="NAME">
      名前は<xsl:value-of select="."/><br/>
   </xsl:template>

   <xsl:template match="AGE">
      年齢は<xsl:value-of select="."/><br/>
   </xsl:template>
   
   <xsl:template match="SIKATO_A">
      <!-- 何も記述しない --> ←template定義を無理やりつくって、中に何も書かなければ「無視を出力」する扱いになる
   </xsl:template>

   <xsl:template match="SIKATO_B">
      <!-- 何も記述しない --> ←template定義を無理やりつくって、中に何も書かなければ「無視を出力」する扱いになる
   </xsl:template>
   

   
</xsl:stylesheet>



■結果

一部シカトして情報を表示します。

値は100
名前はテスト太郎
 年齢は30


ちなみに↑のシカト定義をつくらないと↓みたいになる。

■シカトしなかった場合の結果

一部シカトして情報を表示します。

値は100
名前はテスト太郎
ほげほげ うんたらかんたら 30 

この場合の「ほげほげ」「うんたらかんたら」を出さなくする、という目的がある。