private static async Task<EpubNavigationPoint> ReadNavigationPointAsync(XmlReader reader) { EpubNavigationPoint result = new EpubNavigationPoint(); //we have to skip first entry as it could be empty after new sub-reader created if (reader.NodeType == XmlNodeType.None) await reader.ReadAsync(); //Now the pointer should point to the <navPoint> itself while (reader.MoveToNextAttribute()) //Doing this we just passing through <navPoint> tag { switch (reader.LocalName.ToLowerInvariant()) //We have to collect all possible attributes from the <navPoint> { case "id": result.Id = reader.Value; break; case "class": result.Class = reader.Value; break; case "playorder": result.PlayOrder = reader.Value; break; } } if (String.IsNullOrWhiteSpace(result.Id)) throw new Exception("Incorrect EPUB navigation point: point ID is missing"); result.NavigationLabels = new List<EpubNavigationLabel>(); result.ChildNavigationPoints = new List<EpubNavigationPoint>(); // We need to make sure that we will return pointer back to <navPoint> entry after reading all attributes reader.MoveToElement(); //Now we are looking for subnodes - navLabel, content and sub-navPoints while (await reader.ReadAsync()) { if (reader.NodeType != XmlNodeType.EndElement) switch (reader.LocalName.ToLowerInvariant()) { case "navlabel": EpubNavigationLabel navigationLabel = await ReadNavigationLabelAsync(reader);// Adding label to collection result.NavigationLabels.Add(navigationLabel); break; case "content": EpubNavigationContent content = await ReadNavigationContentAsync(reader); //Adding content to collection result.Content = content; break; case "navpoint": //Yeep. Looks like we found a <navPoint> sub-node XmlReader subTree = reader.ReadSubtree(); //Cooking a separate sub-reader scope for this node to separate it from the others siblings EpubNavigationPoint childNavigationPoint = await ReadNavigationPointAsync(subTree);// I hate recursion... //Adding a child to a collection result.ChildNavigationPoints.Add(childNavigationPoint); subTree.Dispose(); break; } }; return result; }
private static EpubNavigationPoint ReadNavigationPoint(XmlNode navigationPointNode) { EpubNavigationPoint result = new EpubNavigationPoint(); foreach (XmlAttribute navigationPointNodeAttribute in navigationPointNode.Attributes) { string attributeValue = navigationPointNodeAttribute.Value; switch (navigationPointNodeAttribute.Name.ToLowerInvariant()) { case "id": result.Id = attributeValue; break; case "class": result.Class = attributeValue; break; case "playOrder": result.PlayOrder = attributeValue; break; } } if (String.IsNullOrWhiteSpace(result.Id)) throw new Exception("Incorrect EPUB navigation point: point ID is missing"); result.NavigationLabels = new List<EpubNavigationLabel>(); result.ChildNavigationPoints = new List<EpubNavigationPoint>(); foreach (XmlNode navigationPointChildNode in navigationPointNode.ChildNodes) switch (navigationPointChildNode.LocalName.ToLowerInvariant()) { case "navlabel": EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationPointChildNode); result.NavigationLabels.Add(navigationLabel); break; case "content": EpubNavigationContent content = ReadNavigationContent(navigationPointChildNode); result.Content = content; break; case "navpoint": EpubNavigationPoint childNavigationPoint = ReadNavigationPoint(navigationPointChildNode); result.ChildNavigationPoints.Add(childNavigationPoint); break; } if (!result.NavigationLabels.Any()) throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain at least one navigation label", result.Id)); if (result.Content == null) throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain content", result.Id)); return result; }