diff --git a/Source/VersOne.Epub.Test/Unit/Readers/Epub3NavDocumentReaderTests.cs b/Source/VersOne.Epub.Test/Unit/Readers/Epub3NavDocumentReaderTests.cs index 29e046e..34504e9 100644 --- a/Source/VersOne.Epub.Test/Unit/Readers/Epub3NavDocumentReaderTests.cs +++ b/Source/VersOne.Epub.Test/Unit/Readers/Epub3NavDocumentReaderTests.cs @@ -159,6 +159,19 @@ public class Epub3NavDocumentReaderTests """; + private const string NAV_FILE_WITH_WITH_NON_TOP_LEVEL_NAV_ELEMENT = """ + + +
+ +
+ + + """; + private static EpubPackage MinimalEpubPackageWithNav => new ( @@ -447,6 +460,12 @@ public async Task ReadEpub3NavDocumentAsyncWithEscapedAHrefTest() await TestSuccessfulReadOperation(NAV_FILE_WITH_ESCAPED_HREF_IN_A_ELEMENT, expectedEpub3NavDocument); } + [Fact(DisplayName = "Reading a NAV file with non-top-level 'nav' element should succeed")] + public async Task ReadEpub3NavDocumentAsyncWithNonTopLevelNavElementTest() + { + await TestSuccessfulReadOperation(NAV_FILE_WITH_WITH_NON_TOP_LEVEL_NAV_ELEMENT, MinimalEpub3NavDocumentWithHeader); + } + private static async Task TestSuccessfulReadOperation(string navFileContent, Epub3NavDocument expectedEpub3NavDocument, EpubReaderOptions? epubReaderOptions = null) { TestZipFile testZipFile = CreateTestZipFileWithNavFile(navFileContent); diff --git a/Source/VersOne.Epub/Readers/Epub3NavDocumentReader.cs b/Source/VersOne.Epub/Readers/Epub3NavDocumentReader.cs index 31e7f9a..bfbdb74 100644 --- a/Source/VersOne.Epub/Readers/Epub3NavDocumentReader.cs +++ b/Source/VersOne.Epub/Readers/Epub3NavDocumentReader.cs @@ -49,12 +49,24 @@ public Epub3NavDocumentReader(EpubReaderOptions? epubReaderOptions = null) XElement htmlNode = navDocument.Element(xhtmlNamespace + "html") ?? throw new Epub3NavException("EPUB parsing error: navigation file does not contain html element."); XElement bodyNode = htmlNode.Element(xhtmlNamespace + "body") ?? throw new Epub3NavException("EPUB parsing error: navigation file does not contain body element."); List navs = new(); - foreach (XElement navNode in bodyNode.Elements(xhtmlNamespace + "nav")) + ReadEpub3NavsWithinContainerElement(bodyNode, navs); + return new(navFileEntryPath, navs); + } + + private static void ReadEpub3NavsWithinContainerElement(XElement containerElement, List resultNavs) + { + foreach (XElement childElement in containerElement.Elements()) { - Epub3Nav epub3Nav = ReadEpub3Nav(navNode); - navs.Add(epub3Nav); + if (childElement.GetLowerCaseLocalName() == "nav") + { + Epub3Nav epub3Nav = ReadEpub3Nav(childElement); + resultNavs.Add(epub3Nav); + } + else + { + ReadEpub3NavsWithinContainerElement(childElement, resultNavs); + } } - return new(navFileEntryPath, navs); } private static Epub3Nav ReadEpub3Nav(XElement navNode)