def set_authors(root, prefixes, refines, authors): ensure_prefix(root, prefixes, 'marc') for item in XPath('./opf:metadata/dc:creator')(root): props = properties_for_id_with_scheme(item.get('id'), prefixes, refines) opf_role = item.get(OPF('role')) if (opf_role and opf_role.lower() != 'aut') or ( props.get('role') and not is_relators_role(props, 'aut')): continue remove_element(item, refines) metadata = XPath('./opf:metadata')(root)[0] for author in authors: if author.name: a = metadata.makeelement(DC('creator')) aid = ensure_id(a) a.text = author.name metadata.append(a) m = metadata.makeelement(OPF('meta'), attrib={ 'refines': '#' + aid, 'property': 'role', 'scheme': 'marc:relators' }) m.text = 'aut' metadata.append(m) if author.sort: m = metadata.makeelement(OPF('meta'), attrib={ 'refines': '#' + aid, 'property': 'file-as' }) m.text = author.sort metadata.append(m)
def set_identifiers(root, prefixes, refines, new_identifiers, force_identifiers=False): uid = root.get('unique-identifier') package_identifier = None for ident in XPath('./opf:metadata/dc:identifier')(root): if uid is not None and uid == ident.get('id'): package_identifier = ident continue val = (ident.text or '').strip() if not val: ident.getparent().remove(ident) continue scheme, val = parse_identifier(ident, val, refines) if not scheme or not val or force_identifiers or scheme in new_identifiers: remove_element(ident, refines) continue metadata = XPath('./opf:metadata')(root)[0] for scheme, val in iteritems(new_identifiers): ident = metadata.makeelement(DC('identifier')) ident.text = '%s:%s' % (scheme, val) if package_identifier is None: metadata.append(ident) else: p = package_identifier.getparent() p.insert(p.index(package_identifier), ident)
def set_pubdate(root, prefixes, refines, val): for date in XPath('./opf:metadata/dc:date')(root): remove_element(date, refines) if not is_date_undefined(val): val = isoformat(val) m = XPath('./opf:metadata')(root)[0] d = m.makeelement(DC('date')) d.text = val m.append(d)
def set_publisher(root, prefixes, refines, val): for dc in XPath('./opf:metadata/dc:publisher')(root): remove_element(dc, refines) m = XPath('./opf:metadata')(root)[0] if val: val = val.strip() if val: c = m.makeelement(DC('publisher')) c.text = normalize_whitespace(val) m.append(c)
def set_comments(root, prefixes, refines, val): for dc in XPath('./opf:metadata/dc:description')(root): remove_element(dc, refines) m = XPath('./opf:metadata')(root)[0] if val: val = val.strip() if val: c = m.makeelement(DC('description')) c.text = val m.append(c)
def set_tags(root, prefixes, refines, val): for dc in XPath('./opf:metadata/dc:subject')(root): remove_element(dc, refines) m = XPath('./opf:metadata')(root)[0] if val: val = uniq(list(filter(None, val))) for x in val: c = m.makeelement(DC('subject')) c.text = normalize_whitespace(x) if c.text: m.append(c)
def set_title(root, prefixes, refines, title, title_sort=None): main_title = find_main_title(root, refines, remove_blanks=True) if main_title is None: m = XPath('./opf:metadata')(root)[0] main_title = m.makeelement(DC('title')) m.insert(0, main_title) main_title.text = title or None ts = [refdef('file-as', title_sort)] if title_sort else () set_refines(main_title, refines, refdef('title-type', 'main'), *ts) for m in XPath('./opf:metadata/opf:meta[@name="calibre:title_sort"]')(root): remove_element(m, refines)
def __call__(self, container): from calibre.ebooks.oeb.base import uuid_id opf = container.opf uid = uuid_id() opf.set('unique-identifier', uid) m = container.opf_xpath('/opf:package/opf:metadata') if not m: m = [container.opf.makeelement(OPF('metadata'), nsmap={'dc':DC11_NS})] container.insert_into_xml(container.opf, m[0], 0) m = m[0] dc = m.makeelement(DC('identifier'), id=uid, nsmap={'opf':OPF2_NS}) dc.set(OPF('scheme'), 'uuid') dc.text = uid container.insert_into_xml(m, dc) container.dirty(container.opf_name) return True
def set_languages(root, prefixes, refines, languages): opf_languages = [] for lang in XPath('./opf:metadata/dc:language')(root): remove_element(lang, refines) val = (lang.text or '').strip() if val: opf_languages.append(val) languages = list(filter(lambda x: x and x != 'und', normalize_languages(opf_languages, languages))) if not languages: # EPUB spec says dc:language is required languages = ['und'] metadata = XPath('./opf:metadata')(root)[0] for lang in uniq(languages): l = metadata.makeelement(DC('language')) l.text = lang metadata.append(l)
def set_book_producers(root, prefixes, refines, producers): for item in XPath('./opf:metadata/dc:contributor')(root): props = properties_for_id_with_scheme(item.get('id'), prefixes, refines) opf_role = item.get(OPF('role')) if (is_relators_role(props, 'bkp')) or (opf_role and opf_role.lower() != 'bkp'): continue remove_element(item, refines) metadata = XPath('./opf:metadata')(root)[0] for bkp in producers: a = metadata.makeelement(DC('contributor')) aid = ensure_id(a) a.text = bkp metadata.append(a) m = metadata.makeelement(OPF('meta'), attrib={'refines':'#'+aid, 'property':'role', 'scheme':'marc:relators'}) m.text = 'bkp' metadata.append(m)
def writer(root, prefixes, refines, ival=None): uid = root.get('unique-identifier') package_identifier = None for ident in XPath('./opf:metadata/dc:identifier')(root): is_package_id = uid is not None and uid == ident.get('id') if is_package_id: package_identifier = ident val = (ident.text or '').strip() if (val.startswith(name + ':') or ident.get(OPF('scheme')) == name) and not is_package_id: remove_element(ident, refines) metadata = XPath('./opf:metadata')(root)[0] if ival: ident = metadata.makeelement(DC('identifier')) ident.text = '%s:%s' % (name, ival) if package_identifier is None: metadata.append(ident) else: p = package_identifier.getparent() p.insert(p.index(package_identifier), ident)
def fix_opf(self, container): spine_names = {n for n, l in container.spine_names} spine = container.opf_xpath('//opf:spine')[0] rmap = {v: k for k, v in container.manifest_id_map.iteritems()} # Add unreferenced text files to the spine for name, mt in container.mime_map.iteritems(): if mt in OEB_DOCS and name not in spine_names: spine_names.add(name) container.insert_into_xml( spine, spine.makeelement(OPF('itemref'), idref=rmap[name])) # Remove duplicate entries from spine seen = set() for item, name, linear in container.spine_iter: if name in seen: container.remove_from_xml(item) seen.add(name) # Ensure that the meta cover tag is correct cover_id = rmap['_static/' + self.config.epub_cover[0]] for meta in container.opf_xpath('//opf:meta[@name="cover"]'): meta.set('content', cover_id) # Add description metadata metadata = container.opf_xpath('//opf:metadata')[0] container.insert_into_xml(metadata, metadata.makeelement(DC('description'))) metadata[-1].text = 'Comprehensive documentation for calibre' # Remove search.html since it is useless in EPUB container.remove_item('search.html') # Remove unreferenced files for error in check_links(container): if error.__class__ is UnreferencedResource: container.remove_item(error.name) # Pretty print the OPF pretty_opf(container.parsed(container.opf_name)) container.dirty(container.opf_name)