private static EpubSpine ReadSpine(XElement spineNode) { var result = new EpubSpine(); var tocAttribute = spineNode.Attribute("toc"); if (string.IsNullOrWhiteSpace(tocAttribute?.Value)) { throw new Exception("Incorrect EPUB spine: TOC is missing"); } result.Toc = tocAttribute?.Value; foreach (var spineItemNode in spineNode.Elements()) { if (string.Compare(spineItemNode.Name.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) is 0) { var spineItemRef = new EpubSpineItemRef(); var idRefAttribute = spineItemNode.Attribute("idref"); if (idRefAttribute is null || string.IsNullOrWhiteSpace(idRefAttribute.Value)) { throw new Exception("Incorrect EPUB spine: item ID ref is missing"); } spineItemRef.IdRef = idRefAttribute.Value; var linearAttribute = spineItemNode.Attribute("linear"); spineItemRef.IsLinear = linearAttribute is null || string.Compare(linearAttribute.Value, "no", StringComparison.OrdinalIgnoreCase) != 0; result.Add(spineItemRef); } } return(result); }
private static EpubSpine ReadSpine(XmlNode spineNode) { EpubSpine result = new EpubSpine(); XmlAttribute tocAttribute = spineNode.Attributes["toc"]; if (tocAttribute == null || String.IsNullOrWhiteSpace(tocAttribute.Value)) { throw new Exception("Incorrect EPUB spine: TOC is missing"); } result.Toc = tocAttribute.Value; foreach (XmlNode spineItemNode in spineNode.ChildNodes) { if (String.Compare(spineItemNode.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) == 0) { EpubSpineItemRef spineItemRef = new EpubSpineItemRef(); XmlAttribute idRefAttribute = spineItemNode.Attributes["idref"]; if (idRefAttribute == null || String.IsNullOrWhiteSpace(idRefAttribute.Value)) { throw new Exception("Incorrect EPUB spine: item ID ref is missing"); } spineItemRef.IdRef = idRefAttribute.Value; XmlAttribute linearAttribute = spineItemNode.Attributes["linear"]; spineItemRef.IsLinear = linearAttribute == null || String.Compare(linearAttribute.Value, "no", StringComparison.OrdinalIgnoreCase) != 0; result.Add(spineItemRef); } } return(result); }
private static EpubSpine ReadSpine(XElement spineNode, EpubVersion epubVersion) { EpubSpine result = new EpubSpine(); foreach (XAttribute spineNodeAttribute in spineNode.Attributes()) { string attributeValue = spineNodeAttribute.Value; switch (spineNodeAttribute.GetLowerCaseLocalName()) { case "id": result.Id = attributeValue; break; case "page-progression-direction": result.PageProgressionDirection = PageProgressionDirectionParser.Parse(attributeValue); break; case "toc": result.Toc = attributeValue; break; } } if (epubVersion == EpubVersion.EPUB_2 && String.IsNullOrWhiteSpace(result.Toc)) { throw new Exception("Incorrect EPUB spine: TOC is missing"); } foreach (XElement spineItemNode in spineNode.Elements()) { if (spineItemNode.CompareNameTo("itemref")) { EpubSpineItemRef spineItemRef = new EpubSpineItemRef(); foreach (XAttribute spineItemNodeAttribute in spineItemNode.Attributes()) { string attributeValue = spineItemNodeAttribute.Value; switch (spineItemNodeAttribute.GetLowerCaseLocalName()) { case "id": spineItemRef.Id = attributeValue; break; case "idref": spineItemRef.IdRef = attributeValue; break; case "properties": spineItemRef.Properties = SpinePropertyParser.ParsePropertyList(attributeValue); break; } } if (String.IsNullOrWhiteSpace(spineItemRef.IdRef)) { throw new Exception("Incorrect EPUB spine: item ID ref is missing"); } XAttribute linearAttribute = spineItemNode.Attribute("linear"); spineItemRef.IsLinear = linearAttribute == null || !linearAttribute.CompareValueTo("no"); result.Add(spineItemRef); } } return(result); }
private static async Task <EpubSpine> ReadSpineAsync(XmlReader reader) { EpubSpine result = new EpubSpine(); bool spineFound = await reader.ReadToFollowingAsync("spine", "http://www.idpf.org/2007/opf"); if (!spineFound) { throw new Exception("EPUB parsing error: spine declarations not found in the package."); } if (String.IsNullOrWhiteSpace(reader.GetAttribute("toc"))) { throw new Exception("Incorrect EPUB spine: TOC attribute is missing or empty"); } result.Toc = reader.GetAttribute("toc"); while (await reader.ReadAsync() && !(reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "spine")) { if (reader.LocalName.ToLowerInvariant() == "itemref") { EpubSpineItemRef spineItemRef = new EpubSpineItemRef(); spineItemRef.IsLinear = true; while (reader.MoveToNextAttribute()) { switch (reader.LocalName.ToLowerInvariant()) { case "idref": spineItemRef.IdRef = reader.Value; break; case "linear": if (reader.Value.ToLowerInvariant() == "no") { spineItemRef.IsLinear = false; } break; } } result.Add(spineItemRef); } } return(result); }
public static List <EpubChapterRef> GetChapters(EpubBookRef bookRef, EpubSpine spine, List <EpubNavigationPoint> navigationPoints) { var result = new List <EpubChapterRef>(); for (var s = 0; s < spine.Count; s++) { var itemRef = spine[s]; string contentFileName; string anchor; contentFileName = WebUtility.UrlDecode(bookRef.Schema.Package.Manifest .FirstOrDefault(e => e.Id == itemRef.IdRef)?.Href); anchor = null; if (!bookRef.Content.Html.TryGetValue(contentFileName, out var htmlContentFileRef)) { throw new Exception(string.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.", contentFileName)); } var chapterRef = new EpubChapterRef(htmlContentFileRef); chapterRef.ContentFileName = contentFileName; chapterRef.Anchor = anchor; chapterRef.Parent = null; var navPoint = navigationPoints.LastOrDefault(nav => spine.Take(s + 1) .Select(sp => bookRef.Schema.Package.Manifest.FirstOrDefault(e => e.Id == sp.IdRef)?.Href) .Contains(nav.Content.Source.Split('#')[0])); if (navPoint != null) { chapterRef.Title = navPoint.NavigationLabels.First().Text; } else { chapterRef.Title = $"Chapter {s + 1}"; } chapterRef.SubChapters = new List <EpubChapterRef>(); result.Add(chapterRef); } return(result); }
public static EpubPackage ReadPackage(ZipArchive epubArchive, string rootFilePath) { ZipArchiveEntry rootFileEntry = epubArchive.GetEntry(rootFilePath); if (rootFileEntry == null) { throw new Exception("EPUB parsing error: root file not found in archive."); } XmlDocument containerDocument; using (Stream containerStream = rootFileEntry.Open()) containerDocument = XmlUtils.LoadDocument(containerStream); XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(containerDocument.NameTable); xmlNamespaceManager.AddNamespace("opf", "http://www.idpf.org/2007/opf"); XmlNode packageNode = containerDocument.DocumentElement.SelectSingleNode("/opf:package", xmlNamespaceManager); EpubPackage result = new EpubPackage(); string epubVersionValue = packageNode.Attributes["version"].Value; if (epubVersionValue == "2.0") { result.EpubVersion = EpubVersion.EPUB_2; } else if (epubVersionValue == "3.0") { result.EpubVersion = EpubVersion.EPUB_3; } else { throw new Exception(String.Format("Unsupported EPUB version: {0}.", epubVersionValue)); } XmlNode metadataNode = packageNode.SelectSingleNode("opf:metadata", xmlNamespaceManager); if (metadataNode == null) { throw new Exception("EPUB parsing error: metadata not found in the package."); } EpubMetadata metadata = ReadMetadata(metadataNode, result.EpubVersion); result.Metadata = metadata; XmlNode manifestNode = packageNode.SelectSingleNode("opf:manifest", xmlNamespaceManager); if (manifestNode == null) { throw new Exception("EPUB parsing error: manifest not found in the package."); } EpubManifest manifest = ReadManifest(manifestNode); result.Manifest = manifest; XmlNode spineNode = packageNode.SelectSingleNode("opf:spine", xmlNamespaceManager); if (spineNode == null) { throw new Exception("EPUB parsing error: spine not found in the package."); } EpubSpine spine = ReadSpine(spineNode); result.Spine = spine; XmlNode guideNode = packageNode.SelectSingleNode("opf:guide", xmlNamespaceManager); if (guideNode != null) { EpubGuide guide = ReadGuide(guideNode); result.Guide = guide; } return(result); }
private static async Task<EpubSpine> ReadSpineAsync(XmlReader reader) { EpubSpine result = new EpubSpine(); bool spineFound = await reader.ReadToFollowingAsync("spine", "http://www.idpf.org/2007/opf"); if (!spineFound) throw new Exception("EPUB parsing error: spine declarations not found in the package."); if (String.IsNullOrWhiteSpace(reader.GetAttribute("toc"))) throw new Exception("Incorrect EPUB spine: TOC attribute is missing or empty"); result.Toc = reader.GetAttribute("toc"); while (await reader.ReadAsync() && !(reader.NodeType == XmlNodeType.EndElement && reader.LocalName == "spine")) { if (reader.LocalName.ToLowerInvariant() == "itemref") { EpubSpineItemRef spineItemRef = new EpubSpineItemRef(); spineItemRef.IsLinear = true; while (reader.MoveToNextAttribute()) { switch (reader.LocalName.ToLowerInvariant()) { case "idref": spineItemRef.IdRef = reader.Value; break; case "linear": if (reader.Value.ToLowerInvariant() == "no") { spineItemRef.IsLinear = false; } break; } } result.Add(spineItemRef); } } return result; }
private static EpubSpine ReadSpine(XmlNode spineNode) { EpubSpine result = new EpubSpine(); XmlAttribute tocAttribute = spineNode.Attributes["toc"]; if (tocAttribute == null || String.IsNullOrWhiteSpace(tocAttribute.Value)) throw new Exception("Incorrect EPUB spine: TOC is missing"); result.Toc = tocAttribute.Value; foreach (XmlNode spineItemNode in spineNode.ChildNodes) if (String.Compare(spineItemNode.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) == 0) { EpubSpineItemRef spineItemRef = new EpubSpineItemRef(); XmlAttribute idRefAttribute = spineItemNode.Attributes["idref"]; if (idRefAttribute == null || String.IsNullOrWhiteSpace(idRefAttribute.Value)) throw new Exception("Incorrect EPUB spine: item ID ref is missing"); spineItemRef.IdRef = idRefAttribute.Value; XmlAttribute linearAttribute = spineItemNode.Attributes["linear"]; spineItemRef.IsLinear = linearAttribute == null || String.Compare(linearAttribute.Value, "no", StringComparison.OrdinalIgnoreCase) != 0; result.Add(spineItemRef); } return result; }
public static async Task <EpubPackage> ReadPackageAsync(ZipArchive epubArchive, string rootFilePath) { ZipArchiveEntry rootFileEntry = epubArchive.GetEntry(rootFilePath); if (rootFileEntry == null) { throw new Exception("EPUB parsing error: root file not found in archive."); } XDocument containerDocument; using (Stream containerStream = rootFileEntry.Open()) containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false); XNamespace opfNamespace = "http://www.idpf.org/2007/opf"; XElement packageNode = containerDocument.Element(opfNamespace + "package"); EpubPackage result = new EpubPackage(); string epubVersionValue = packageNode.Attribute("version").Value; if (epubVersionValue == "2.0") { result.EpubVersion = EpubVersion.EPUB_2; } else if (epubVersionValue == "3.0") { result.EpubVersion = EpubVersion.EPUB_3; } else { throw new Exception(String.Format("Unsupported EPUB version: {0}.", epubVersionValue)); } XElement metadataNode = packageNode.Element(opfNamespace + "metadata"); if (metadataNode == null) { throw new Exception("EPUB parsing error: metadata not found in the package."); } EpubMetadata metadata = ReadMetadata(metadataNode, result.EpubVersion); result.Metadata = metadata; XElement manifestNode = packageNode.Element(opfNamespace + "manifest"); if (manifestNode == null) { throw new Exception("EPUB parsing error: manifest not found in the package."); } EpubManifest manifest = ReadManifest(manifestNode); result.Manifest = manifest; XElement spineNode = packageNode.Element(opfNamespace + "spine"); if (spineNode == null) { throw new Exception("EPUB parsing error: spine not found in the package."); } EpubSpine spine = ReadSpine(spineNode); result.Spine = spine; XElement guideNode = packageNode.Element(opfNamespace + "guide"); if (guideNode != null) { EpubGuide guide = ReadGuide(guideNode); result.Guide = guide; } return(result); }
//Parsing metadata, manifest, spine and guide public static async Task <EpubPackage> ReadPackageAsync(ZipArchive epubArchive, string rootFilePath) { EpubPackage result = new EpubPackage(); XmlReaderSettings xmlReaderSettings = new XmlReaderSettings { // XmlResolver = null, Async = true, DtdProcessing = DtdProcessing.Ignore }; ZipArchiveEntry rootFileEntry = epubArchive.GetEntry(rootFilePath); if (rootFileEntry == null) { throw new Exception(string.Format("EPUB parsing error: {0} file not found in archive.", rootFilePath)); } //Starting content.opf parsing... using (Stream containerStream = rootFileEntry.Open()) { using (XmlReader xmlReader = XmlReader.Create(containerStream, xmlReaderSettings)) { await xmlReader.ReadToFollowingAsync("package", "http://www.idpf.org/2007/opf"); //Trying to get version attribute from <package version=... //Looks like we only need EPUB version data and we don`t care about unique-identifier //if EPUB version is FUBAR then throwing an exeption xmlReader.MoveToAttribute("version"); string epubVersionValue = xmlReader.Value; if (epubVersionValue == "2.0") { result.EpubVersion = EpubVersion.EPUB_2; } else if (epubVersionValue == "3.0") { result.EpubVersion = EpubVersion.EPUB_3; } else { throw new Exception(String.Format("Unsupported EPUB version: {0}.", epubVersionValue)); } //Reading metadata EpubMetadata metadata = await ReadMetadataAsync(xmlReader, result.EpubVersion); result.Metadata = metadata; //Reading manifest EpubManifest manifest = await ReadManifestAsync(xmlReader); result.Manifest = manifest; //Reading spine EpubSpine spine = await ReadSpineAsync(xmlReader); result.Spine = spine; //Reading guide. And we actually don`t care if it is no present in our EPUB... bool isGuidePresent = await xmlReader.ReadToFollowingAsync("guide", "http://www.idpf.org/2007/opf"); if (isGuidePresent) { EpubGuide guide = await ReadGuideAsync(xmlReader); result.Guide = guide; } } } return(result); }