XMLの鬼門:処理命令

XMLを処理する上で普段めったにお目にかからないのが処理命令です.
普通オーサリングで意図的に処理命令を書く人はまずいらっしゃらないでしょう?ではどのような場面で処理命令は使われるのでしょうか?
OxygenやXMetaLなんかのXMLエディタを使うとTracking Change(変更履歴の記録)の機能があります.実はここで挿入や削除を記録しするのに処理命令を使うのです.例えばOxygenだと、Trackin Changeの機能をONにしておくと次のように挿入/削除が表示されます.また自由に文書中にコメントを入れることができます.まるで履歴を管理するMicrosoft Wordみたいですね.

f:id:toshi_xt500:20200719211925p:plain
OxygenのTracking Change機能

挿入されたところはこんな感じで処理命令に囲まれます.

<?oxy_insert_start author="toshi" timestamp="20200719T192312+0900"?>Use this element
only when there is not some other more proper element. For example, for specific items such as GUI
controls, use the <xmlelement>uicontrol</xmlelement> element. This element is part of the DITA highlighting domain.<?oxy_insert_end?>

削除された内容は処理命令の中に保存されます.

<?oxy_delete author="toshi" timestamp="20200719T203739+0900" content="&lt;b&gt;STOP!&lt;/b&gt; This is &lt;b&gt;very&lt;/b&gt; important!"?>

コメントも次のように範囲が囲まれます.

<?oxy_comment_start author="toshi" timestamp="20200719T204110+0900" comment="重要な指摘!Typographic elementは出力の体裁を指定するので、論理的な意味は持っていない."?>
Use this element only when there is not some other more proper element.
<?oxy_comment_end?>

これをXMLエディタの表示と同じように出したいお話があります.企業や組織が文書を作るときは、必ずレビューするからです.レビューはやっぱりPDFに出して行いますので必要なのです.

このような処理命令をXSLTスタイルシートで処理するにはどうしたらよいでしょうか?上記のような例だと、ある要素の下のノードを、

  • 挿入の開始の処理命令~挿入の終了の処理命令
  • 削除の処理命令(これは単独)
  • コメントの開始の処理命令~コメントの終了の処理命令

でグルーピングすれば良いように見えます.

ところがこの目論見(もくろみ)は無残にも打ち砕かれます.それは次のような、要素をまたがったコメントが出てきてしまうからです.

f:id:toshi_xt500:20200719212548p:plain
要素をまたがって書けてしまうコメント

この箇所のXMLはつぎのようになっています.

<p>The superscript (<xmlelement>sup</xmlelement>) element indicates that text should be
       superscripted, or vertically raised in relationship to the surrounding text.
        Superscripts are usually a smaller font than the surrounding text. Use this element
      only when there is not some other more proper tag. This element is part of the
      <?oxy_comment_start author="toshi" timestamp="20200719T210652+0900" comment="&lt;p&gt;要素をまたがったコメントが書けてしまいます.
これは通常のXSLTスタイルシートでは処理しようがありません."?>DITA
       highlighting domain.</p>
<p>A subscript (<xmlelement>s<?oxy_comment_end?>ub</xmlelement>) indicates that text
       should be subscripted, or placed lower in relationship to the surrounding text.
       Subscripted text is often a smaller font than the surrounding text. Formatting may
       vary depending on your output process. This element is part of the DITA highlighting
       domain.</p>

つまり処理命令はXMLの要素の開始タグ/終了タグなど無視して、どこの位置にも書けてしまうということです.これはノードのグルーピングでは太刀打ちができません.これが処理命令が「XMLの鬼門」である所以(ゆえん)です.

ところが、こんなどうにもなりそうにない処理命令をバッチリ捕捉できるXSLTの手段があります.それはxsl:accumulatorです.以下でどのように捕捉できるかを紹介します.