diff --git a/src/calibre/ebooks/metadata/opf.py b/src/calibre/ebooks/metadata/opf.py
index ce93c09531..105841917b 100644
--- a/src/calibre/ebooks/metadata/opf.py
+++ b/src/calibre/ebooks/metadata/opf.py
@@ -8,7 +8,7 @@ from __future__ import (unicode_literals, division, absolute_import,
from lxml import etree
from calibre.ebooks.metadata.opf2 import OPF, pretty_print
-from calibre.ebooks.metadata.opf3 import apply_metadata
+from calibre.ebooks.metadata.opf3 import apply_metadata, read_metadata
from calibre.ebooks.metadata.utils import parse_opf, normalize_languages, create_manifest_item, parse_opf_version
from calibre.ebooks.metadata import MetaInformation
@@ -20,13 +20,19 @@ class DummyFile(object):
def read(self):
return self.raw
+def get_metadata2(root, ver):
+ opf = OPF(None, preparsed_opf=root, read_toc=False)
+ return opf.to_book_metadata(), ver, opf.raster_cover, opf.first_spine_item()
+
+def get_metadata3(root, ver):
+ return read_metadata(root, ver=ver, return_extra_data=True)
+
def get_metadata(stream):
if isinstance(stream, bytes):
stream = DummyFile(stream)
root = parse_opf(stream)
ver = parse_opf_version(root.get('version'))
- opf = OPF(None, preparsed_opf=root, read_toc=False)
- return opf.to_book_metadata(), ver, opf.raster_cover, opf.first_spine_item()
+ return get_metadata2(root, ver)
def set_metadata_opf2(root, cover_prefix, mi, opf_version,
cover_data=None, apply_null=False, update_timestamp=False, force_identifiers=False, add_missing_cover=True):
diff --git a/src/calibre/ebooks/metadata/opf3.py b/src/calibre/ebooks/metadata/opf3.py
index 9e944f0efa..28ae691d11 100644
--- a/src/calibre/ebooks/metadata/opf3.py
+++ b/src/calibre/ebooks/metadata/opf3.py
@@ -825,7 +825,13 @@ def ensure_is_only_raster_cover(root, prefixes, refines, raster_cover_item_href)
# Reading/setting Metadata objects {{{
-def read_metadata(root):
+def first_spine_item(root, prefixes, refines):
+ for i in XPath('./opf:spine/opf:itemref/@idref')(root):
+ for item in XPath('./opf:manifest/opf:item')(root):
+ if item.get('id') == i:
+ return item.get('href') or None
+
+def read_metadata(root, ver=None, return_extra_data=False):
ans = Metadata(_('Unknown'), [_('Unknown')])
prefixes, refines = read_prefixes(root), read_refines(root)
identifiers = read_identifiers(root, prefixes, refines)
@@ -869,6 +875,8 @@ def read_metadata(root):
ans.user_categories = read_user_categories(root, prefixes, refines) or ans.user_categories
for name, fm in (read_user_metadata(root, prefixes, refines) or {}).iteritems():
ans.set_user_metadata(name, fm)
+ if return_extra_data:
+ ans = ans, ver, read_raster_cover(root, prefixes, refines), first_spine_item(root, prefixes, refines)
return ans
def get_metadata(stream):
diff --git a/src/calibre/ebooks/metadata/opf3_test.py b/src/calibre/ebooks/metadata/opf3_test.py
index 947a4b8847..853226cd85 100644
--- a/src/calibre/ebooks/metadata/opf3_test.py
+++ b/src/calibre/ebooks/metadata/opf3_test.py
@@ -486,20 +486,22 @@ class TestOPF3(unittest.TestCase):
"label": "date", "table":
"custom_column_2", "is_multiple": null,
"is_category": false}"/>
-
+
''' # }}}
def compare_metadata(mi2, mi3):
self.ae(mi2.get_all_user_metadata(False), mi3.get_all_user_metadata(False))
for field in ALL_METADATA_FIELDS:
- if field != 'manifest':
+ if field not in 'manifest spine':
v2, v3 = getattr(mi2, field, None), getattr(mi3, field, None)
self.ae(v2, v3, '%s: %r != %r' % (field, v2, v3))
mi2 = OPF(BytesIO(raw.encode('utf-8'))).to_book_metadata()
root = etree.fromstring(raw)
root.set('version', '3.0')
- mi3 = read_metadata(root)
+ mi3, _, raster_cover, first_spine_item = read_metadata(root, return_extra_data=True)
+ self.assertIsNone(raster_cover)
+ self.ae('start.html', first_spine_item)
compare_metadata(mi2, mi3)
apply_metadata(root, mi3, force_identifiers=True)
nmi = read_metadata(root)