Open XML Format SDK 2.0 (CTP)

少々時間も立っているのですが、ようやくお話できるようになりました。

Open XML Format SDK 2.0(Aplil 2009 CTP)https://www.microsoft.com/downloads/details.aspx?FamilyID=c6e744e5-36e9-45f5-8d8c-331df206e0d0&DisplayLang=en

SDK1.0との違いを中心に書きたいと思います。

まずはコレです。

Strongly Typed Classes and Objects

まず1.0のコーディングスタイルを見てみましょう。

const string wordmlNamespace = "https://schemas.openxmlformats.org/wordprocessingml/2006/main"; XNamespace w = wordmlNamespace; WordprocessingDocument wordDoc = WordprocessingDocument.Open(@"C:\aaa.docx", true); MainDocumentPart mainPart = wordDoc.MainDocumentPart; XDocument doc = XDocument.Load(new System.IO.StreamReader(mainPart.GetStream())); var query = from para in doc                           .Root                           .Element(w + "body")                           .Descendants(w + "p")             from t in para.Descendants(w + "t")             select t; foreach (var q in query) {     Console.WriteLine(q.Value); } wordDoc.Close();

特にLINQ to XMLの部分に注目してください。

var query = from para in doc
                          .Root
                          .Element(w + "body")
                          .Descendants(w + "p")
            from t in para.Descendants(w + "t")
            select t;

 

 

XParh軸としてDescendants(子孫要素を返す)が使用されているのが分かるとおり、あくまでも汎用的なXMLを扱うコードと全く変わりありません。

コレが2.0になると以下のようなスタイルが可能です。

WordprocessingDocument wordDoc = WordprocessingDocument.Open(@"C:\aaa.docx", false); var query = from para in wordDoc                 .MainDocumentPart                 .Document                 .Body                 .Elements<Paragraph>()            from t in para.Elements()            select t;

foreach (var q in query) {    Console.WriteLine(q.InnerText); } wordDoc.Close();

まず、「みじかっ」が初めの印象ですよね。
XML名前空間の指定をしていないためなんですが、その根本を確認するために、LINQ to XML部分を見てみると・・・

var query = from para in wordDoc
                .MainDocumentPart
                .Document
                .Body
                .Elements<Paragraph>()
           from t in para.Elements()
           select t;

おぉ、型付けされたクラスが使用されてるのが分かります。
このDOMと仲良しになったのが、大きな変更点です。コードは短くなるし、intellisenceは使えるし、ますますLINQに馴染んだとも言い換えることが出来るでしょう。

さて次に、Validationを見てみましょう。
Wordのdocxを作成してテーブルを追加します。
その中に文字列を入れ込みますが、果たしてこのコードで正しいXMLになってるでしょうか?

WordprocessingDocument wordDoc = WordprocessingDocument.Create(@"c:\bbb.docx", WordprocessingDocumentType.Document);

MainDocumentPart mainPart = wordDoc.AddMainDocumentPart(); mainPart.Document = new Document(); Body body = new Body(); mainPart.Document.Body = body;

Table table = new Table(); table.Append(new TableProperties()); //table.Append(new TableGrid()); //ここが実行されないと、このXMLはInValidになるはず table.Append(new TableRow(new TableCell(new Paragraph(new Run(new Text("こんにちは")))))); body.Append(table); wordDoc.MainDocumentPart.Document.Save();

OpenXmlValidator validator = new OpenXmlValidator(); var errors = validator.Validate((wordDoc)); foreach (ValidationErrorInfo error in errors) {     Console.WriteLine(error.Description); } wordDoc.Close();

実行すると、コンソールに以下のようなエラーが表示されます。コメントにした部分が間違っていることが分かります。
image
OpenXMLはコードで生成することも可能ですから、こうしたチェックを利用するのは一つ手ですよね。

次にツールを紹介したいのですが、長くなってきましたので、次回にしたいと思います。