Wordでの履歴
WordのGUI画面上では「校閲」タブから設定することで履歴の記録が行われます。設定しない場合、履歴に関連する記述は追加されません。
ほか、同じ文書を複数のユーザに渡した後、それぞれが行った編集を比較、統合する機能も存在します。
WordprocessingMLでは、文書に対し補助的なマークアップを提供するために、注釈仕様があります。
注釈に分類される機能としてはコメント、変更履歴、しおり、スペルミスや文法エラー位置、編集権限があります。簡単には「最終的な印刷物には表示されずとも問題ないマークアップ」と捉えるのが良いでしょう。
注釈を記述する構造として、次の3つがあります。
以後、それぞれインライン注釈、構造縦断注釈、プロパティ注釈と呼びます。
インライン注釈の例として、ISOの該当箇所ではテキストの削除、挿入のマークアップが例示されています。
XMLは基本的に階層構造になります。要素は入れ子で記述され、開始タグと終了タグは互い違いにはなりません。
構造縦断注釈については、OOXMLより以前のWord機能をXMLとして記述するためなどに利用されます。注釈のような構造では、基本の文書自体の階層構造とは別の構造をマークアップすることが有り得ます。たとえば「複数の段落に対して1つのコメントを付加したい」といった場合です。XMLの仕様との整合性を取りながらこれを実現する手法がCross Structure(構造縦断)です。この構造について簡単にまとめると、範囲の開始、範囲の終了を示す要素(*RangeStart、*RangeEnd)を導入します。テーブル内で使用するとき、*RangeStartへcolFirstとcolLast属性を指定し、列の範囲を限定可能です。
そしてプロパティ注釈はrPrやpPrといったプロパティに対する注釈の仕組みで、以前のプロパティの履歴など、文書構造からは読み取りにくい操作を保持する目的で利用されます。
Annotationsに分類される機能は、スペルミス・文法エラーを除き、共通の属性として、author、id、dateを持ちます。authorなどは記述しない場合、文書全体のauthorにフォールバックされます。
Wordでは、文書のある箇所を選択してコメントを追加することができます。
WordProcessingMLのコメントは大きく2つの構造で構成されます。コメントの位置を示すタグと、コメントの内容です。コメント位置はdocument.xml内に、コメント内容は独立したパーツとしてcomments.xmlに格納されます。
<w:p>
<w:commentRangeStart w:id="0"/>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>...</w:t>
</w:r>
...
<w:commentRangeEnd w:id="0"/>
</w:p>
構造縦断メソッドであるcommentRangeStart要素とcommentRangeEnd要素は、id属性を持っています。StartとEndで同一のIDであるものが範囲として扱われ、互い違いに別の範囲指定も可能です。また、参照するコメントの内容はこのidと紐付きます。
開始位置と終了位置を別のタグで記述することで、コメントをテキストの途中の箇所から開始し、別の段落の途中の箇所で終了するような範囲選択が可能となっています。
常に範囲に対してコメントを行うとは限りません。「ある文の末尾にコメントを足したい」といったときにはcommentReferenceタグを挿入することで目的が達成できます。
次に、コメントの内容は、コメントのためのパーツが作成され、その中にコメントテキストが列挙されています。コメントのパーツはwordフォルダにcomments.xmlというファイル名で作成されます。このパーツは文書でコメントが使用された場合にだけ作成されます。
comments.xmlファイルの内容は、comments要素をルートとして、comment要素が列挙されています。1つのcomment要素が1つのコメントを表しています。
comment要素の内容は文書と同じく段落としてp要素を使って記述されています。
<w:comment w:id="0" w:author="..." w:date="2007-02-01T19:02:00Z" w:initials="MSOffice">
<w:p ... >
<w:pPr>
<w:pStyle w:val="a9"/>
</w:pPr>
<w:r>
<w:rPr>
<w:rStyle w:val="a8"/>
</w:rPr>
<w:annotationRef/>
</w:r>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
</w:rPr>
<w:t>コメント挿入</w:t>
</w:r>
</w:p>
</w:comment>
comment要素はid属性を持っています。このID値がメイン文書から参照されるときの値になります。author属性にはコメントの作成者名が入ります。date属性はコメントの作成日時です。
履歴の記載を有効にすると、pの箇所で、参照する履歴IDを示すrsidRとrsidRDefaultが指定されます。
Word 2019では、実際のコメント機構は仕様に拡張を加えたものとなります。コメントのステータス、親子関係によるスレッド機能などが存在します。
WordprocessingMLには、多人数での編集を含めた履歴機構があります。
履歴の種類としては大きく「削除」「挿入」「移動」があります。文書構造に合わせて履歴構造があります。ISO文書中ではrevision typeとして表記されている要素と、履歴識別の一意のIDによって、最低限の履歴が構成されます。
単一セッション内で一意なIDを用いて履歴を管理します。
この履歴IDは文書設定内に記述されます。挿入や削除などの操作はここに記述されたIDで履歴順序が管理されます。履歴のIDは16進数で、現在時刻を基に作成され、それ以前の履歴IDよりも大きな値であることが期待されます。rsidのvalにIDが保存されます。
<w:settings>
<w:rsids>
<w:rsidRoot w:val="..." />
<w:rsid w:val="..." />
<w:rsid w:val="..." />
...
<w:rsids>
</w:settings>
他のファイルとの比較に際しては「同じ元ファイルであるのか」が重要になります。この基準となるのが特殊なrsidであるrsidRootで、この値が同一であれば、同じ編集セッションとして扱われます。
基本的なテキストの変更について見てみましょう。「Office 2007のWord…」というテキストで、一度「2007」を削除した後、改めて「2007以降」と挿入し、保存した例を示します。
<w:p ... w:rsidR="003E4DDA" w:rsidRDefault="003E4DDA" w:rsidP="003E4DDA">
...
<w:r w:rsidRPr="003E4DDA">
...
<w:t xml:space="preserve">Office </w:t>
</w:r>
<w:ins w:id="2" w:author="..." w:date="2021-06-21T14:44:00Z">
<w:r w:rsidR="00F078E9">
<w:rPr>...</w:rPr>
<w:t>2007</w:t>
</w:r>
<w:r w:rsidR="00F078E9">
<w:rPr>...</w:rPr>
<w:t>以降</w:t>
</w:r>
</w:ins>
<w:del w:id="3" w:author="..." w:date="2021-06-21T14:44:00Z">
<w:r w:rsidRPr="003E4DDA" w:rsidDel="00F078E9">
<w:rPr>...</w:rPr>
<w:delText>2007</w:delText>
</w:r>
</w:del>
<w:r w:rsidRPr="003E4DDA">
...
<w:t>のWord、Excel、PowerPointを使って作成されたファイルは、...</w:t>...
</w:r>
...
</w:p>
id、author、date属性が挿入の注釈であるins要素と、削除の注釈であるdel要素に指定されています。また、pにrsidR(Revision Identifier for Paragraph)、rsidDefault(Default Revision Identifier for Run)、rsidP(Revision Identifier for Paragraph Properties)が指定されています。これはそれぞれpの履歴ID、子のrの履歴IDの既定、pのプロパティの履歴IDとなっています。
delの内部から見ていきましょう。子のrに、rPrの履歴IDと、削除を行った履歴IDがrsidDelとして指定されています。実際に変更されたテキストはdelTextに格納されています。
insの属性には、rの履歴番号のみが指定されていました。挿入されたテキストは現在表示される最新のテキストなので、通常のtに格納されています。
履歴番号に注目すると、delの内部のrsidDelとins内部のrsidRの番号が一致しており、それ以外はpに指定されている履歴番号と一致しています。
テキストに対しての変更が行われた場合、rにrとrPrの履歴番号を記載し、rPrの属性には履歴番号を記述しないようです。
あるpの内部で、複数のrに対して操作を行った場合、delやinsの子には、それらのrがまとめて記述されます。複数のpに対して同時に操作を行った場合は、pごとに履歴がまとめられます。
「ある内容を別の新しい段落に移す」といったp単位の操作についてはプロパティ注釈で表現されます。その段落のpPrの子のrPrの子としてins、del要素が挿入されます。
移動については、移動元をmoveFrom、移動先をmoveTo要素で履歴が記録されます。「ある段落が移動した」という履歴には、段落内部でのテキストの変化は含まれません。
WordのGUI画面上では「校閲」タブから設定することで履歴の記録が行われます。設定しない場合、履歴に関連する記述は追加されません。
ほか、同じ文書を複数のユーザに渡した後、それぞれが行った編集を比較、統合する機能も存在します。
アプリケーション上でのコメントの表示非表示については、履歴で説明しているrevisionViewのcomments属性で設定されます。
テーブルの履歴には、セルに対する操作、行に対する操作、列に対する操作、テーブルに対する操作、それぞれのプロパティに対する操作の履歴のための要素があります。
セル結合についての操作履歴も存在します。
カスタムXML用の履歴は、customXMLでの操作を示す開始位置と終了位置をcustomXML*RangeStart、customXML*RangeEndで指定します。内部での操作履歴については通常の段落と同様に記述します。
WordprocessingMLでの数式はOffice Open XML Mathの名前空間で記述します。しかし数式部分の操作履歴はWordprocessingMLの名前空間で記述されます。
<m:f>
<m:fPr>
<m:ctrlPr>
<w:ins w:id="0" w:author="..." w:date="...">
…
</w:ins>
</m:ctrlPr>
</m:fPr>
…
</m:f>
数式のプロパティ操作を記述する箇所で、通常の履歴同様に記述できます。上の例ではf(fraction)のプロパティとして履歴が記述されています。
スタイル定義の操作は履歴として記録可能です。style要素の子孫でスタイル定義が記述されますが、そのうちのrsid要素で、そのスタイルが定義された履歴がval属性に指定したIDで格納されます。
<w:style ... w:styleId="...">
<w:name w:val="..." />
<w:rsid w:val="..." />
</w:style>
文書設定で、アプリケーション上での履歴の表示非表示が指定可能です。
<w:settings ...>
<w:revisionView w:markup="false" w:comments="false" w:insDel="false" w:formatting="false" />
</w:settings>
テキストの挿入・削除・移動についてはinsDelへ、書式などについてはformattingへ指定します。範囲を示すtrueで表示、falseで非表示です。
コメント、インク注釈の表示についてもこの要素で扱われます。
revisionViewの記述を省略した場合、すべての履歴表示についてtrueとみなされます。
WordprocessingMLにおけるブックマークは、文書内部でのハイパーリンクのジャンプ対象となります。アウトラインとは異なり、文書内の任意の箇所をジャンプ対象に設定します。
ブックマークの範囲は構造縦断注釈によって表現されます。id属性に同じIDが指定されたbookmarkStartとbookmarkEndに挟まれた範囲が、そのブックマークとなります。設定したブックマークへジャンプするリンクは、bookmarkStartのname属性に指定したテキストを参照します。nameに指定したテキストが重複したとき、文書の読み込み順で最初に登場したブックマークが有効となり、それ以降の同名のブックマークは無視されます。
スペルミスや文法エラーの箇所も注釈として格納されます。これはアプリケーション上ではたとえば下線でユーザに表示されます。
この機能を実現する仕様は、要素としてはproofErrのみです。 type属性としてスペルミス開始位置であることを示すspellStartと終了位置を示すspellEnd、同様に文法エラーを示すgramStartとgramEndで範囲を示します。
スペルミス、文法エラーについての制御仕様はAnnotationsにはありません。文書設定のや段落プロパティで制御します。
documentProtectionに関連した操作です。 開始位置にpermStartを、終了位置にpermEndを記述します。
permStartでは編集権限についてより詳細な内容を記述します。その範囲に対する編集権限は、特定のユーザへの権限であればed、ユーザの集合への権限であればedGrpへ指定します。