学习EPUB文件内部

547 阅读2分钟

电子书提供了一种在旅途中阅读书籍、杂志和其他内容的好方法。读者可以在长途飞行和乘坐火车时享受电子书来打发时间。最流行的电子书文件格式是EPUB文件,是 "电子出版物 "的简称。EPUB文件支持各种电子阅读器,是当今电子书出版的有效标准。

EPUB文件格式是一种基于XHTML的内容和XML的元数据的开放标准,包含在一个压缩文件档案中。由于一切都基于开放标准,我们可以使用普通工具来创建或检查EPUB文件。让我们来探索一个EPUB文件,以了解更多信息。今年早些时候在Opensource.com上发表的C语言编程技巧指南,可以用PDF或EPUB格式提供。

因为EPUB文件是XHTML内容和XML元数据的压缩文件,你可以从unzip 命令开始,从命令行检查EPUB。

$ unzip -l osdc_Jim-Hall_C-Programming-Tips.epub 
Archive: osdc_Jim-Hall_C-Programming-Tips.epub
Length Date Time Name
--------- ---------- ----- ----
20 06-23-2022 00:20 mimetype
8259 06-23-2022 00:20 OEBPS/styles/stylesheet.css
1659 06-23-2022 00:20 OEBPS/toc.xhtml
4460 06-23-2022 00:20 OEBPS/content.opf
44157 06-23-2022 00:20 OEBPS/sections/section0018.xhtml
1242 06-23-2022 00:20 OEBPS/sections/section0002.xhtml
22429 06-23-2022 00:20 OEBPS/sections/section0008.xhtml
[...]
9628 06-23-2022 00:20 OEBPS/sections/section0016.xhtml
748 06-23-2022 00:20 OEBPS/sections/section0001.xhtml
3370 06-23-2022 00:20 OEBPS/toc.ncx
8308 06-23-2022 00:21 OEBPS/images/image0011.png
6598 06-23-2022 00:21 OEBPS/images/image0009.png
[...]
14492 06-23-2022 00:21 OEBPS/images/image0005.png
239 06-23-2022 00:20 META-INF/container.xml
--------- -------
959201 41 files

这个EPUB包含很多文件,但其中大部分是内容。要了解EPUB文件是如何组合在一起的,请遵循电子书阅读器的工艺流程。

  1. 电子书阅读器需要验证EPUB文件确实是一个EPUB文件。他们通过检查EPUB档案根部mimetype 文件来验证该文件。这个文件只包含一行,描述EPUB文件的MIME类型。

    application/epub+zip
    
  2. 为了定位内容,电子书阅读器从META-INF/container.xml 文件开始。这是一个简短的XML文件,表明在哪里可以找到内容。对于这个EPUB文件,container.xml 文件看起来像这样。

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

    为了使container.xml 文件更容易阅读,我把单行分成多行,并在每行添加了一些间距来缩进。XML文件并不真正关心像新行和空格这样的额外留白,所以这个额外的间距并不影响XML文件。

  3. container.xml 文件说,EPUB的根从OEBPS目录下的content.opf 文件开始。OPF的扩展名是因为EPUB是基于开放包装格式的,但content.opf 文件实际上只是另一个XML文件。

  4. content.opf 文件包含一个完整的EPUB内容清单,加上一个有序的目录,并有参考文献来找到每一章或每一节。这个EPUB的content.opf 文件相当长,所以我在这里只展示一点,作为一个例子。

    XML数据包含在一个<package> 块中,它本身有一个<metadata>块、<manifest> 数据和一个<spine>块,其中包含电子书的目录。

    <?xml version="1.0" encoding="UTF-8"?>
    <package unique-identifier="unique-identifier" version="3.0" xmlns="http://www.idpf.org/2007/opf" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:opf="http://www.idpf.org/2007/opf">
    <metadata>
    <dc:identifier id="unique-identifier">osdc002</dc:identifier>
    <dc:title>Tips and Tricks for C Programming</dc:title>
    <dc:creator>Jim Hall</dc:creator>
    <dc:language>English</dc:language>
    <meta property="dcterms:modified">2022-06-23T12:09:13Z</meta>
    <meta content="LibreOffice/7.3.0.3$Linux_X86_64 LibreOffice_project/0f246aa12d0eee4a0f7adcefbf7c878fc2238db3 (libepubgen/0.1.1)" name="generator"/>
    </metadata>
    <manifest>
    ...
    <item href="sections/section0001.xhtml" id="section0001" media-type="application/xhtml+xml"/>
    <item href="images/image0003.png" id="image0003" media-type="image/png"/>
    <item href="styles/stylesheet.css" id="stylesheet.css" media-type="text/css"/>
    <item href="toc.ncx" id="toc.ncx" media-type="application/x-dtbncx+xml"/>
    ...
    </manifest>
    <spine toc="toc.ncx">
    <itemref idref="section0001"/>
    <itemref idref="section0002"/>
    <itemref idref="section0003"/>
    ...
    </spine>
    </package>
    

    你可以匹配这些数据,看看在哪里可以找到每个部分。这就是EPUB阅读器的做法。例如,目录中的第一项引用了section0001 ,它在清单中被定义为位于sections/section0001.xhtml 文件中。该文件的名称不需要与idref条目相同,但LibreOffice Writer的自动流程就是这样创建的。(你可以在元数据中看到,这个EPUB是在Linux上用LibreOffice 7.3.0.3版本创建的,它可以将内容导出为EPUB文件)。

EPUB格式

EPUB文件是一种使用开放格式发布内容的好方法。EPUB文件格式是XML元数据与XHTML内容,在一个拉链容器内。虽然大多数技术作家使用工具来创建EPUB文件,因为EPUB是基于开放的标准,意味着你可以创建自己的EPUB文件,在一些其他方式。