29 Jan 2010

Design of an NCX handler class in C#

Figure 1. shows a revised design for the Book Content screen of the online wysiwyg epub editor I'm developing.

Click to see the full image
Figure 1. Book content and editing screen

The main changes to the design are as follows:
  • The TreeView display of the NCX (Table of Contents) is replaced by a Repeater control. This allows more flexibility in the management of the NCX. This post explores the functionality required by a C# class that maintains the NCX document of an epub publication; access to that functionality is achieved through the Repeater control in a way that isn't so easy with a TreeView. Each document now has a checkbox beside it, allowing the document to be selected for action.
  • A dropdown list of actions that can be applied to one or more selected content documents. This is the key feature that gives access to NCX management functionality and includes the following actions:
    • Remove one or more content documents from the publication.
    • Move a content document up or down in the reading order.
    • Insert a new content document before or after a given document.
    • Change the text that appears in the table of contents for a given document.
  • The TinyMCE editor configuration has been enriched so the author has more control over the initial styling of the text (but remember, features like selected font, font-size, and text/background colouring should be left to the reader who makes personal presentation choices when using a reading device). The new editor configuration also allows the more technical author to view the XHTML for the current content document.
  • When the user wants to add a content document, they now have the ability to specify the following items:
    • The name of the file where the new content should be written.
    • The document heading that should appear at the start of the content.
    • The text that should appear in the table of contents.
In Figure 2. the Actions dropdown list is shown expanded. This list provides the structure for much of the remainder of this post, with the addition of the following methods and properties:
  • A constructor that, given an NCX document, will instantiate the class.
  • A method for saving changes to the NCX back to disk. In the current design, changes are only written to the .epub file when the entire publication is saved.
  • Properties that allow the following items in the NCX to be set programmatically:
    • The title of the publication in the docTitle/text element.
    • The author of the publication in the docAuthor/text element.
    • The unique identifier of the publication in the meta element which has a name attribute of dtb:uid
    • The document publisher in the meta element which has a name attribute of epub-creator.
Click to see the full image
Figure 2. Actions on content documents

This editor application contains a class called 'ncx' which we will now examine.

Constructor
An instance of the ncx class is created by its constructor. An NCX is an XML document, so much of the functionality of NCX management is concerned with XML operations - finding individual nodes, getting and setting attribute values, managing NameSpaces etc.

The ncx constructor is given the filepath to the ncx document. This was extracted from the .epub file when the current book was selected. The <spine> element of the <package> has a toc attribute. This holds the identifier of the <manifest> item which gives the href of the NCX file. The path to this file is passed to the constructor.

The ncx document is loaded and parsed, then key nodes are extracted as follows:
  • <docTitle><text>Book Title</text></docTitle> - allowing the book's title to be easily read and written using the Title property.
  • <docAuthor><text>Author name</text></docAuthor> - allowing the book's author to be easily read and written using the Author property.
  • <head><meta name='dtb:uid'/> - allowing the unique identifier of the publication to be easily read and written using the Identifier property.
  • <head><meta name='epub-creator'/> - allowing the publisher to be easily read and written using the Publisher property.
Save
The converse of the constructor, where the NCX is read and parsed, the Save method writes the updated NCX back to disk. After it has been saved by this method, the new NCX will be saved to the .epub file the next time the publication is saved.

Remove
What does it mean to remove a content document from an epub publication? Complete removal means performing the following actions:
  • Delete the <item> from the <manifest>.
  • Delete the <itemref> from the <spine>.
  • Delete the <navPoint> from the <navMap> in the NCX.
  • Delete the content document from the file system.
  • Rebuild the container (.epub file).
The ncx class is concerned only with managing the NCX document, so the Remove method deletes the <navPoint> from the <navMap>. To keep the <navMap> tidy, the method also renumbers the playOrder attribute of all <navPoint> elements that came after the removed document.

Insert After and Insert Before
Authors and publishers commonly want to reorganise and rearrange content. This might involve changing the order in which content documents are presented and that is the topic of the next section. It might also involve the insertion of new content into an existing publication. As discussed above with the Remove method, adding a content document requires work elsewhere in the <package> - the <manifest> and the <spine> must also be updated.

The ncx class methods InsertAfter and InsertBefore make the required changes to the NCX document. The required behaviour is as follows:
  • In both cases a new <navPoint> is added to the <navMap>. The <navLabel><text> element of the <navPoint> is set to the given text. The src attribute of the <content> element is set to the given filename.
  • The value given to the playOrder attribute of the <navPoint> will depend on whether the action is to insert the new document before or after a selected document:
    • When the new document is inserted before a selected document, the new document takes the playOrder of the selected document. The selected document and all following <navPoint> elements have their playOrder incremented to move them down the reading order.
    • When the new document is inserted after a selected document, the new document takes the playOrder of the next document. That document and all following documents have their playOrder incremented, again moving them down the reading order.
Move Up and Move Down
To move a content document up or down in the reading order is relatively straightforward. The only requirement is to swap the playOrder values of two adjacent <navPoint> elements.

When a given document is to be moved up the reading order i.e. to be presented to the reader earlier, the playOrder of the given document is swapped with that of the previous document. When a document is to be moved down the reading order, it will swap playOrder values with the content document that follows it in the current reading order.

Of course, the <navMap> nodes must be sorted by playOrder before they are bound to the user interface controls. Only then will the table of contents look as expected.

The <spine> element of the <package> document also holds the linear reading order of the publication. Any changes made to the NCX should also be reflected there, but those actions are outside the scope of the ncx class.

Rename
The Rename method allows the content provider to change the text that describes a content document as seen in the table of contents. The action of this method is to store the given string in the <navLabel><text> element of the given <navPoint>.

Properties
The following properties provide convenient access to the elements and attributes of the NCX document that aren't part of the document navigation (navMap).

Title
Gets or sets the publication title, held in the <docTitle><text> element.

Author
Gets or sets the publication author, held in the &t;docTitle><text> element.

Identifer
Gets or set the unique identifier of the publication which is held in the content attribute of the <head><meta> element with its name attribute set to dtb:uid.

Publisher
Gets or sets the publisher name which is held in the content attribute of the <head><meta> element with its name attribute set to epub-creator.

Article Navigation
Developing an epub editor << Previous   Next >>
Exploring epub standarda: Introduction

21 Jan 2010

Online Epub Editor Project: Technical Notes

This post adds some technical notes to the Inside Epub articles which explore the epub standards and show how to write an online wysiwyg epub editor. The following topics are covered:
  • Using the DotNetZip library to open and save an ebook
  • Checking the validity of your .epub files
  • Using the Sandcastle Help Builder to document code
  • Sorting an NCX navMap by playOrder
Using the DotNetZip library to open and save an ebook
I chose the DotNetZip library for this project because it looked well documented and seemed to offer the functionality I wanted. All was fine until I submitted an epub for validation using the facility provided by Threepress (see Checking the validity of your .epub files, below).

There were a few simple problems to resolve but the most persistent was a report that the mimetype file did not contain the expected information (application/epub+zip). The file clearly did have the correct information in it so I suspected the zipping wasn't working correctly.

The rules for the ZIP Container in the Open Container Format Specification state:
The first file in the ZIP Container MUST be a file by the ASCII name of ‘mimetype’ which holds the MIME type for the ZIP Container (i.e., “application/epub+zip” as an ASCII string; no padding, white-space or case change). The file MUST be neither compressed nor encrypted and there MUST NOT be an extra field in its ZIP header. If this is done, then the ZIP Container offers convenient “magic number” support as described in RFC 2048 and the following will hold true:


  • The bytes “PK” will be at the beginning of the file
  • The bytes “mimetype” will be at position 30
  • The actual MIME type (i.e., the ASCII string “application/epub+zip”) will begin at position 38 
I made a couple of mistakes when building the epub the first few (many) times. Figure 1. shows one of my earlier attempts which I opened in Notepad to view the characters in the zipped file (remember it's in Zip format so you can't expect to see normal text). You can see that, although the mimetype is the first file in the archive, the file shouldn't have the long folder path 'eBookTemp/Inside epub/' and the 'application/epub+zip' doesn't start at position 38.

Click to see the full image

Figure 1. Badly constructed epub

It was clear that I couldn't simply write:
using (ZipFile zippedBook = new ZipFile())
{
     zippedBook.AddDirectory(ebookPath);
}
where ebookPath was the folder holding the epub files. I had to make sure that the mimetype was uncompressed and started at the right position in the file. I evolved the following code to achieve this:
zippedBook.ForceNoCompression = true;
zippedBook.AddEntry("mimetype","","application/epub+zip");

zippedBook.ForceNoCompression = false;
zippedBook.AddDirectory(_fileSystemPath + "META-INF","META-INF");
zippedBook.AddDirectory(
    _fileSystemPath + _package.PackagePath,_package.PackagePath);

zippedBook.Save(_ebookPath);
The 'ForceNoCompression=true;' ensures that mimetype is not compressed. This is followed by 'ForceNocompression=false;' to compresss the rest of the epub. With this code, the application produced an epub file that looked like Figure 2. when opened in Notepad.

Click to see the full image

Figure 2. Well constructed epub archive

This file passed the epub validation check discussed below.

The other side of the coin with respect to epub files is how to expand an epub archive so you can work with its files. I developed the following code to do this:

foreach (ZipEntry ze in zippedBook.Entries){
   ze.ExtractExistingFile = ExtractExistingFileAction.OverwriteSilently;
   if (ze.IsDirectory){
     Directory.CreateDirectory(fileSystemPath + Path.GetDirectoryName(ze.FileName));
  }
  else{
     ze.Extract(fileSystemPath);
  }
}
Checking the validity of your .epub files
There are some important tests to perform to be sure the online epub editor is working correctly. Perhaps the most obvious is whether its output can be loaded into a reading device. That could be deceptive, though, because the reading software on one reading device might be more rigorous and compliant than on another.

Another way is to use a tool that validates epub publications. I found one of these at Threepress, as shown in Figure 3. The underlying tool is a software project called epubcheck.

Click to see the full image

Figure 3. ePub validation of Inside Epub.epub

You could argue that this is also software and it may have bugs in it, and you'd be right. Given the wide and rapidly growing range of Zip tools, epub conversion tools, and reading software around, some confirmation of compliance to standards is required and tools like epubcheck will become an important way of ensuring readers will not be disappointed.

It was a great relief, therefore, that I overcame my initial difficulties with building a conforming OCF epub file and received the big green tick from epubcheck.

Using the Sandcastle Help Builder to document code
Microsoft and others provide several tools and techniques for documenting code in the MSDN style, as in this example of the System Class Library.
  • When using Visual Studio, you enable XML comments on the Build tab of Project | Properties. Then you can use the triple slash (///) notation to add XML-style documentation to your source code. See Figure 4. for a sample. The comments are needed for every Namespace and for every public Class, including all its Public members - methods, properties etc. As soon as you type /// before one of these items, the Visual Studio IDE creates the comment structure with an initial <summary> and, if it's a method, with <param> elements appropriate to the method's signature.
  • Tools are available to extract the comments by reflection on the binary files of your application and to build navigable documentation like the MSDN example above. I've used Ndoc before so I thought I would try Sandcastle Help File Builder.
I've made a preliminary pass through the code adding XML decoration, as it's called. Figure 4. shows an example of this. There are guidelines for XML documentation comments which list and explain the appropriate XML grammar.

Click to see the full image

Figure 4. XML decoration of source code

The Sandcastle Help File Builder needed a little configuration. I set values for the following in the Project Properties:
  • HelpFileFormat, set to 'Website'
  • OutputPath, set to the folder where the output should be written.
  • WorkingPath, set to a folder where work files can be created.
You click on the Build icon and wait five minutes while Sandcastle works its magic. You can see the results in Figure 5. and also at Inside Epub Class Library.

Click to see the full image

Figure 5. Sandcastle 'Website' output

Sorting an NCX navMap by playOrder
The NCX document of an epub publication holds information, in XML format, about the structure of the publication. Its most important feature is a hierarchical list of 'navigation points' showing how the publication is subdivided. This list can be used by software in a reading device to provide access points allowing the reader to select directly what they want to view.

The root of the navigation data is the <navMap> element. This contains a hierarchical set of <navPoint> elements. Figure 6. shows a sample <navMap>.

Click to see the full image

Figure 6. Sample NCX showing its navMap

A <navPoint> element holds the text to be displayed to the reader in the <navLabel> element. It also tells the reading software where to go for the content document; this is held in the src attribute of the <content> element.

The topic of this Technical Note is the playOrder attribute of the <navPoint>. The playOrder attribute holds a number specifying the sequence in which the <navPoint> details should be presented to the reader.

It's important to distinguish the playOrder sequence from the sequence in which the <navPoint> nodes are held within the <navMap>; they don't have to be the same. In general, you can't assume anything about the way a content provider has built the <navMap>.

For instance, supposing a publisher is working on a 'flat' document i.e. one with only one level in the <navPoint> hierarchy. If a new content document needs to be inserted between two documents with playOrder values of 5 and 6, the publisher might add the new <navPoint> as the last node in the <navMap>; they would give the new <navPoint> a playOrder value of 6, and increment the playOrder of all <navPoint> elements that need to follow it in reading order.

What this means is that before presenting the navigation details to the reader, the <navPoint> nodes need to be sorted by their playOrder attribute. There are several approaches that could be taken, but the one described here is to use an XSL transform.

The following listing shows one possible transform.

1   <?xml version="1.0" encoding="utf-8"?>
2     <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3        <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="utf-8"/>
4        <xsl:template match="node()[local-name()='navMap']">
5           <xsl:element name="navMap">
6               <xsl:apply-templates select="node()[local-name()='navPoint']">
7                 <xsl:sort select="number(@playOrder)" data-type="number"/>
8               </xsl:apply-templates>>
9           </xsl:element>
10      </xsl:template>
11      <xsl:template match="node()[local-name()='navPoint']">
12         <xsl:copy-of select="."/>
13     </xsl:template>
14 </xsl:stylesheet>
At line 3, the <xsl:output> statement declares that the output is to be an XML document which includes an <?xml ?> declaration and is encoded in UTF-8.

Lines 4-10 of the transform find and process the <navMap> element.

At line 5 a new <navMap> is generated in the output.

At line 6, the transform handles the <navPoint> elements. The corresponding template at lines 11-13 returns a copy of each <navPoint>.

Line 7 is the key to the whole transform. It sorts the returned <navPoint> elements using the playOrder attribute.

The end result is a <navMap> in which the <navPoint> elements are in the order in which they should be presented to the reader.

Calling the transform in C#
The calling sequence for using this transform in C# can be something like the following:
// load the transform into an XslCompiledTransform instance
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(MapPath(".") + "/TransformNavMap.xsl");

// prepare an XmlWriter to write the transform output
StringBuilder newNavMap = new StringBuilder();
XmlWriter writer = XmlWriter.Create(newNavMap , xslt.OutputSettings);

// sort the book's navMap using the transform
xslt.Transform(book.container.package.ncx.NavMap, writer);
writer.Close();
Now the new <navMap> can be retrieved as an XmlDocument using newNavMap.ToString();

19 Jan 2010

User interface for an online epub editor

This article looks at the minimum requirements for an online epub editor and how they have been implemented in the sample application. The scope is limited to handling the editor's functionality - how to create, save, edit, and view .epub publications. It excludes the supporting features like user login, disk space management, uploading and referencing images. Those are important topics but they are common to many online applications, so I don't want to reinvent them here.

Requirements Summary
To refine further the scope of this project, an epub editor should include the following abilities:
  • Select an existing epub book for viewing or amendment.
  • Open a selected epub book and view its contents - including its metadata.
  • Navigate around a book using its NCX table of contents.
  • Edit a section and save its contents.
  • Add a new section to the book.
  • Remove a section from the book.
  • Change the reading order of the content documents.
  • View the book's metadata.
  • Edit and save the book's metadata.
  • Save the book to its .epub file.
  • Create a new epub book.
Not included, for this first version of the editor, are:
  • Adding multiple instances of metadata items, such as title, identifier, language, creator, etc.
  • Implementing Save As to an .epub with a different name.
Application Overview
Figure 1. shows a screenshot of the online editor. A menu gives access to different views of the application. It has options called:
  • Books - showing a list of epub books in the user's 'library'.
  • Book Information - displaying the metadata for the selected book.
  • Book Content - displaying the table of contents for the selected book.
  • Media - listing the non-text media items (e.g. images) that are part of the selected book.
  • Styles - listing the CSS files that are associated with the selected book.
Click to see the full image
Figure 1. Viewing a list of books

Select an existing epub book for viewing or amendment
Figure 1. shows the application positioned on the 'Books' view. The screen below the menu comprises a ListBox and a button showing the text 'New epub'.

The ListBox displays the .epub files that are in the user's library, where 'library' is defined as a folder on the web server that hosts the application. In this example, I've added an item to the <appSettings> in the web.config file of the application which provides the path to the library folder. This is shown in Figure 2.

Click to see the full image
Figure 2. epub library configuration

When the user selects a book, by clicking on it in the list, the application reads the .epub file using the ZipFile entity of the DotNetZip library. Using the ExtractAll method of that class the contents of the .epub are written to the file system. All subsequent operations, like changing a document or adding a document, are carried out on files rather than on the in-memory zipped data. However, the .epub file is kept upto date after each saved change.

In a multi-user application a more sophisticated approach would be required to keep each user's library separate from all others and under the protection of an access control mechanism. There are similarities with blogging sites and Content Management Systems.

The 'New epub' button, unsurprisingly, is where the user will start creating a new epub publication from scratch.

Viewing and changing metadata
Figure 3. is a screenshot after the user selects a book and then clicks on the 'Book Information' tab.

Click to see the full image
Figure 3. epub metadata

The application displays the metadata items that are found in the <metadata> section of the book's package document. The display is created using an ASP.Net Repeater control which is bound to the <metadata> node, so it displays all of the items found there and only the items found there. Further, it displays them in the order in which they appear, so the two <date> elements for instance are not together.

Edit and save a book's metadata
The information is displayed in TextBox controls, so it can be changed. The 'Save' button is used to update the metadata in the package document. We'll see later how the application saves the package data in the .epub file.

Some enhancements are needed to this model for a more flexible editor. For instance:
  • The ability to mark an entire .epub as read-only is desirable. If you don't own the intellectual property to a work, it's not appropriate to change it.
  • Some metadata items can occur more than once. Examples are: title, identifier, language, creator, contributor. It would be useful to be able to add and remove such items in the metadata.
Navigate around a book using its NCX table of contents
Figure 4. shows a screenshot similar to one in an earlier post and is the result of clicking on the 'Book Content' tab while a book is selected.

Click to see the full image
Figure 4. Navigating a book's contents

This screen uses a TreeView control to show a hierarchical table of contents. The TreeView is bound to a version of the navMap extracted from the book's NCX information. To the right of the table of contents is the area used to view and edit the text. This is a TextBox control associated with the tiny MCE Javascript, converting it into an editor control.

Edit and save content and add a new section
Beneath the reading/writing area in Figure 4. you can see the following controls:
  • A button marked 'Save'. This is used to save the current contents of the edit area to the underlying content document in the file system. 
  • A button marked 'Add' accompanied by two TextBoxes labelled 'Name' and 'Title'. The user enters the name for the content document in the Name box and the content heading in the Title box and clicks the Add button.
Figure 5. shows the results when Name is set to 'chapter01' and Title is set to 'Chapter 1'.

Click to see the full image
Figure 5. Navigating a book's contents

An empty content document called 'chapter01.xml' is created and the text 'Chapter 1' is inserted into the document heading. The application adds chapter01 to the package, meaning the content document is added to the <manifest>, the <spine>, and the <navMap> in the NCX document. The application navigates to the new document ready for the user to start typing. In this case, the user has typed some text into the editing area and pressed 'Save'.

Creating a new epub publication
It was shown above that there is a 'New epub' button on the 'Books' tab. Figure 6. shows the result of clicking that button.

Click to see the full image
Figure 6. Creating a new epub

The user is presented with a set of TextBoxes inviting input of basic metadata for the new book. The first three items - title, identifier, and language - are mandatory. The only item already set to a value is the identifier. In case you don't have your own ISBN number or other number that is globally unique, the application generates a GUID (Globally Unique IDentifier). You can use this or overwrite it with your own number.

Figure 7. shows the screen after each metadata item has been given a value and just before the 'Create' button is clicked.

Click to see the full image
Figure 7. metadata for the new epub

Figure 8. shows the results of clicking the 'Create' button. A new epub is created and the application shows the 'Book Contents' view. The user has entered and saved some text. Notice this is an almost empty publication, having only one content document.

Click to see the full image
Figure 8. The new epub waiting to be written

Figure 9. shows the 'Books' view after a new book is created. The list of books is updated to show the new title. Clicking on the new book opens it for viewing and editing just like any other book in the library.

Click to see the full image
Figure 9. New epub showing in the 'Books' list

Summary
This article has given a view of how an online wysiwyg epub editor might look. Details of the code can be found, shortly, in the reference section for the code project.

Undoubtedly, this is rough and ready. Many refinements would be required to make using this application a useful and pleasant experience. Among these are:
  • A much richer configuration of the tiny MCE editor to provide better formatting of the text.
  • Autosaving contents at short intervals.

Article Navigation
Developing an epub editor << Previous   Next >>
Exploring epub standarda: Introduction

14 Jan 2010

Develop your own epub editor

The previous posts in this series explored the structure of epub books and demonstrated how the epub standards work together to describe and package content documents. If you found those articles highly technical you might want to look away now - this post is the first of a series that shows how to create your own web-based, wysisyg editor that you can use to create epub documents. The programming strand of Inside Epub starts here. This post is an introduction to the subject and gives an idea of the development environment, the software tools, and the documentation that will be available as the project unfolds.

There are still topics to cover in the previous strand, like embedding XML islands in your content and handling fallback from non-standard to standard document types - and I will cover those in future. To help you choose the posts that match your interests, I've created a separate list of links for the code development and will join the posts in each strand with 'next' and 'previous' links.

Objectives - mine and yours
The aim of the programming strand of this blog is to create a web-based, wysiwyg epub editor. This will work only with epub documents and will be suitable for the creation of new ebooks. There's plenty of effort going into conversion of existing texts between formats so I don't feel the need to do that. If you believe that epub will become the format of choice for ebooks then why not create your book in epub directly? I don't claim that this application will be as powerful as Microsoft Word® with a 'Save As epub' add-in; it definitely won't be. My aim is to show you how you might set about creating a robust, online, multi-user epub editor.

To show you where we'll end up, Figure 1. shows a screenshot of the editor after opening the sample epub book The Curious Case of Benjamin Button. It has a menu across the top and the body of the page shows the result of selecting a book on the 'Books' tab and clicking on the 'Book Content' tab. This manages to look like Adobe Digital Editions but, being online, doesn't require you to download and install the reader.

At the moment we're not interested in style, only in functionality. If you want to see what might be possible by adding CSS styling, look at epub Zen Garden.

Click to see the full image

Figure 1. Web-based, wysiwyg epub editor

The application was written for the ASP.Net platform using Microsoft's Visual Web Developer 2008 Express Edition®. The programming language is C#.

On the left of the screenshot, a Treeview control is bound to the navMap of the NCX document in order to display the Table of Contents. To the right, an editor control shows the content of the Title Page.

Software Prerequisites
We've seen that epub publications are held as Zip archives and that epub packaging is achieved using a range of XML documents. Content documents are held in XHTML. To start developing an epub editor that runs on the .Net platform I chose the following range of free and/or open software tools:
  • Visual Web Developer 2008 Express Edition is used as the main development platform. There are more recent versions of this toolkit available, in beta testing at the time of writing, if you must have the latest. The tool enables the development of ASP.Net websites and includes extensive XML handling. The NCX file requires transformation before it is bound to the Table of Contents control and Visual Web Developer has facilities for using XSLT transforms.
  • DotNetZip library is used to manipulate Zip files in the C# .Net environment. Follow the stratightforward installation instructions. The ZipFile class of this library is used to open .epub files and to extract the contents to a folder on disk. It is also used to refresh the archive when a content document is changed or when documents are added or removed.
  • tiny MCE is a widely used Javascript editor which converts an ASP.Net TextBox control into an editor that outputs XHTML documents. The WordPress blogging site and the Joomla Content Management Software use this technology. The installation instructions are easy to follow. Configuration is a bit harder so, for the purposes of these posts, I'm keeping it simple.
Prototyping Approach
My favourite approach to using visual development tools is prototyping and this is especially true if I just want to demonstrate some techniques. It's really easy to throw a website together using Visual Web Developer but, having said that, the object-oriented approach required by C# means we need to give some thought to the classes of object that will be required.

Data Model
Figure 2. shows the data model for an epub document drawn, literally, on the back of an envelope.

Click to see the full image

Figure 2. epub data model

Each node in this model will be developed either as a C# class or will be accessible as an XMLNode within one of those classes.

Example Class epub
Figure 2. shows the class epub which is used to model the contents of an epub file. Most of the code is hidden in this image to enable you to see the structure. The class has Members, Constructors, Methods, and Properties.

Click to see the full image


Figure 2. epub class

In order not to clutter the posts in this thread, reference material for the code project, including class definitions, can be found at: Inside Epub Code Reference

That's it for setting the scene. Next time I'll look at the user interface.

Article Navigation
Developing an epub editor << Previous   Next >>
Exploring epub standarda: Introduction

Inside Epub Code Reference

Documentation for the Class Library developed for this project is available at www.hazelhurst.net/insideepub/

Class epub

This class models an epub ebook. The approach is taken that the Zip handler will be used only to open and save a .epub file. All other operations will use the files in the folder to which the Zip file is extracted.

epub Members
Class epub exposes the following members:

Property
Description
_container
_container is a private instance of class container. It gives access to the rest of the epub documents in the ebook, mainly through its package instance.
_filePath
_filePath is a string holding the location in the file system where the .epub for this instance of epub is located.

epub Constructor
The class has a constructor with the signature:
public epub(string ebookPath, string fileSystemPath)
This allows the caller to create an epub instance which will locate and open the ebook at location ebookPath. The ebook is extracted from the .epub and written to the file system at location fileSystemPath.

epub Methods
Class epub exposes the following methods:

Method
Description
Create
Creates a new epub ebook with the given title at the given location. Uses the given working folder path to store the files that will be zipped into the .epub.
Open
Open an existing .epub file and expand it into the given working folder.
Save
Save the epub instance as a .epub file at the given location.
SaveEntry
Save the given text of a content document.

epub Properties
Class epub exposes the following properties:

Property
Description
container
Get or set the container instance belonging to the current instance of epub. This property is widely used to gain access to most of the ebook's package and NCX data.

Code of the epub class (14Jan10 14:20)
The code of the epub class is shown below.

#region using
using System;
using System.IO;
#endregion

namespace net.hazelhurst.epub
{
public class epub
{
#region Members
private container _container;
private string _filePath;
#endregion

#region Constructors
public epub(string eBookPath, string fileSystemPath)
{
Open(eBookPath, fileSystemPath);
}
#endregion

#region Methods
public static epub Create(string title, string booksPath, out string workPath)
{
epub result = null;
string emptyBookPath;

workPath = booksPath + title + "\\";
if (!Directory.Exists(workPath) && !File.Exists(booksPath + title + ".epub"))
{
string newbook = booksPath + title + ".epub";
emptyBookPath = booksPath + "empty\\";
File.Copy(emptyBookPath + "empty.zip", newbook);
result = new epub(newbook, workPath);
result.container.package.Title = title;
}
else
{
throw new Exception("A book with that title already exists");
}
return result;
}
public bool Open(string eBookPath, string fileSystemPath)
{
bool bookOpen = false;

_filePath = eBookPath;

// get the book's container
_container = new container(eBookPath, fileSystemPath);

// if the container is available
if (_container != null)
{
bookOpen = true;
}

return bookOpen;
}
public bool Save()
{
bool result = false;
_container.Save();
//ZipFileHandler.Save(Title, filePath, outputPath);
return result;
}
public bool SaveEntry(string fileName, string content)
{
bool result = false;

try
{
_container.SaveEntry(fileName, content);
}
catch (Exception ex)
{
throw ex;
}
return result;
}
#endregion

#region Properties
public container container
{
get
{
return _container;
}
set
{
_container = value;
}
}
public string Title
{
get { return _container.package.Title; }
set { _container.package.Title = value; }
}
#endregion

} //epub
}

6 Jan 2010

OPS and PDF in one OCF container

I showed you what an OCF container file looked like in the topic: How the standards work together. Here it is again:

Click to see the full image

Figure 1. Container with one <rootfile> element

The container is always called container.xml. The example has a <rootfile> element in it that points to the OPF package file ebp.opf in folder OPS. That folder also holds all of the other items in the manifest.

A key strength of epub is that it delivers text that will fit easily on any size of reading device, from the smallest smartphone to the largest PC monitor. Text will flow smoothly from one screen to the next regardless of the size of screen or the size of font that the reader prefers.

Supposing you want to give the reader the ability to print the book in an attractive format. PDF would be a good choice for this. Sites like Smashwords offer separate downloads of epub and PDF versions of a book, but they could be bundled together using the Open Container Format. The OCF is a general-purpose container specification and you can store more than one version of your publication in it.

Figure 2. shows container.xml for a sample book available in the IDPF forums. The book contains some Sherlock Holmes stories and Figure 2. shows how two renditions of the text - OPS and PDF - are represented:

Click to see the full image

Figure 2. Container with two renditions

Quite simply, there are two <rootfile> elements present, one for each rendition:
<rootfiles>
   <rootfile full-path="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
   <rootfile full-path="PDF/Holmes.pdf" media-type="application/pdf"/>
</rootfiles>
The first <rootfile> identifies the OPF package, as in the earlier example. Reading software designed to handle OPF packages would render the book using information contained in this <rootfile>.

The second <rootfile> points to the file Holmes.pdf in folder PDF and the media-type indicates that this should be handled as a PDF file. Here, then is the alternate rendition for the text. Notice that the container follows the OCF recommendation that alternate renditions should be placed in dedicated folders. Figure 3. illustrates this by showing the folder structure in a WinZip® view of the epub file.

Click to see the full image

Figure 3. Dedicated folders for alternate renditions

The PDF file is held in a distinct folder in the Zip archive.

Not now, but in the future, you may be able to store more than one publication in an OCF container, for example the complete works of an author held as separate ebooks. This would require the reading software to read the container and present the list of contained ebooks to the reader.

Article Navigation
Next >>

5 Jan 2010

NCX navigation in epub books

We saw in an earlier post how the <spine> element in the package document is used to provide a linear reading order for the content documents of an epub publication. An ebook reader could use the spine data to retrieve and chain together the book's content documents and present them to you, starting at the first screen of the first document.

But, suppose you're looking at Victor Hugo's Les Misérables and you want to find the passage where Jean Valjean is carrying the wounded Marius through the sewers of Paris. How to find it? You don't want to scroll forwards through the book from the beginning (my Penguin Classics version has 1200 pages and I'd be looking for page 1083). What you need is a Table of Contents that would guide you to Part Five, Book III, Chapter III. The epub specifications make this possible through the use of an XML document that follows yet another open standard.

The DAISY Consortium and NCX
The Digital Accessible Information System consortium is an organisation aiming "to lead the worldwide transition from analog to Digital Talking Books." As such, they have been heavily involved in developing and maintaining information standards. The DAISY/NISO standard entitled DAISY Specifications for the Digital Talking Book is the basis of the approach taken by the International Digital Publishing Forum (IDPF) to providing a Table of Contents in an epub publication.

The standard has an acronym. It's called NCX. The Open Packaging Format specification offers two meanings for the acronym:
  • Navigation Center eXtended
  • Navigation Control for XML applications
Take your pick, it doesn't really matter. The important thing is that the standard is followed. To give you immediately an idea of how NCX can be used to present a Table of Contents, take a look at Figure 1.

Click to see the full image

Figure 1. NCX for The Curious Case of Benjamin Button

The screenshot in Figure 1. shows the NCX document that's shipped with the epubBooks version of The Curious Case of Benjamin Button. In this view, I've collapsed the <head>, <docTitle>, and <docAuthor> elements in order to concentrate on the <navMap> information.

A simple NCX example
A book can be said to have a hierarchical structure - it may have Parts which comprise Chapters which in turn may be divided into Sections and Sub-sections. This hierarchy is expressed in the navMap section of the NCX document. Starting with our simple example, which has no hierarachy to speak of, take a look at Figure 2, below.
<navMap>
   <navPoint id="navpoint-1" playOrder="1">
      <navLabel>
         <text>Title Page</text>
      </navLabel>
      <content src="title.xml"/>
   </navPoint>
   <navPoint id="navpoint-2" playOrder="2">
      <navLabel>
         <text>epubBooks Information</text>
      </navLabel>
      <content src="epubbooksinfo.xml"/>
   </navPoint>
   <navPoint id="navpoint-3" playOrder="3">
      <navLabel>
         <text>1</text>
      </navLabel>
      <content src="chapter-001.xml"/>
   </navPoint>
Figure 2. A simple navMap

The <navMap> element can have any number of <navPoint> elements. Each <navPoint> identifies a significant subdivision of the book to which the reader may navigate directly - for instance to the start of a given chapter. The <navPoint> element has attributes 'id' and 'playOrder'. 'id' is a unique identifier and 'playOrder' is a number, starting from 1, that indicates the position of the navPoint in the sequence of content documents making up the publication.

A <navPoint> element contains a <navLabel> element and a <content> element. The <navLabel> has a <text> element which holds the text that will be displayed in the Table of Contents. The <content> element has 'src' attribute that tells the reading software the name of the content document to display.

Figure 3. shows The Curious Case of Benjamin Button opened using Adobe Digitial Editions®. You can see how the <text> values from each <navPoint> are displayed in the Table of Contents.

Click to see the full image

Figure 3. NCX Table of Contents in Adobe Digital Editions®

When the reader clicks on chapter 1, represented by the imaginatively selected "1" in the Table of Contents, the reading software looks up the <content> element of that <navPoint> and fetches 'chapter-001.xml' for display.

An NCX with two levels
A <navPoint> may itself contain further <navPoint> elements. That is how the hierarchical structure of the book is expressed. In the simple example above the nesting is only one level deep, but take a look at Figure 4.
<navPoint id="navpoint-3" playOrder="3">
   <navLabel>
      <text>PART ONE</text>
   </navLabel>
   <content src="part-01.xml"/>
   <navPoint id="navpoint-4" playOrder="4">
      <navLabel>
         <text>CHAPTER I</text>
      </navLabel>
      <content src="chapter-001.xml"/>
   </navPoint>
   <navPoint id="navpoint-5" playOrder="5">
      <navLabel>
         <text>CHAPTER II</text>
      </navLabel>
      <content src="chapter-002.xml"/>
   </navPoint>

...intervening navPoints in Part One

</navPoint> (end of navpoint-3)
Figure 4. navPoints nested to two levels

The NCX extract in Figure 4. is taken from Jules Verne's 20,000 Leagues Under the Sea, also downloaded from epubBooks. I've changed the colour coding of the elements to show the hierarchical relationship between the navPoints.

navPoint-3 introduces Part One of the book. As before, it has a navLabel (PART ONE) and the content document is called 'part-01.xml'. Next is another navPoint within the Part One navPoint i.e. before the </navPoint> declaration. This indicates that the new navPoint and all of the navPoints up to the next </navPoint> belong to Part One of the book. Figure 5. shows how this looks in Adobe Digital Editions®

Click to see the full image

Figure 5. Two-level NCX

Notice how the chapter titles are indented within PART ONE. The standard does not impose any limit on the depth of nesting so if you're a corporate lawyer drawing up an eContract you can create sub-sections to your heart's content. Also, NCX doesn't impose names like part, chapter, and section to the structure of a book. It's left entirely to the publisher how they want to name these subdivisions; the NCX document holds whatever you choose in the navLabel/text entries.

Ebooks are nothing without the writing
To finish off this topic, I went and found my all-time favourite book, Les Misérables, and opened it in Adobe Digital Editions to locate that passage I mentioned earlier. Figure 6. Shows how epubBooks built the NCX for this book. They have three levels of nesting, dividing the work into Volumes, Books, and Chapters.

Click to see the full image

Figure 6. Jean Valjean carrying Marius

4 Jan 2010

A closer look at OPF

Let's take a closer look at the Open Packaging Format.

Recall from the previous post that an electronic publication conforming to the OPF standard must provide a package document. This must be an XML document with a root element of <package> which includes elements called <metadata>, <manifest>, and <spine>. Figure 1. shows an overview of the package document that is delivered with our sample epub ebook.

Click to see the full image
Figure 1. Package Overview

You can see this document has the correct set of package elements. Before looking at each in detail, there are two things I'd like to point out on this screenshot. First, the unique-identifier attribute in the <package>:
unique-identifier="EPB-UUID"
This attribute tells the software of the reading device to look out for a metadata item of type <dc:identifier> that has an 'id' attribute with the value 'EPB-UUID'. The value of this element is an identifier that is globally unique. Towards the bottom of the metadata, when we look at it, you will find the following element:
<dc:identifier   id="EPB-UUID">
     urn:uuid:CBC56AFC-6C29-1014-8672-92A1DF1F0AF1
</dc:identifier>
That 32-digit hexadecimal value is the GUID (Globally Unique Identifier) generated by epubBooks to identify this particular publication. Of course, an ISBN is another globally unique identifier, and if you are in the publishing business and routinely buy ISBNs by the dozen, you would probably insert the ISBN here.

Second, the attributes in the <metadata> element:
xmlns:opf="http://www.idpf.org/2007/opf"
xmlns:dc="http://purl.org/dc/elements/1.1"
indicate that the prefix 'dc' refers to the Dublin Core element definitions (see below for more detail), and that the 'opf' prefix refers to OPF extensions to the Dublin Core. For instance, look at the two date elements in the metadata:

<dc:date opf:event="original-publication">1922</dc:date>
<dc:date opf:event="epub-publication">2009-09-24</dc:date>
The 'dc' prefix on the 'date' elements identifies them as publication dates that follow the Dublin Core specification. The 'opf' prefix on the 'event' attribute identifies 'event' as belonging to the OPF specification.

Unfortunately, looking at the OPF specification, it seems the publisher is free to give the event attribute whatever value they like:
"The set of values for event are not defined by this specification; possible values may include: creation, publication, and modification."
Now, let's look in more detail at the package metadata.

Package <metadata>
The <metadata> element of the package can contain wide ranging information about the publication. To keep OPF as open as possible, the metadata of an OPF package makes use of another open standard, namely the Dublin Core Metadata standard.

The Dublin Core is an initiative working towards standard ways of describing resources. They actively promote standardised sharing information thereby increasing interoperability between organisations - let's all agree to call a spade a spade and not a shovel or a digger.

The Dublin Core has a wider scope than just ebooks. However, there is a rich set of attributes that can be applied to electronic publications. Figure 2. shows the metadata that epubBooks placed in the package of The Curious Case of Benjamin Button.

Click to see the full image
Figure 2. Package Metadata

For convenience, I'll list the metadata elements again here:
  • title
  • language
  • identifier
  • ---------
  • creator
  • date(s)
  • publisher
  • subject
  • source
  • rights
The elements above the dashed line are mandatory. The OPF Package Schema says that there must be at least one title, at least one language element, and at least one identifier element. All other elements are optional.

Title
In fact the schema says there must be 'One Or More' of the mandatory elements. In other words, there can be more than one title, more than one language, and more than one identifier. The standard does not specify which title should be displayed, only that a reading device should choose 'the most appropriate title' for display, perhaps based on available fonts or language.

Identifier
There can also be more than one identifier element in the metadata. We've seen above how the unique identifier is handled. If you wanted, you could publish an ebook with several identifiers: your internally generated identifier, a GUID, and your ISBN. You then have to say which is to be considered the globally unique identifier.

Language
The specification says there must be at least one <language> metadata element, but there may be more than one. I suppose if you were publishing an English-Mandarin dictionary or were writing a learned text about the Rosetta Stone you might have a reason to specify more than one language.

Full list of metadata elements
The following table summarises the full set of metadata elements that can appear in the <metadata> section of a <package>

Element
Number
Description
title
One or more
The title of the publication. As we've seen, there can be more than one, but there must be at least one title.
creator
Zero or more
The primary creators or authors of the publication. Each element is recommended to hold one name and is recommended to be in the form it should be presented to the reader. When there's more than one creator, it's expected they would be displayed in the order in which the elements appear in the metadata. Other contributors should be identified in <contributor> elements.
subject
Zero or more
The subject matter of the publication. There is no standardisation here. The optional text could be a sentence, a list of keywords, or one keyword per element.
description
Zero or more
The description(s) of the publication.
publisher
Zero or more
The publisher(s) of the publication.
contributor
Zero or more
The person(s) making contributions to the publication in a manner that is secondary to the role of creator. OPF defines nearly 30 different roles as contributor and specifies the syntax for their identification.
date
Zero or more
The publication date(s) for the publication. We've already seen that OPF extends the Dublin Core definition of this element, allowing different 'event' dates to be recognised.
type
Zero or more
The type(s) that describe the publication. This is relatively free-form although the specification recommends using words from controlled vocabularies i.e. selecting from a restricted set of words. Terms relating to genre e.g. Young Adult, Fantasy, Literary, might be used as well as terms like Fiction, Non-Fiction etc.
format
Zero or more
The media-types of the publication. The recommendation is to use a MIME type.
identifier
One or more
One or more identifiers for the publication, one of which must be defined as a unique identifier. See the discussion above.
source
Zero or more
Identification of any other documents or publications from which the current publication is derived.
language
One or more
One or more language identifiers.
relation
Zero or more
Identifier(s) of resources to which the current publication is related.
coverage
Zero or more
One or more identifiers of the scope of the publication. OPF recommends following the Dublin Core specification of coverage and to use a controlled vocabulary for geographical, temporal, and juridical descriptions.
rights
Zero or more
An assertion of the rights of the publisher/creator with respect to this publication.
Table 1. Package metadata elements

Package <manifest>
Figure 3. shows the <manifest> element of the OPF package for our sample epub ebook, The Curious Case of Benjamin Button.

Click to see the full image

Figure 3. Package Manifest

The package manifest identifies all of the resources that are needed to display the ebook fully and correctly. Each entry in the manifest consists of an <item> element, as in:
<item id="chapter-001" href="chapter-001.xml" media-type="application/xhtml+xml"/>
Each <item> element has an 'id' attribute which identifies this resource uniquely within the publication. It has an 'href' attribute which points to the content document, in the example above it's an XML document called 'chapter-001.xml'. The 'media-type' attribute in this example shows that the resource should be handled as an XHTML document.

You can see that the manifest lists 13 content documents: a title page, a page of information about the publisher (epubBooks), and the 11 chapters of the story.

Each content document includes a 'link' element that refers to the CSS stylesheet 'body.css'. Therefore, the manifest includes an <item> for it:

<item id="main-css" href="css/book.css" media-type="text/css"/>
The publisher information document, epubbooksinfo.xml, includes an image which is the company logo. Therefore, the manifest includes an <item> for it:

<item id="epubbooks-logo" href="images/epubbooks-logo.png" media-type="image/png"/>

The rule is: if the content documents use it, it must be in the manifest. There are some aspects of the manifest that will be reserved for a future post so they don't clutter up this presentation. These cover media-types that are not part of the OPS Core, Out-Of-Line XML Islands, and the use of fallback documents to support these non-standard documents.

There's one more item in the manifest, and it's quite an important one:
<item id="ncx" href="epb.ncx" media-type="application/x-dtbncx+xml">
The 'id' attribute is set to 'ncx', the 'href' points to a file called 'epb.ncx', and the 'media-type' indicates that the resource should be handled as an NCX document. NCX is a standard way of declaring a Table of Contents. It's another open standard, this time maintained by the DAISY consortium.

This leads us nicely into the description of the third mandatory element of an OPF package - the <spine> element.

Package <spine>
Figure 4. shows the expanded <spine> element of our sample package.

Click to see the full image

Figure 4. Package Spine

The <spine> starts off like this:
<spine toc="ncx">
   <itemref idref="titlepage" linear="yes"/>
   <itemref idref="epubbooksinfo" linear="yes"/>
   <itemref idref="chapter-001" linear="yes"/>
   <itemref idref="chapter-002" linear="yes"/>
The element has a 'toc' attribute with the value 'ncx'. This is the value of the 'id' attribute of the item in the manifest that points to the mandatory table of contents document. In other words, it's a way to identify the table of contents. We saw in the last section that the manifest item with an id of 'ncx' points to a document called 'epb.ncx'. We'll look at NCX documents in more detail in a future article.

The next thing to notice about the <spine> is that it contains a list of <itemref> elements. Each <itemref> has an attribute called 'idref', and the value of an idref is the id of an item in the manifest.

For example, the first idref has value 'titlepage'. Look back at the manifest screenshot and you'll see that the first content document in the manifest has id="titlepage", and that item points to the content document itself (titlepage.xml).

The spine is a list of content documents and the important thing about the list is that it specifies the linear order in which the content documents should be displayed: title page, followed by the publisher's information page, followed by chapter 1, etc.

The <itemref> element has an optional attribute called 'linear'. This attribute takes a yes/no value and is used to indicate whether the referenced document is primary or auxiliary. This can be used by reading devices to show auxiliary information in a different way from the main flow of the primary information. In our case, the values are all set to 'yes' which is the default.

3 Jan 2010

How the standards work together

In earlier posts I've referred to the Open Publication Structure, the Open Container Format, and the Open Packaging Format. What helps to make these specifications open is that they make widespread use of other, industry-wide, open standards like XHTML, XML, CSS, MIME, among others.

The IDPF standards documents make frequent reference to these other standards, and they all work together to make it possible for content providers - authors and publishers - to ensure that their publications are available on the widest range of reading devices. All they have to do is to create documents that conform to the standards. Likewise, hardware and software developers know that if they also follow the standards their reading devices will be able to display all conforming publications.

Three Standards
If you looked at the IDPF website you might be wondering why there are three standards documents for epub publications. The reason is that they address different aspects of an electronic publication. It's widely recognised in the industry that features like content and presentation should be stored separately. Just as content is stored in XML and presentation is stored in CSS, what is packaged in an epub document is described separately from how it is packaged.

Book Analogy
Imagine for a moment that you have in your hand a first edition copy of The Curious Case of Benjamin Button. The words that Fitzgerald used belong to a vocabulary - the English language. The Open Publication Structure defines the 'Preferred Vocabulary' of epub Content Documents - not the words you use to write a book, rather the XHTML elements that you use to create the structure of the book, building it into sections, chapters, and parts.

The paper book has several chapters that are printed in order (we hope). The book also has a title page and other items that are not part of the story but which book designers call Front Matter (Foreword, Preface, Acknowledgements etc.). The book may also have a Table of Contents in the Front Matter which helps the reader find their way around the content. The Open Packaging Format defines how all of these parts of an epub document should be described.

Finally, the book has a cover which binds the content into a single entity, as opposed to loose pages or separately bound chapters. The Open Container Format specifies how the electronic Package, which is all of the necessary information for the book to comply with the epub standards, is held as a unit. In abstract terms the output of this bundling together is called a Container. On your computer it might be represented as a folder in your file system or, as in our case, a Zip archive held in one file with the .epub extension.

Open Publication Structure
The Open Publication Structure is mostly concerned with which XHTML elements you can use to build a content document. Let's take a look at what we mean by a content document. The following image shows one of the shorter chapters from our sample ebook The Curious Case of Benjamin Button.

Click to see the full image
Figure 1. Sample Content Document

You can see from the first line that a content document is an XML document. The next declaration says that it contains an XHTML document which means it contains a version of HTML that can be held as valid XML.

If you're not sure about XML, take a look at the XML Tutorial at W3Schools

This is followd by the XHTML content itself. You can see the usual <html>, <head>, and <body> elements that make up an XHTML document. Let's look at the contents of the <head> element first:
<link rel="stylesheet" href="css/book.css" type="text/css"/>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"/>
<meta name="EPB-UUID" content="CBC56AFC-6C29-1014-8672-...">

 The <head> contains a <link> element that points to the external stylesheet called 'body.css' which can be found in the css folder. It also contains a <meta> element which declares that the content type of the document is 'application/xhtml+xml' and that the character encoding is UTF-8.

Now take a look at the <body> of the document:

<div class="body">
   <div class="chapter">
      <h3 class="chapter-title">6</h3>
         <p>When, six months later, the...</p>
         <p>The Sunday supplements of...</p>
         <p>However, every one agreed with...</p>
         <p>On the part of the two people most...</p>
      </div>
</div>
The <body> element contains two <div> elements, each with a different class, so that appropriate CSS styling will be applied. It contains a chapter title with <h3> styling, and four paragraphs elements (<p>).

What the Open Publication Structure tells you is which XHTML elements you can use to build a content document. The following extract from the standard shows how the elements we've just seen are defined as required elements that all conforming epub reading software must accept and render.

XHTML 1.1 Module Name
Elements
Structure
body, head, html, title
Text
abbr, acronym, address, blockquote, br, cite, code, dfn, div, em, h1, h2, h3, h4, h5, h6, kbd, p, pre, q, samp, span, strong, var
Meta-information
meta
Link
link
Table 1. Extract of Open Publication Structure Preferred Vocabulary

The standard refers to XHTML Module Names because XHTML can be subdivided into areas of functionality called Modules. This allows designers and developers to know what they can use and what they might find in a document that allows or requires the use of a given Module.

There is a lot more to write about Open Publication Structure, but this introduction serves to show that, at its simplest, it specifies what can go into a content document.

Open Packaging Format
The Open Packaging Format is a standard that defines how the contents of an epub electronic publication are identified and specifies how they should be presented. Recalling the post First look Inside an epub ebook, there's a file in the Zip archive called 'ebp.opf'. That .opf extension indicates that the file contains Open Packaging Format information.

In Figure 2. I've extracted ebp.opf from the Zip and renamed it as ebp_opf.xml. Then I've loaded the XML file into Visual Web Developer 2008 Express Edition and collapsed all but the root node and the first level of child nodes. This gives an overview of the package document.

Click to see the full image
Figure 2. Package Overview

The <package> node has three child nodes:
  1. A <metadata> node which holds a range of information about the publication as a whole. This list is quite long and includes such information as: title, creator, subject, description, publisher, creator.
  2. A <manifest> node which holds descriptions of every file making up the publication. The manifest lists all of the content files, style sheets that are referenced, and all images that are included in the content.
  3. A <spine> node that includes an ordered list of the content documents, effectively defining their reading order or the order in which they will be displayed by a reading device.
We'll look in more detail at these elements in a future post, but notice that the <spine> node has a 'toc' attribute. 'toc' stands for Table of Contents, and the value of this attribute is the unique identifier (id) of the document that contains the table of contents. In our example the value is 'ncx'. This means that the manifest will include an item which has an 'id' attribute set to "ncx" and the file that this item points to should be treated as the Table of Contents for the publication.

Open Container Format
Finally in this post giving an overview of how the IDPF standards work together, we'll take a quick look at the Open Container Format. Remember from the book analogy how the container binds all of the package contents together. The OCF defines how this should be done by defining a container system analagous to a set of folders in your file system.

The standard defines that there must be a file called 'mimetype' at the root level of the container and the mimetype file should comprise the ASCII string: "application/epub+zip". By so doing, reader software can confirm that the file it's been asked to open with extension .epub is intended to be an epub publication. There may be other problems that make it invalid, but the mimetype file is an assertion that the container and its contents should be handled as an epub document.

To further qualify as valid epub, the container file system must include a folder called 'META-INF' and that folder must contain a file called 'container.xml'. It may contain other files, which will be the subject of later posts in the blog, but it must have container.xml.

Figure 2. shows the contents of our container.xml, again opened in Visual Web Developer 2008 Express Edition.

Click to see the full image
Figure 3. OCF Container

container.xml has a root node called <rootfiles>. In our example there is only one <rootfile> and that points to the package file: 'OPS/ebp.opf'.

The standards working together
We've seen that our sample epub, The Curious Case of Benjamin Button, has satisfied the requirements of the Open Container Format - it has a valid mimetype file and a META-INF folder with a valid container.xml.

Reading software accessing the epub will open container.xml and use it to locate and open the Open Package Format information in the indicated .opf file. Typically, the Table of Contents will be opened and displayed and the first content document will be displayed in a viewing area.

The vocabulary of the content documents should hold no surprises for the reading software and it should be able to render the text with the structure and style indicated, including the display of any referenced images.

In this simple example, that is how the different IDPF standards work together. In subsequent posts we'll look at these features in greater detail, show how their scope is wider than I've shown so far, and also start looking at C# Class modelling of epub entities.