'Generate the OPF file.
Start with header template, construct manifest, spine and guide.
Inputs:
genres (list)
html_filelist_1 (list)
html_filelist_2 (list)
thumbs (list)
Updated:
play_order (int)
Outputs:
opts.basename + \'.opf\' (file): written'

def generate_opf(self):

    self.update_progress_full_step(_('Generating    OPF'))
    header = '\n                                                <?xml    version="1.0"    encoding="UTF-8"?>\n                                                <package    xmlns="http://www.idpf.org/2007/opf"    version="2.0"    unique-identifier="calibre_id">\n                                                                <metadata    xmlns:dc="http://purl.org/dc/elements/1.1/"    xmlns:opf="http://www.idpf.org/2007/opf"\n                                                                                                xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n                                                                                <dc:language>en-US</dc:language>\n                                                                </metadata>\n                                                                <manifest></manifest>\n                                                                <spine    toc="ncx"></spine>\n                                                                <guide></guide>\n                                                </package>\n                                                '
    soup = BeautifulStoneSoup(header, selfClosingTags=['item', 'itemref', 'meta', 'reference'])
    metadata = soup.find('metadata')
    mtc = 0
    titleTag = Tag(soup, 'dc:title')
    titleTag.insert(0, escape(self.opts.catalog_title))
    metadata.insert(mtc, titleTag)
    mtc += 1
    creatorTag = Tag(soup, 'dc:creator')
    creatorTag.insert(0, self.opts.creator)
    metadata.insert(mtc, creatorTag)
    mtc += 1
    if self.generate_for_kindle_mobi:
        periodicalTag = Tag(soup, 'meta')
        periodicalTag['name'] = 'calibre:publication_type'
        periodicalTag['content'] = 'periodical:default'
        metadata.insert(mtc, periodicalTag)
        mtc += 1
    manifest = soup.find('manifest')
    mtc = 0
    spine = soup.find('spine')
    stc = 0
    guide = soup.find('guide')
    itemTag = Tag(soup, 'item')
    itemTag['id'] = 'ncx'
    itemTag['href'] = ('%s.ncx' % self.opts.basename)
    itemTag['media-type'] = 'application/x-dtbncx+xml'
    manifest.insert(mtc, itemTag)
    mtc += 1
    itemTag = Tag(soup, 'item')
    itemTag['id'] = 'stylesheet'
    itemTag['href'] = self.stylesheet
    itemTag['media-type'] = 'text/css'
    manifest.insert(mtc, itemTag)
    mtc += 1
    if self.generate_for_kindle_mobi:
        itemTag = Tag(soup, 'item')
        itemTag['id'] = 'mastheadimage-image'
        itemTag['href'] = 'images/mastheadImage.gif'
        itemTag['media-type'] = 'image/gif'
        manifest.insert(mtc, itemTag)
        mtc += 1
    if self.opts.generate_descriptions:
        for thumb in self.thumbs:
            itemTag = Tag(soup, 'item')
            itemTag['href'] = ('images/%s' % thumb)
            end = thumb.find('.jpg')
            itemTag['id'] = ('%s-image' % thumb[:end])
            itemTag['media-type'] = 'image/jpeg'
            manifest.insert(mtc, itemTag)
            mtc += 1
    for file in self.html_filelist_1:
        itemTag = Tag(soup, 'item')
        start = (file.find('/') + 1)
        end = file.find('.')
        itemTag['href'] = file
        itemTag['id'] = file[start:end].lower()
        itemTag['media-type'] = 'application/xhtml+xml'
        manifest.insert(mtc, itemTag)
        mtc += 1
        itemrefTag = Tag(soup, 'itemref')
        itemrefTag['idref'] = file[start:end].lower()
        spine.insert(stc, itemrefTag)
        stc += 1
    for genre in self.genres:
        itemTag = Tag(soup, 'item')
        start = (genre['file'].find('/') + 1)
        end = genre['file'].find('.')
        itemTag['href'] = genre['file']
        itemTag['id'] = genre['file'][start:end].lower()
        itemTag['media-type'] = 'application/xhtml+xml'
        manifest.insert(mtc, itemTag)
        mtc += 1
        itemrefTag = Tag(soup, 'itemref')
        itemrefTag['idref'] = genre['file'][start:end].lower()
        spine.insert(stc, itemrefTag)
        stc += 1
    for file in self.html_filelist_2:
        itemTag = Tag(soup, 'item')
        start = (file.find('/') + 1)
        end = file.find('.')
        itemTag['href'] = file
        itemTag['id'] = file[start:end].lower()
        itemTag['media-type'] = 'application/xhtml+xml'
        manifest.insert(mtc, itemTag)
        mtc += 1
        itemrefTag = Tag(soup, 'itemref')
        itemrefTag['idref'] = file[start:end].lower()
        spine.insert(stc, itemrefTag)
        stc += 1
    for book in self.books_by_description:
        itemTag = Tag(soup, 'item')
        itemTag['href'] = ('content/book_%d.html' % int(book['id']))
        itemTag['id'] = ('book%d' % int(book['id']))
        itemTag['media-type'] = 'application/xhtml+xml'
        manifest.insert(mtc, itemTag)
        mtc += 1
        itemrefTag = Tag(soup, 'itemref')
        itemrefTag['idref'] = ('book%d' % int(book['id']))
        spine.insert(stc, itemrefTag)
        stc += 1
    if self.generate_for_kindle_mobi:
        referenceTag = Tag(soup, 'reference')
        referenceTag['type'] = 'masthead'
        referenceTag['title'] = 'mastheadimage-image'
        referenceTag['href'] = 'images/mastheadImage.gif'
        guide.insert(0, referenceTag)
    outfile = open(('%s/%s.opf' % (self.catalog_path, self.opts.basename)), 'w')
    outfile.write(soup.prettify())
