Edited at

Word docxファイルの中身を探検する - Office Open XML ざっくり入門

「Word docxファイルはzipファイルとして展開できる」って、知ってましたか?


シナリオ

あなたは、ドキュメント変換ツール「Pandoc」で、Markdownファイルからdocxファイルを生成したい、と考えます。

しかし、いろいろな都合で、docxファイルのフォーマットにかなり手を加える必要がある、とわかりました。

(たとえば、ルビ・脚注・図表など、単純なMarkdownの知識ではどうしようもないようなフォーマットを想定しましょう)

調べた結果、「Pandocフィルタを書いて、docxファイルをいじればよい」とひとまず結論を出します。

さて……


  • docxの中身ってどうなっているのでしょうか?

  • どうやって、MS Word本体なしで、docxファイルをいじればよいのでしょうか?

下記では、前者の「docxの中身」についてざっくり話します。後者は割愛します。


Office Open XMLとは

Office Open XML (OOXML)は、MS Officeのファイル(Office2007以降)の形式を定めている規格です。

雑に言えば「zip圧縮されたxmlファイル群+アセットファイル(画像など)」という構成です。

厳密には、次の規格群によって定められています:

さらに、MS Officeの各ソフト(Word、Excel、PowerPoint)によって、それぞれ具体的な規格が定められています:


  • WordprocessingML (Word docxに対応)

  • SpreadsheetML (Excel xlsxに対応)

  • PresentationML (PowerPoint pptxに対応)


docxファイルの中身

とにかく、docxファイルを調達しましょう。

便宜上、ここではPandocがデフォルトで利用する reference.docx というファイルを使います。

$ pandoc --print-default-data-file=reference.docx > reference.docx

まず、docxファイルはzipアーカイブです

docxファイルをzipファイルと見なせば、展開ができます。

ひとまず、中身をざっくり見てみましょう。

$ unzip -l reference.docx

Archive: reference.docx
Length Date Time Name
--------- ---------- ----- ----
1830 02-22-2019 07:00 [Content_Types].xml
724 02-22-2019 07:00 _rels/.rels
724 02-22-2019 07:00 docProps/app.xml
595 02-22-2019 07:00 docProps/core.xml
242 02-22-2019 07:00 docProps/custom.xml
8125 02-22-2019 07:00 word/document.xml
2494 02-22-2019 07:00 word/fontTable.xml
1135 02-22-2019 07:00 word/footnotes.xml
626 02-22-2019 07:00 word/comments.xml
2157 02-22-2019 07:00 word/numbering.xml
2126 02-22-2019 07:00 word/settings.xml
199 02-22-2019 07:00 word/webSettings.xml
14247 02-22-2019 07:00 word/styles.xml
1367 02-22-2019 07:00 word/_rels/document.xml.rels
301 02-22-2019 07:00 word/_rels/footnotes.xml.rels
7674 02-22-2019 07:00 word/theme/theme1.xml
--------- -------
44566 16 files

実際にzipファイルとして展開してみましょう。

$ unzip reference.docx -d reference_docx

Archive: reference.docx
inflating: reference_docx/[Content_Types].xml
inflating: reference_docx/_rels/.rels
inflating: reference_docx/docProps/app.xml
inflating: reference_docx/docProps/core.xml
inflating: reference_docx/docProps/custom.xml
inflating: reference_docx/word/document.xml
inflating: reference_docx/word/fontTable.xml
inflating: reference_docx/word/footnotes.xml
inflating: reference_docx/word/comments.xml
inflating: reference_docx/word/numbering.xml
inflating: reference_docx/word/settings.xml
inflating: reference_docx/word/webSettings.xml
inflating: reference_docx/word/styles.xml
inflating: reference_docx/word/_rels/document.xml.rels
inflating: reference_docx/word/_rels/footnotes.xml.rels
inflating: reference_docx/word/theme/theme1.xml

ディレクトリ構造を tree コマンドで見てみます。

$ tree reference_docx

reference_docx
├── [Content_Types].xml
├── _rels
├── docProps
│   ├── app.xml
│   ├── core.xml
│   └── custom.xml
└── word
├── _rels
│   ├── document.xml.rels
│   └── footnotes.xml.rels
├── comments.xml
├── document.xml
├── fontTable.xml
├── footnotes.xml
├── numbering.xml
├── settings.xml
├── styles.xml
├── theme
│   └── theme1.xml
└── webSettings.xml


中身の雰囲気のみをつかむ

ここからかなり割愛して、ディレクトリ内の雰囲気をつかんでいきます。

まず注目してほしいのは word ディレクトリです。

Wordファイルのコンテンツが、大体ここに入っていると思ってください。

_rels ディレクトリなどは、いったん無視して大丈夫です。(ざっくり言えば、OPCに基づき、各ファイル間の関係(relation)を定義しています)

試しに word/documents.xml の中身を見てみます。

$ cd reference_docx/word

$ cat document.xml


document.xml

<?xml version="1.0" encoding="utf-8"?>

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"
xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing">

<w:body>
<w:p>
<w:pPr>
<w:pStyle w:val="Title" />
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Title
</w:t>
</w:r>
</w:p>
<w:p>
<w:pPr>
<w:pStyle w:val="Subtitle" />
</w:pPr>
<w:r>
<w:t xml:space="preserve">
Subtitle
</w:t>
</w:r>
</w:p>

(中略)

<w:p>
<w:pPr>
<w:pStyle w:val="Heading1" />
</w:pPr>
<w:bookmarkStart w:id="21" w:name="heading-1" />
<w:r>
<w:t xml:space="preserve">
Heading 1
</w:t>
</w:r>
<w:bookmarkEnd w:id="21" />
</w:p>

(中略)

<w:sectPr />
</w:body>
</w:document>


ひとまず、ここではWord文書らしきものが、XMLで定義されているということをつかめばOKです。

詳細については、ここでは割愛します。

もっと中身を覗きたい場合は、テキストエディタを使って中身を見てみましょう。

ただし、XMLファイルがminifyされている場合も多いため、XMLの整形ができるエディタ(もしくは拡張機能)を使いましょう。


まとめ

今の段階では、次のことがわかれば十分です。


  • docxファイルはzipアーカイブ(zipとして展開ができる)

  • その中身はXMLファイル

  • 上記は、主にOffice Open XML (OOXML) という規格で定められている


    • パッケージ構成自体の規格: Open Packaging Convention (OPC)

    • Word docxの詳細な規格: WordprocessingML




さらに知りたい人へ

今回は以上です。


and more...?(勝手に宣伝)

理音伊織さん(電子書籍制作ソフト「LeME」の開発者)が、技術書典6 (4/14)でOOXMLの本を出すらしいです。‏