僕は下書きとなるべく文書はXMLでフラットな文書で書いて、それをXSLTを用いて構造化させたXHTMLに変換させた物を公開している。その際には、jintrickさんの構造化モジュールを利用させて頂いていたのだが、最近になってようやく、そのロジックと言うかアルゴリズムが理解できたので自作のモジュールを作ろうと思ったのだが、ただ単に同じ作用の物を作ってもしょーもないので、新たな機能を盛り込んでみる事にした。
ご存知の通り、フラットな文書は「見出し」によって暗示的に構造モデルが形成されている。例えば、次の様な文書があるとする。
<h1>見出し1</h1>
<p>本文a</p>
<h2>見出し2</h2>
<p>本文b</p>
<h3>見出し3</h3>
<p>本文c</p>
<p>本文d</p>
すると暗示的な構造は、以下のようになる。
が、PaGeさんが言われているように、見出し3の本文dを見出し1の本文dと看做したい時が稀にあるのである。つまりは、以下のような構造にしたいのである(残念ながら、XSLT2.0をほとんど勉強していない小生にとって、PaGeさんのXSLTはお手上げです。 ....エイゴノシヨウショ、ワカリマセン...)。
div
要素を用いてセクションを設ける事で表現する事は可能であるが(無論、このような構造を持つ文書が果たして妥当か否かは別として)、それでは何の為にフラットな文書を採用したのか分からなくなる。div
要素、若しくはXHTML2.0的なsection
要素の記述が面倒臭くて、フラットなものを採用したのではなかったのか?
で、面倒臭く無くに明示的な終わりを表現できるようにモジュールを作っていましたが、何とか使用に耐えられる処までこぎ着けたので、公開してみようと思います。
え〜、使い方や注意点ですが、名前空間宣言以外はjintrickさんのものと全く同じなので、そちらの「フラットな文書を構造化 その2」を参照の事(構造化のアルゴリズム自体がパクリだから...)。で、独自な機能として、明示的な終わりを示すend
要素が扱えます。このend
要素には、http://www.lcv.ne.jp/~denori
なる名前空間を持たせて下さい。これより以下では、名前空間接頭辞dn
で名前空間宣言した事にして、dn:end
で説明します。
例えば、先のような構造にしたい場合は、次の様にフラットな文書を記述します。
<body xmlns:dn="http://www.lcv.ne.jp/~denori">
<h1>見出し1</h1>
<p>本文a</p>
<h2>見出し2</h2>
<p>本文b</p>
<h3>見出し3</h3>
<p>本文c</p>
<dn:end h="2"/>
<p>本文d</p>
</body>
dn:end
のh
属性に、終わらせたい見出しレベルの数値を与えます。対応する見出しレベルがあれば、文書中何回でも使えます。
【ソース】<body xmlns:dn="http://www.lcv.ne.jp/~denori"> <h1>見出し1</h1> <p>本文a</p> <h2>見出し2</h2> <p>本文b</p> <h3>見出し3</h3> <p>本文c</p> <dn:end h="3"/> <p>本文d</p> <dn:end h="2"/> <p>本文e</p> <h2>見出し2</h2> <p>本文f</p> </body>
【出力】<body> <div class="section1"> <h1>見出し1</h1> <p>本文a</p> <div class="section2"> <h2>見出し2</h2> <p>本文b</p> <div class="section3"> <h3>見出し3</h3> <p>本文c</p> </div> <p>本文d</p> </div> <p>本文e</p> <div class="section2"> <h2>見出し2</h2> <p>本文f</p> </div> </div> </body>
不正なdn:end
要素は用いないで下さい。不正があった場合、その内容は無視されます(下の例では、何れも"本文d"が無視される)。
h
属性にあり得ない値を与える。
<h2>見出し2</h2>
<p>本文b</p>
<h3>見出し3</h3>
<p>本文c</p>
<dn:end h="4"/>
<p>本文d</p>
<h2>見出し2</h2>
<p>本文b</p>
<dn:end h="2"/>
<p>本文c</p>
<dn:end h="2"/>
<p>本文d</p>
<h2>見出し2</h2>
<p>本文b</p>
<p>本文c</p>
<dn:end h="2"/>
<p>本文d</p>
<h3>見出し3</h3>
<p>本文e</p>
一応、考えられる不正には対処してみたが、もしかしたらとんでもないバグが潜んでいるかもしれません....
不正の判断には別の方法も思いつくも、どちら方の処理が速いのか分からなかったので簡単な方を選んだけど、ノード集合をふるいに掛けるのと、文字列をふるいに掛けるのは、どっちが速いんだろう? この辺りは次回に持ち越しってことで。
ともかく、何とか作ってみたのだが、今回も勉強になりました。各方面で情報を公開して下さっている皆様には、ただただ感謝するばかりです。
jintrickさんが言及されている事はおっしゃる通りだと思いますし、僕も良いとは思っていません。
ただ、論理的構成をせずに文章を書く事がある僕にとって、最後のp要素
には見出しを与えるほどの内容ではないとか、与えるにしては同位レベルのセクション群とは趣が違う、という事がありまして...。極力そのような文章は書かない様にしている積もりですが、書いたら書いたで「フラットの文書でどうにか表現できんかな?」と考えて、作ったシロモノです。
まあ、XSLTやアルゴリズムの勉強の一環でして、多分僕も使う機会は滅多に無いと思うところです。
どうもノード集合をふるいに掛けるより文字列をふるいに掛ける方が、処理に負担がかかる模様。xsl:choose
やxsl:if
、文字関数とかの負担が大きいのかも知れない。
しかしながら、xsltprocは速い。同じ処理をJAVA版プロセッサの10倍は速くこなす。くそー、インデントとかが納得できる出力してくれれば、直ぐにも乗り換えるのに。
いま、松田優作にハマっている。彼は確実にカッコいいし、憧れもしてしまう。
そういえば、彼がでている映画を「Black Rain」以外マトモに見た事が無かったので、取りあえず「蘇える金狼」「野獣死すべし」「家族ゲーム」の3本を見ようとDVD購入を計画。何とか全部ゲットしたが、近郊のCD屋さんや本屋さんを這いずり廻ったのは言うまでもない。しかも、最後にはamazonに頼る始末...。
って、なんじゃ、ソリャァー!?
知らぬ間に「ボボボーボ・ボーボボ」を観ている俺(おまけにジャンケン、やってるし...)。