概説EPUB(構造解説編)

これ何

EPUBの構造と、各ファイルの役割を解説する文章です。私自身がEPUBを作ろうと思って調べました。EPUBに必要なファイルと夫々の役割が理解できることを目指しています。とりあえず、空っぽのサンプルを用意してみました。これを見つつ読めば、いくらか理解しやすいと思われます。僕はこのテンプレートをもとにEPUBを作ってますが、これ単体ではEPUBとして成立してないので、ご注意を。

EPUBを構成するよく分からないファイル達

EPUBは、乱暴に説明するならば『ZIPファイル』です。以下の解説は、冒頭で紹介したサンプルファイルの構造を基準に書いてあります。これを展開して構造を見ながら読むといいと思います。そんなわけで、夫々のファイルがどんな役割を果たしているのかを解説していきます。

mimetype

これは「オマジナイ」だと考えてください。EPUBのファイルを開いたアプリケーションは、最初にこのファイルの中身を確認します。そして内容が『zapplication/epub+zip』であることを確認します(もし内容が違っていたり、このファイルが存在しない場合には、アプリケーションはそのEPUBが正しい構造ではないと判断して、処理を中止します)。

このファイルに関しては、何も考えるべきことはありません。

META-INF/container.xml

このファイルは、内容が変わることもありますが、基本的にはほぼ固定の内容です。また、ファイル名とパスは固定です。要するに、EPUBのzipファイルの中に入っている『使われてるファイル一覧』みたいなデータがどこに書かれているかを指し示しています。この例では『OEBPS/content.opf』というファイルの場所を指し示しています。以下がcontainer.xmlの内容です。

<?xml version="1.0" encoding="UTF-8"?>
<container
	xmlns="urn:oasis:names:tc:opendocument:xmlns:container"
	version="1.0">
	<rootfiles>
		<rootfile
			full-path="OEBPS/content.opf"
			media-type="application/oebps-package+xml" />
	</rootfiles>
</container>
OEBPS/content.opf

このファイルの中には以下のような情報が格納されています。

  • EPUBそのものに関するメタ情報(作者名など)
  • EPUB内で利用されるファイルと、夫々のID
  • ファイルの並び順

とりあえずファイルの全貌を紹介します。

<?xml version="1.0" encoding="UTF-8"?>
<package
	version="2.0"
	xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">
	<!-- EPUBのメタ情報 -->
	<metadata
		xmlns:dc="http://purl.org/dc/elements/1.1/"
		xmlns:opf="http://www.idpf.org/2007/opf">
		<dc:title>タイトル</dc:title>
		<dc:creator opf:role="aut">著者名</dc:creator>
		<dc:language>ja</dc:language>
		<dc:publisher>EPUB作った人</dc:publisher>
		<dc:identifier id="BookId">urn:uuid:d.hatena.ne.jp/HowManyFiles/book001</dc:identifier>
	</metadata>

	<!-- EPUBで使われるファイルの一覧 -->
	<manifest>
		<item id="ncx"      href="toc.ncx"     media-type="application/x-dtbncx+xml" />
		<item id="style"    href="default.css" media-type="text/css" />
		<item id="html-001" href="001.html"    media-type="application/xhtml+xml" />
		<item id="html-002" href="002.html"    media-type="application/xhtml+xml" />
		<item id="html-003" href="003.html"    media-type="application/xhtml+xml" />
		<item id="html-004" href="004.html"    media-type="application/xhtml+xml" />
		<item id="img_001"  href="fig001.png"  media-type="image/png"/>
		<item id="img_002"  href="fig002.png"  media-type="image/png"/>
	</manifest>

	<!-- ファイルの並び順 -->
	<spine toc="ncx">
		<itemref idref="html-001" />
		<itemref idref="html-002" />
		<itemref idref="html-003" />
	</spine>
</package>

一気に構造が複雑になった気がしますが、大したことはないです。XMLなので複雑に見えるだけというか。

EPUBのメタ情報』とコメントが書かれた下に書かれているのが、本のタイトルは何で・著者が誰で・言語は何で……みたいな情報です。これはコンテンツの内容によって変わります。あと、この情報は必ずしも全部が必要というわけではないみたいです。例えばpublisherの情報とかは無いなら無いで表示できました。

EPUBで使われるファイルの一覧』とコメントが書かれた下にあるのが、そのまんまですがファイル一覧です。ページデータの本体であるXHTMLファイルや画像ファイル・CSSファイル・目次のためのncxファイルなどが書かれています。id属性値で夫々のファイルにIDを与え、href属性値でファイル名を明示し、media-type属性値でそれがどんな種類のファイルであるかを明示しています。当然の話ですが、IDは一つのEPUBの中では同じものを使えません。

『ファイルの並び順』とコメントが書かれた下にあるのは、順当にページをめくっていったときにどんな順番で内容を表示していくかの指定です。この時、先程ファイル一覧のところで各ファイルに与えたIDで並び順を指定しています。XHTMLのなかで使われるだけのCSSファイルや画像ファイルは当然ここには登場しません。

OEBPS/toc.ncx

このファイルの中には、本の目次情報が入っています。例えばiBooksではこのファイルをもとにちゃんと目次ページを生成してくれるので『二章三節まで読んだ』とかそういうアクセスが簡単にできます。目次項目には『~.html#foobar』のようにファイルの途中をIDで指定することも出来るので、XHTMLファイルを正しくマークアップしておけば、整然とした目次を作ることが出来ます。

とりあえず中身を見てみましょう。

<?xml version="1.0" encoding="UTF-8"?>
<ncx
	xmlns="http://www.daisy.org/z3986/2005/ncx/"
	version="2005-1">
	<head>
		<meta name="dtb:uid" content="d.hatena.ne.jp/HowManyFiles/book001"/>
		<meta name="dtb:depth" content="1"/>
		<meta name="dtb:totalPageCount" content="0"/>
		<meta name="dtb:maxPageNumber" content="0"/>
	</head>
	<docTitle>
		<text>タイトル</text>
	</docTitle>
	<docAuthor>
		<text>著者</text>
	</docAuthor>
	<navMap>
		<navPoint id="html-001" PlayOrder="1">
			<navLabel>
				<text>第一章</text>
			</navLabel>
			<content src="001.html"/>

			<vavPoint id="html-001-001" PlayOrder="2">
				<navLabel>
					<text>第一章一節</text>
				</navLabel>
				<content src="001.html#c001"/>
			</navPoint>
		</navPoint>
	</navMap>
</ncx>

なんかまた複雑ですが、ここもパート別に見ていけばなんてことは無いです。

head要素の中身は、そんなにいじることはないはずです。唯一変更すべき場所は、最初に書かれたmeta要素のidで、これはcontent.opfで指定したidと同じものを指定しておけばいい感じです。このへんなんだか冗長な感じがしますが、たぶん色々都合があるんだと思います。

同じように、docTitle要素とかdocAuthor要素とかも、content.opfで指定したものと同じにしておけばいいと思います。iBooksで試してみたところ、基本的にcontent.opfに書かれた情報が使用されるみたいですが、そこはきっと環境によりけりなので、トラブルを防ぐ意味でも同じ内容にしておいたほうがいいんじゃないでしょうか。

navMapの部分に関してはXHTMLで言うところの入れ子リストみたいなもんだと思えばいいです。目次を階層化出来るというか。基本的には目次はnavPoint要素の集合体で、navPoint要素の中にnavPoint要素が入っていることがあります。まあ、実際には精々二階層くらいまでで、そんなに派手に多層化することはないと思います。

navPoint要素には必須の属性値が二つあり、一つはidで、これは他とかぶってなきゃなんでもいいです。もう一つは PlayOrder で、これはnavPoint要素の登場順に1から数字が割り振られます。

navPoint要素の中にはnavLabel要素とcontent要素が入っています。navLabel要素の中に更にtext要素が入っていて、そこに目次として表示したい文字列が書かれています。で、content要素は空要素で、src属性値によって、コンテンツの場所を指定します。で、入れ子リストみたいな感じで、navPointのなかにはさらにnavPointを入れることが出来ます。

navMapに登場してないXHTMLファイルであっても、目次に載らないというだけで、端末のページを捲っていけば普通に読めます。基本的にはきちんと目次を作ることが望ましいと思うのですが、ゲームブックとかではあえて目次には載せないページがあってよいいんじゃないかと思います。

文章を構成するファイル達

XHTMLファイル

これがEPUBの本分を構成する主たるパーツになります。他のファイルはいわばEPUBとしての体裁を整えるためのお飾りみたいなもんです。基本的にはまともなXHTMLであればそれほど問題ないですが、貴方がまともだと思っているXHTMLが実は糞みたいなものだって可能性は捨てきれないので、一度きちんとXHTMLの仕様を勉強してみることをおすすめします。

CSSファイル

これも普通のCSSファイルであれば、基本的にそんなに問題は起きないはずですが、EPUBの仕様上使えないプロパティが結構あったりします。例えば背景画像や背景色を指定することは出来ないですし、『position:fixed』とかでページヘッダみたいなものを実現することも出来ないです。また、EPUBの仕様上使えるはずのプロパティでも、EPUBを表示させるアプリケーションによってかなり対応の度合いが違うと思います。このへんに関しては、iBooksに関してのみ続編のエントリで纏めようと思います。その他の端末に関しては知らん。

画像ファイル

PNGやらJPEGなどの無難なファイル形式であればあまり問題は無いと思います。血迷ってJPEG2000とかつかおうとしなけりゃ大丈夫。

次回予告

次のエントリで、具体的に『どうやって自分が書いたテキストやらXHTMLからEPUBを作るのか』を説明しようかなと思います。今回のは、とりあえず自分で読み解くのが面倒くさそうな、仕様上作らなきゃいけないファイルに関しての説明でした。