XML工房
~第4章~ XSLTスタイルシートの応用
2005年11月号掲載記事
それでは今回は、前回の最後に示した課題を解決したXSLTスタイルシートを紹介しましょう。
■前回の最後に示した課題
(A)フォルダ階層に従ってインデントを加える(「|」や「└」記号を付与する)
(B)フォルダ容量の大きさでソートする
(C)フォルダ容量の大きさであるバイト数を、KBやMBで表示する
(D)指定の階層レベルまで処理し、その先の階層を処理しない
確認のため、対象データであるXMLファイルと、現状の変換結果を、最初に示しておきます。
XMLファイル(※インデントを加えています) |
<?xml version="1.0" encoding="Shift_JIS"?> <Dir Name="My Documents" Size="0"> <File Name="Default.rdp" Size="1176"/> <File Name="desktop.ini" Size="0"/> <Dir Name="My Music" Size="0"> <File Name="Desktop.ini" Size="108"/> <Dir Name="Sample Music" Size="0"> <File Name="Beethoven's Symphony No. 9 (Scherzo).wma" Size="613638"/> <File Name="New Stories (Highway Blues).wma" Size="760748"/> </Dir> </Dir> <Dir Name="My Pictures" Size="0"> <File Name="Desktop.ini" Size="107"/> <Dir Name="Sample Pictures" Size="0"> <File Name="Blue hills.jpg" Size="28521"/> <File Name="Sunset.jpg" Size="71189"/> <File Name="Water lilies.jpg" Size="83794"/> <File Name="Winter.jpg" Size="105542"/> </Dir> </Dir> <Dir Name="My Webs" Size="0"> <Dir Name="images" Size="0"/> <Dir Name="_private" Size="0"/> <Dir Name="_vti_cnf" Size="0"/> <Dir Name="_vti_pvt" Size="0"> <File Name="botinfs.cnf" Size="146"/> <File Name="bots.cnf" Size="323"/> <File Name="service.cnf" Size="1072"/> <File Name="service.lck" Size="0"/> <File Name="services.cnf" Size="3"/> </Dir> </Dir> </Dir> |
現状の変換結果 |
My Documents(1,666,367) My Music(1,374,494) Sample Music(1,374,386) My Pictures(289,153) Sample Pictures(289,046) My Webs(1,544) images(0) _private(0) _vti_cnf(0) _vti_pvt(1,544) |
そして次のXSLTスタイルシートが、
(A)フォルダ階層に従ってインデントを加える(「|」や「└」記号を付与する)
(B)フォルダ容量の大きさでソートする
(C)フォルダ容量の大きさであるバイト数を、KBやMBで表示する
(D)指定の階層レベルまで処理し、その先の階層を処理しない
という機能を実装したものです。
もちろんスタイルシートの作り方はほかにもあると思います。
<?xml version="1.0" encoding="Shift_JIS"?> </xsl:template> |
このスタイルシートを使用して対象のXMLファイルを変換すると、結果は次のようなものになります。
My Documents(1.6MB) |
ポイントを絞って解説します。
まずは簡単なところから。。
課題(B)に対しては[12]の1行で実現できます。「フォルダ容量の大きさ」を計算するには、XPathのsum関数を使用できます。このスタイルシートでは昇順(ascending)でソートしていますが、order属性値をdescendingに変えれば降順でソートできます。
そして課題(C)は[7]で実装しています。xsl:choose要素を使用し、フォルダ容量の大きさで条件判断し、「MB」で表示するか、「KB」で表示するか、あるいは「0」か「byte」かを決めています。
ちょっと複雑なのが(A)と(D)ですが、まずは(D)から。
XMLファイルの階層構造には、スタイルシートの再帰処理でうまく対応できます。このときノードの階層が深くなるごとに、indent変数の値をインクリメントすれば、処理対象ノードの階層レベルを常に把握することができます。indent変数の宣言が[4]、indent変数のインクリメントが[11]です。そして次の階層のノードを処理するかしないかを判断しているのが、[9]のxsl:if要素です。つまりここの条件判断がFalseであるときは、再帰呼出を行いません。どの階層レベルまで処理するかは、先頭[1]のstoplevel変数の値で決まります。
最後に(A)についてですが、この考え方は(D)の解説と重なります。つまりノードの階層が深くなるごとに、インデント文字を追加していきます。インデント文字の追加は[10]で行っていますが、ここでは対象ノード以降に兄弟ノードがあるかないかによって、追加文字を変えています。この違いは、変換結果の最終行とその他の行での表示の違いとなります。インデント文字を保持するstring変数の宣言が[5]で、実際にインデントを出力しているのが[6]です。
いかがでしょうか。
このようにXSLTスタイルシートの機能はかなり高機能で、XMLファイルからデータを抽出したり、並べ替えたり、または関数を使用した計算などもできます。XSLTスタイルシートをうまく使用できると、プログラミングの負担を大きく削減できると思いますので、ぜひ参考にしてみてください。