DITAのfiltering・flaggingで製品バージョンによる分岐を扱いたい
さて、DITAアーキテクチャでは出力文書の表示制御について、filteringとflaggingという機構を用意しています。これらは文書中で特定のプロパティによってマークした構造について、外部から出力・表現を制御するものです。今回、日本語での記事が全然無さそうな部分について記述します。まとめとして、filtering・flaggingはグルーピングによる制御が可能です。これを用いて「製品1.x未満」「製品1.y以降」という制御を行う方法について紹介します。
あまり動作を確かめられていないので、怪しい記述があります。確認できたら修正していきます。
filtering・flaggingに使う属性についての補足
filtering・flaggingに利用するプロパティは次があります。これらはprofile属性という括りで扱われます。
@product
@audience
@platform
@otherprops
@rev
@rev
はrevisionであるので、「これバージョンに使えそう」と思うのですが、『DITA概説書』では<q>revはflaggingに使え</q>(意訳)とあるんですよね。その反映か、@rev
だけditavalでは<revprop>
を使うようになっています。
抑、製品のドキュメントを考えたとき「ここでの@rev
は何のrevisionなのか」というのがハッキリしないという問題があります。つまり、このプロパティだけでは次の2つを区別できません。
- 文書の改訂版
- 製品のバージョン
@otherprops
は独自の分岐処理、つまりは特殊化に利用可能ですが、製品ってバージョンも含めて1つの扱いな気もするので難しいところです。今回はproductを使います。
基本的なfiltering
productの値について、productAの製品は「productA
+ver
+バージョン」で示すとします。
<!-- DITAトピック内 -->
<p product="productAver1 productAver2">ProductAではhogeができます。</p>
<p product="productAver3">以前あったhoge機能は廃止されました。</p>
バージョン3用の出力をするなら次のようにditavalを用意します。
<!-- ditaval ファイル -->
<val>
<prop att="product" value="productAver2" action="exclude"/>
<prop att="product" value="productAver3" action="include"/>
</val>
「バージョンが増えると大変になりそう」というのは、薄々想像がつくのではないでしょうか。また、文書で扱う製品バージョンが増えたときに、修正箇所を把握しておくのが大変です。
長期に渡りメインテナンスされる文書では「ここはv1-v3まで」「ここはv2-v4まで」など複雑な構造になることがあります。単純なatt="product",value="..."
では対応が大変ですし、filtering・flagging周りはユーザが独自に処理を追加するのが難しい箇所でもあります。
<!-- ver 20 用新機能用の ditaval ファイル -->
<val>
<prop att="product" value="productAver2" action="exclude"/>
<prop att="product" value="productAver3" action="exclude"/>
<prop att="product" value="productAver4" action="exclude"/>
...
<prop att="product" value="productAver20" action="include"/>
</val>
グルーピング
今回紹介するのは、ditavalの書き方が簡単になる方法です。@product
の方は簡単になりません。
profile属性の値には<groupname>(value1 value2 ...)
のようにしてグループ指定を利用できます。
OxygenXMLのサイトにあるサンプルによると、次がequivalentということらしいです。a,b,cは下のようになるのがこの時点ではしっくりきませんでしたが、ditavalを書く方で掴めるようになります。
product="a dataBase(dbA dbB) b appserver(mySERVER) c"
product="product(a b c) dataBase(dbA dbB) appserver(mySERVER)"
先に述べたように、DITAトピック文書側の記述は減りそうにないですね。肝心なのはここからで、これらをditaval側で指定するときにグループ名で指定できるようです。
<val><!-- ditavalでこう書けるようになる -->
<prop att="dataBase" action="exclude" value="dbA"/>
<prop att="product" action="exclude" value="a"/>
</val>
空のグループ名は無指定と同値のようです。
product="hoge()"
product=""
また、@product="dataBase(dbA)"
と@product="dbA"
は異なるというのもポイントですね。
前者は@att="dataBase"
で@value="dbA"
で扱うもので、
後者は@att="product"
で@value="dbA"
で扱うものになります。
本題
これを製品バージョンに応用します。
- ver3より前(ver1, ver2)のとき表示するパラグラフ
- ver3以降で表示するパラグラフ
<p product="productVer(v1 v2)"> ...</p>
<p product="productVer(v3 v4 ... v20)"> ...</p>
<!-- ver 20のditaval -->
<val>
<!-- productVerにv2を含むものは除外、v3を含むものは残す -->
<prop att="productVer" action="exclude" value="v2" />
<prop att="productVer" action="include" value="v3" />
</val>
保留 複雑なケース
上のグルーピングもケースによっては当然複雑になります。
<p product="productVer(v1 v2)">ある文脈</p>
<p product="productVer(v3 v4 ... v20)">ある文脈</p>
...
<p product="productVer(v1 v2 v3 v4)">別の文脈1</p>
<p product="productVer(v5 ... v20)"> 別の文脈1'</p>
<!-- コメント:v4から、文をv2以前と同様にしてみた -->
<p product="productVer(v3)">別の文脈2</p>
<p product="productVer(v1 v2 v4 v5 ... v20)"> 別の文脈2'</p>
「別の文脈1」のv4以前とv5以後で処理が変わるものについては、v3でinclude指定したものをv20など、被らないものにすればよいでしょう。
「別の文脈2」はどうでしょう。「v1,v2が今度はincludeに、v3がexcludeになるようにしたい、しかし「ある文脈」ではv1,v2はexcludeだし……」と混乱しますね。
specでの例示では、複数のグループで矛盾する処理が記述されているケースなども扱っていますが、hidarumaが咀嚼できていないため説明を保留します。
おまけ branch filtering
DITA 1.3以降では、<topicref>
の子に<ditavalref>
でditavalを指定し、ditavalの内容に沿って処理された結果をtopicとして扱うことができます。
例としてspecにあるものの一例を挙げてみます:
1. platform属性でwin,mac.linuxで個別のパラグラフを用意したトピック
2. それぞれをinclude,excludeするditavalを用意
3. 同じトピックを@href
に指定する<topicref>
を3つ用意
4. それぞれの子に、先に用意したditavalをditavalrefで指定
5. 必要ならそれぞれに参照時に使うsuffixなどを指定可能
6. ditavalを反映した結果がそれぞれ別のトピックとして扱われる
参考資料
- 『DITA概説書』(ComtechServices, Inc. 著,DITAコンソーシアムジャパン 監訳, エスアイビーアクセス (2010/1/1))
- https://www.antenna.co.jp/XML/behaviors-ja.html
- https://www.antenna.co.jp/dita/dita-intro.html
- https://toshi-xt500.hatenablog.com/entry/16765391
- https://www.oxygenxml.com/dita/1.3/specs/archSpec/base/usage-of-conditional-processing-attributes.html
- https://www.oxygenxml.com/dita/1.3/specs/archSpec/base/example-setting-condproc-values.html
- https://www.oxygenxml.com/dita/1.3/specs/archSpec/base/filtering.html
- https://www.oxygenxml.com/dita/1.3/specs/langRef/ditaval/ditaval-val.html
Discussion