ワープロ ドキュメント内のすべての変更を反映する
このトピックでは、Open XML SDK for Office を使用して、プログラムによってワープロ ドキュメントのすべてのリビジョンを受け入れる方法について説明します。
WordProcessingML ドキュメントの構造
WordProcessingML
ドキュメントの基本的なドキュメント構造は、document
要素とbody
要素で構成され、その後に段落を表す p
などの 1 つ以上のブロック レベル要素が続きます。 段落には、1 つ以上の r
要素が含まれています。
r
は、書式設定などのプロパティの共通セットを持つテキストの領域である run を表します。 実行には、1 つ以上の t
要素が含まれています。
t
要素には、テキストの範囲が含まれています。 次のコード例は、"テキストの例" というテキストを含むドキュメントの WordprocessingML
マークアップを示しています。
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Example text.</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
Open XML SDK を使用すると、 WordprocessingML
要素に対応する厳密に型指定されたクラスを使用して、ドキュメント構造とコンテンツを作成できます。 これらのクラスは、 名前空間にあります。 次の表に、 document
、 body
、 p
、 r
、 t
の各要素に対応するクラスのクラス名を示します。
WordprocessingML 要素 | Open XML SDK クラス | 説明 |
---|---|---|
<document/> |
Document | メイン ドキュメント パーツのルート要素。 |
<body/> |
Body | ISO/IEC 29500 仕様で指定されている、段落、表、注釈などのブロック レベル構造のコンテナー |
<p/> |
Paragraph | 段落 |
<r/> |
Run | セクション |
<t/> |
Text | さまざまなテキスト |
WordprocessingML ドキュメントのパーツと要素の全体的な構造の詳細については、「 WordprocessingML ドキュメントの構造」を参照してください。
WordProcessingML
ドキュメントの基本的なドキュメント構造は、document
要素とbody
要素で構成され、その後に段落を表す p
などの 1 つ以上のブロック レベル要素が続きます。 段落には、1 つ以上の r
要素が含まれています。
r
は、書式設定などのプロパティの共通セットを持つテキストの領域である run を表します。 実行には、1 つ以上の t
要素が含まれています。
t
要素には、テキストの範囲が含まれています。 次のコード例は、"テキストの例" というテキストを含むドキュメントの WordprocessingML
マークアップを示しています。
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>Example text.</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
Open XML SDK を使用すると、 WordprocessingML
要素に対応する厳密に型指定されたクラスを使用して、ドキュメント構造とコンテンツを作成できます。 これらのクラスは、 DocumentFormat.OpenXml.Wordprocessing 名前空間にあります。 次の表に、 document
、 body
、 p
、 r
、 t
の各要素に対応するクラスのクラス名を示します。
WordprocessingML の要素 | Open XML SDK クラス | 説明 |
---|---|---|
document | Document | メイン ドキュメント パーツのルート要素。 |
body | Body | ISO/IEC 29500 仕様で指定されている、段落、表、注釈などのブロック レベル構造のコンテナー |
p | Paragraph | 段落 |
r | Run | セクション |
t | Text | さまざまなテキスト |
ParagraphPropertiesChange 要素
変更履歴のマークを受け入れる場合は、既存のテキストを削除するか、新しいテキストを挿入することによって、段落のプロパティを変更します。 以降のセクションでは、段落のコンテンツを変更するためにコードで使用される 3 つの要素、<w: pPrChange>
(段落プロパティのリビジョン情報)、<w:del>
(削除された段落)、および <w:ins>
(挿入される表の行) を中心に説明します。
ISO/IEC 29500 仕様の次の情報では、ParagraphPropertiesChange
要素 (pPrChange
) について説明します。
*pPrChange (段落プロパティのリビジョン情報)
この要素は、WordprocessingML ドキュメント内の段落プロパティのセットに対する単一のリビジョンについての詳細を指定します。
この要素は、こうしたリビジョンを次のように保存します。
この要素の子要素には、このリビジョンの前に段落に適用された段落プロパティの完全なセットが含まれます。
この要素の属性には、このリビジョンが発生した時点 (つまり、これらのプロパティが段落プロパティの「前」のセットになった時点) に関する情報が含まれます。
中央揃えの WordprocessingML ドキュメント内の段落を検討すると、段落プロパティのこの変更はリビジョンとして追跡されます。 このリビジョンは、次の WordprocessingML マークアップを使用して指定します。
<w:pPr>
<w:jc w:val="center"/>
<w:pPrChange w:id="0" w:date="01-01-2006T12:00:00" w:author="Samantha Smith">
<w:pPr/>
</w:pPrChange>
</w:pPr>
この要素は、段落のプロパティに対するリビジョンが 2006 年 1 月 1 日に Samantha Smith によって行われたこと、この段落の段落プロパティの前のセットが null セットであった (つまり、この要素の下に段落プロパティが明示的に設定されていない) ことを示しています。
pPr
pPrChange
© ISO/IEC 29500: 2016
削除された要素
ISO/IEC 29500 仕様の次の情報では、Deleted 要素 (del
) について説明します。
del (削除される要素)
この要素は、WordprocessingML 文書内の段落の末尾を区切る段落記号を削除として扱う必要があることを指定します (つまり、この段落の内容は、この段落のマークで区切られなくなり、次の段落と組み合わされますが、それらの内容は、追跡対象のリビジョンの一部として自動的にマークされません)。
2 つの段落で構成されるドキュメントを考えます (各段落は段落記号¶で区切られています)。
る最初の段落の末尾を区切る物理文字が削除され、この変更がリビジョンとして追跡される場合、次の結果になります。
このリビジョンは、次の WordprocessingML を使用して表されます。
<w:p>
<w:pPr>
<w:rPr>
<w:del w:id="0" … />
</w:rPr>
</w:pPr>
<w:r>
<w:t>This is paragraph one.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>This is paragraph two.</w:t>
</w:r>
</w:p>
最初の段落マークの実行プロパティの del
要素は、この段落マークが削除され、この削除がリビジョンとして追跡されたことを指定します。
© ISO/IEC 29500: 2016
挿入される要素
ISO/IEC 29500 仕様の次の情報では、Inserted 要素 (ins
) について説明します。
ins (挿入される表の行)
この要素は、親である表の行が挿入された行として処理され、その挿入がリビジョンとして追跡されていることを示します。 この設定は、この行にある表のセルまたはそれらの内容に関するリビジョンの状態を示すものではなく (それらは個別に記録されたリビジョンである必要があります)、表の行そのものにのみ影響を与えるものとします。
2 番目の行の挿入がリビジョンによって記録されている 2 行 2 列の表を考えます。 この要件は、次のような WordprocessingML を使用して指定されます。
<w:tbl>
<w:tr>
<w:tc>
<w:p/>
</w:tc>
<w:tc>
<w:p/>
</w:tc>
</w:tr>
<w:tr>
<w:trPr>
<w:ins w:id="0" … />
</w:trPr>
<w:tc>
<w:p/>
</w:tc>
<w:tc>
<w:p/>
</w:tc>
</w:tr>
</w:tbl>
2 番目のテーブル行のテーブル行プロパティの ins
要素は、この行が挿入され、この挿入がリビジョンとして追跡されたことを指定します。
© ISO/IEC 29500: 2016
サンプル コード
以下のコード例は、ワープロ ドキュメント内のすべてのリビジョンを受け入れる方法を示しています。
プログラムを実行した後、このワープロ ファイルを開いて、すべてのリビジョン記録が受け入れられていることを確認してください。
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using System;
using System.Collections.Generic;
using System.Linq;
AcceptAllRevisions(args[0], args[1]);
static void AcceptAllRevisions(string fileName, string authorName)
{
using (WordprocessingDocument wdDoc = WordprocessingDocument.Open(fileName, true))
{
if (wdDoc.MainDocumentPart is null || wdDoc.MainDocumentPart.Document.Body is null)
{
throw new ArgumentNullException("MainDocumentPart and/or Body is null.");
}
Body body = wdDoc.MainDocumentPart.Document.Body;
// Handle the formatting changes.
List<OpenXmlElement> changes = body.Descendants<ParagraphPropertiesChange>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
foreach (OpenXmlElement change in changes)
{
change.Remove();
}
// Handle the deletions.
List<OpenXmlElement> deletions = body
.Descendants<Deleted>()
.Where(c => c.Author is not null && c.Author.Value == authorName)
.Cast<OpenXmlElement>().ToList();
deletions.AddRange(body.Descendants<DeletedRun>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
deletions.AddRange(body.Descendants<DeletedMathControl>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
foreach (OpenXmlElement deletion in deletions)
{
deletion.Remove();
}
// Handle the insertions.
List<OpenXmlElement> insertions =
body.Descendants<Inserted>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList();
insertions.AddRange(body.Descendants<InsertedRun>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
insertions.AddRange(body.Descendants<InsertedMathControl>()
.Where(c => c.Author is not null && c.Author.Value == authorName).Cast<OpenXmlElement>().ToList());
foreach (OpenXmlElement insertion in insertions)
{
// Found new content.
// Promote them to the same level as node, and then delete the node.
foreach (var run in insertion.Elements<Run>())
{
if (run == insertion.FirstChild)
{
insertion.InsertAfterSelf(new Run(run.OuterXml));
}
else
{
OpenXmlElement nextSibling = insertion.NextSibling()!;
nextSibling.InsertAfterSelf(new Run(run.OuterXml));
}
}
insertion.RemoveAttribute("rsidR", "https://schemas.openxmlformats.org/wordprocessingml/2006/main");
insertion.RemoveAttribute("rsidRPr", "https://schemas.openxmlformats.org/wordprocessingml/2006/main");
insertion.Remove();
}
}
}