Replace genshi with lxml when generating NCX files

This commit is contained in:
Kovid Goyal 2010-05-28 21:46:50 -06:00
parent 607f864d8c
commit 5082a7b072
2 changed files with 61 additions and 43 deletions

View File

@ -1,35 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?python
from uuid import uuid4
import re
?>
<ncx version="2005-1"
xml:lang="en"
xmlns="http://www.daisy.org/z3986/2005/ncx/"
xmlns:py="http://genshi.edgewall.org/"
xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata"
>
<head>
<meta name="dtb:uid" content="${uid}"/>
<meta name="dtb:depth" content="${toc.depth()}"/>
<meta name="dtb:generator" content="${__appname__}"/>
<meta name="dtb:totalPageCount" content="0"/>
<meta name="dtb:maxPageNumber" content="0"/>
</head>
<docTitle><text>Table of Contents</text></docTitle>
<py:def function="navpoint(np, level)">
${'%*s'%(4*level,'')}<navPoint id="${str(uuid4())}" playOrder="${str(np.play_order)}">
${'%*s'%(4*level,'')}<navLabel>
${'%*s'%(4*level,'')}<text>${re.sub(r'\s+', ' ', np.text)}</text>
${'%*s'%(4*level,'')}</navLabel>
${'%*s'%(4*level,'')}<content src="${unicode(np.href)+(('#' + unicode(np.fragment)) if np.fragment else '')}" />
${'%*s'%(4*level,'')}<calibre:meta py:if="np.author" name="author">${np.author}</calibre:meta>
${'%*s'%(4*level,'')}<calibre:meta py:if="np.description" name="description">${np.description}</calibre:meta>
<py:for each="np2 in np">${navpoint(np2, level+1)}</py:for>
${'%*s'%(4*level,'')}</navPoint>
</py:def>
<navMap>
<py:for each="np in toc">${navpoint(np, 0)}</py:for>
</navMap>
</ncx>

View File

@ -1,14 +1,31 @@
#!/usr/bin/env python #!/usr/bin/env python
__license__ = 'GPL v3' __license__ = 'GPL v3'
__copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>' __copyright__ = '2010, Kovid Goyal <kovid at kovidgoyal.net>'
import os, glob, re import os, glob, re
from urlparse import urlparse from urlparse import urlparse
from urllib import unquote from urllib import unquote
from uuid import uuid4
from calibre import __appname__ from lxml import etree
from lxml.builder import ElementMaker
from calibre.constants import __appname__, __version__
from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup from calibre.ebooks.BeautifulSoup import BeautifulStoneSoup, BeautifulSoup
from calibre.ebooks.chardet import xml_to_unicode from calibre.ebooks.chardet import xml_to_unicode
NCX_NS = "http://www.daisy.org/z3986/2005/ncx/"
CALIBRE_NS = "http://calibre.kovidgoyal.net/2009/metadata"
NSMAP = {
None: NCX_NS,
'calibre':CALIBRE_NS
}
E = ElementMaker(namespace=NCX_NS, nsmap=NSMAP)
C = ElementMaker(namespace=CALIBRE_NS, nsmap=NSMAP)
class NCXSoup(BeautifulStoneSoup): class NCXSoup(BeautifulStoneSoup):
NESTABLE_TAGS = {'navpoint':[]} NESTABLE_TAGS = {'navpoint':[]}
@ -208,10 +225,46 @@ class TOC(list):
self.add_item(href, fragment, txt) self.add_item(href, fragment, txt)
def render(self, stream, uid): def render(self, stream, uid):
from calibre.utils.genshi.template import MarkupTemplate root = E.ncx(
ncx_template = open(P('templates/ncx.xml'), 'rb').read() E.head(
doctype = ('ncx', "-//NISO//DTD ncx 2005-1//EN", "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd") E.meta(name='dtb:uid', content=str(uid)),
template = MarkupTemplate(ncx_template) E.meta(name='dtb:depth', content=str(self.depth())),
raw = template.generate(uid=uid, toc=self, __appname__=__appname__) E.meta(name='dtb:generator', content='%s (%s)'%(__appname__,
raw = raw.render(doctype=doctype) __version__)),
E.meta(name='dtb:totalPageCount', content='0'),
E.meta(name='dtb:maxPageNumber', content='0'),
),
E.docTitle(E.text('Table of Contents')),
)
navmap = E.navMap()
root.append(navmap)
root.set('{http://www.w3.org/XML/1998/namespace}lang', 'en')
def navpoint(parent, np):
text = np.text
if not text:
text = ''
elem = E.navPoint(
E.navLabel(E.text(re.sub(r'\s+', ' ', text))),
E.content(src=unicode(np.href)+(('#' + unicode(np.fragment))
if np.fragment else '')),
id=str(uuid4()),
playOrder=str(np.play_order)
)
au = getattr(np, 'author', None)
if au:
au = re.sub(r'\s+', ' ', au)
elem.append(C.meta(au, name='author'))
desc = getattr(np, 'description', None)
if desc:
desc = re.sub(r'\s+', ' ', desc)
elem.append(C.meta(desc, name='description'))
parent.append(elem)
for np2 in np:
navpoint(elem, np2)
for np in self:
navpoint(navmap, np)
raw = etree.tostring(root, encoding='utf-8', xml_declaration=True,
pretty_print=True)
stream.write(raw) stream.write(raw)