idの重複

ある日スタイルシートをお客様からもらったデータで動かしていました.うまくXSL-FOが出来てFormatterのステップに行ってくれたのですが、やたらエラーメッセージが表示され組版が時間がかかります.なんとか終了したのですがid重複のエラーが3000行も出ていました.ギャッ!これでは遅くなるはずです.スタイルシートを修正してテストするのに、これでは毎回手間がかかってしょうがありません.

原因を調べてみると入れ子のtopicのidが重複しているのでした.一般にDITAがオーサリングできるXMLエディタは、topicを挿入するとユニークなid属性を付加してくれます.

[XMetaLの場合:topicに自動的にユニークなid属性がつきます]

イメージ 1

[oXygenの場合:topicに自動的にユニークなid属性がつきます]

イメージ 2


両方ともエディタの機能を使ったときです.つまりXMetaLだと要素リストからtopicを選んで挿入します.oXygenだとオーサリングモードの表示にしてDITA-Insert-Insert Topicを選択します.XMLを直接編集するモードでは使えません.

問題はここからで、いったん作成したtopicを他で少し内容を変えて使いたいと言う場合、思わずファイル(File)-名前をつけて保存(Save As)、とやってしまうパターンが多いのではないかと思います.こうするとidが同じtopicができてしまいます.使っているCMSによっては、最上位のtopic/@idを自動的にユニークにしてくれる場合もあるようです.でもさすがに入れ子のtopicのidまでは面倒を見てくれません.

DITAではmapでtopicを結合したときに、topic/@idはユニークでなければならないのですが、実はDITA Open Toolkitはそこをうまく面倒を見てくれています.このidを使用せず自動的に中間ファイル上では"uniqueN"というidに置き換えてくれます.

これは良い面と悪い面があります.良い面は、CMSベースでやっていなような場合、上記のようにFile-Save Asをやって別のtopicを作ってしまう場合が多々あるのです.こういう事態であってもDITA Open Toolkitに任せておけばidの重複エラーを避けることができます.悪い面は、あるtopicにどのようなidがつけられるかはDITA-OTにお任せなので外からは値がわからない点です.たとえば複数のマニュアルのPDFを作って、互いに相手のPDFをリンクで参照したいという場合があります.このようなとき、DITA-OTが勝手につけたUniqueNのidでは参照しようがないのです.こういう時はもともと付いていたidを尊重してPDFの外に参照先としてexportしてやる必要があります.
⇒この方法についてはdita-usersでのEliot Kimberさんの質問を参照: http://tech.groups.yahoo.com/group/dita-users/message/31255

あとtopic/@id以外の要素については、基本的にそのtopic内でユニークでなければなりません.でもDITAのDTDではこのような条件は記述しようががりません.DTDを見てみればわかりますが、

<!ENTITY % id-atts 
             'id 
                        NMTOKEN 
                                  #IMPLIED
              %conref-atts;' 
>

となっていて、

<!ENTITY % id-atts 
             'id 
                        ID 
                                  #IMPLIED
              %conref-atts;' 
>

ではないのです.ですので検証では重複はチェックされません.このようなid属性がエディタでどうなるのでしょうか?ol/liの場合についてみてみました.ol/liはxrefの参照先にもなりえるのでidが重要だからです.

[XMetalはol/liにちゃんとidを振ってくれます.]

イメージ 3

イメージ 4


[oXygenはolにはidを振りますが、ol/liにはidを振ってくれません.]

イメージ 5

イメージ 6

この機能の違いもあってか、XMetaLで人為的にol/liに同じidを入れてみてもなんのエラーにもなりません.これはもともとDTDで重複を検出することができないので無理もありません.

[XMetaLで重複したol/liのidを入れて検証]

イメージ 7

oXygenは自動的にidをol/liに振ってくれませんが、人為的にol/liに同じidを入れてみると、Shematronでエラーになります.

[oXygenで重複したol/liを入れて検証]

イメージ 8

これはなかなか賢いです.DTDでは検出しようもないエラーをスキーマトロンは検出してくれます.ちなみにidはそれが属しているtopicでユニークであれば良いのですが、入れ子のtopicでそれぞれ同じidのol/liを入れてもエラーにはなりません.やはりXPathの威力は絶大です.

このあとではスタイルシートでidの重複を防ぐにはどうしたら良いか少し考えてみたいと思います.