diff --git a/src/calibre/ebooks/oeb/transforms/structure.py b/src/calibre/ebooks/oeb/transforms/structure.py index 0db9b153df..fc338da692 100644 --- a/src/calibre/ebooks/oeb/transforms/structure.py +++ b/src/calibre/ebooks/oeb/transforms/structure.py @@ -13,6 +13,7 @@ from urlparse import urlparse from calibre.ebooks.oeb.base import XPNSMAP, TOC, XHTML, xml2text from calibre.ebooks import ConversionError +from calibre.utils.ordered_dict import OrderedDict def XPath(x): try: @@ -95,10 +96,8 @@ class DetectStructure(object): self.log.exception('Failed to mark chapter') def create_level_based_toc(self): - if self.opts.level1_toc is None: - return - for item in self.oeb.spine: - self.add_leveled_toc_items(item) + if self.opts.level1_toc is not None: + self.add_leveled_toc_items() def create_toc_from_chapters(self): counter = self.oeb.toc.next_play_order() @@ -145,49 +144,57 @@ class DetectStructure(object): return text, href - def add_leveled_toc_items(self, item): - level1 = XPath(self.opts.level1_toc)(item.data) - level1_order = [] - document = item - + def add_leveled_toc_items(self): + added = OrderedDict() + added2 = OrderedDict() counter = 1 - if level1: - added = {} - for elem in level1: + for document in self.oeb.spine: + previous_level1 = list(added.itervalues())[-1] if added else None + previous_level2 = list(added2.itervalues())[-1] if added2 else None + + for elem in XPath(self.opts.level1_toc)(document.data): text, _href = self.elem_to_link(document, elem, counter) counter += 1 if text: node = self.oeb.toc.add(text, _href, play_order=self.oeb.toc.next_play_order()) - level1_order.append(node) added[elem] = node #node.add(_('Top'), _href) - if self.opts.level2_toc is not None: - added2 = {} - level2 = list(XPath(self.opts.level2_toc)(document.data)) - for elem in level2: + + if self.opts.level2_toc is not None and added: + for elem in XPath(self.opts.level2_toc)(document.data): level1 = None for item in document.data.iterdescendants(): - if item in added.keys(): + if item in added: level1 = added[item] - elif item == elem and level1 is not None: + elif item == elem: + if level1 is None: + if previous_level1 is None: + break + level1 = previous_level1 text, _href = self.elem_to_link(document, elem, counter) counter += 1 if text: added2[elem] = level1.add(text, _href, play_order=self.oeb.toc.next_play_order()) - if self.opts.level3_toc is not None: - level3 = list(XPath(self.opts.level3_toc)(document.data)) - for elem in level3: + break + + if self.opts.level3_toc is not None and added2: + for elem in XPath(self.opts.level3_toc)(document.data): level2 = None for item in document.data.iterdescendants(): - if item in added2.keys(): + if item in added2: level2 = added2[item] - elif item == elem and level2 is not None: + elif item == elem: + if level2 is None: + if previous_level2 is None: + break + level2 = previous_level2 text, _href = \ self.elem_to_link(document, elem, counter) counter += 1 if text: level2.add(text, _href, - play_order=self.oeb.toc.next_play_order()) + play_order=self.oeb.toc.next_play_order()) + break