diff --git a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt index 1ef4702e7..310f2263e 100644 --- a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt @@ -114,30 +114,16 @@ class EpubFile(var book: Book) { } input ?: return null FileUtils.writeInputStream(file, input) + if (!file.exists()){ + return EpubReader().readEpub(input) + } } - return EpubReader().readEpubLazy(ZipFile(file),"utf-8") + + //通过懒加载读取epub + return EpubReader().readEpubLazy(ZipFile(file), "utf-8") -// val inZip = ZipInputStream(input) -// var zipEntry: ZipEntry? -// val resources = Resources() -// do { -// zipEntry = inZip.nextEntry -// if ((zipEntry == null) || zipEntry.isDirectory || zipEntry == ZipEntry("")) continue -// val resource = ResourceUtil.createResource(zipEntry, inZip) -// if (resource.mediaType == MediaTypes.XHTML) resource.inputEncoding = "UTF-8" -// if (zipEntry.name.endsWith(".opf")) { -// /*掌上书苑有很多自制书OPF的nameSpace格式不标准,强制修复成正确的格式*/ -// val newS = String(resource.data).replace( -// "\\smlns=\"http://www.idpf.org/2007/opf\"".toRegex(), -// " xmlns=\"http://www.idpf.org/2007/opf\"" -// ) -// resource.data = newS.toByteArray() -// } -// resources.add(resource) -// } while (zipEntry != null) -// if (resources.size() > 0) return EpubReader().readEpub(resources) } catch (e: Exception) { e.printStackTrace() } diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/DOMUtil.java b/epublib/src/main/java/me/ag2s/epublib/epub/DOMUtil.java index 34e826abc..e6ae05b3d 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/DOMUtil.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/DOMUtil.java @@ -1,135 +1,177 @@ package me.ag2s.epublib.epub; -import me.ag2s.epublib.util.StringUtil; -import java.util.ArrayList; -import java.util.List; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; +import java.util.ArrayList; +import java.util.List; + +import me.ag2s.epublib.util.StringUtil; + /** * Utility methods for working with the DOM. * * @author paul - * */ // package class DOMUtil { - /** - * First tries to get the attribute value by doing an getAttributeNS on the element, if that gets an empty element it does a getAttribute without namespace. - * - * @param element element - * @param namespace namespace - * @param attribute attribute - * @return String Attribute - */ - public static String getAttribute(Element element, String namespace, - String attribute) { - String result = element.getAttributeNS(namespace, attribute); - if (StringUtil.isEmpty(result)) { - result = element.getAttribute(attribute); + /** + * First tries to get the attribute value by doing an getAttributeNS on the element, if that gets an empty element it does a getAttribute without namespace. + * + * @param element element + * @param namespace namespace + * @param attribute attribute + * @return String Attribute + */ + public static String getAttribute(Element element, String namespace, + String attribute) { + String result = element.getAttributeNS(namespace, attribute); + if (StringUtil.isEmpty(result)) { + result = element.getAttribute(attribute); + } + return result; } - return result; - } - /** - * Gets all descendant elements of the given parentElement with the given namespace and tagname and returns their text child as a list of String. - * - * @param parentElement parentElement - * @param namespace namespace - * @param tagName tagName - * @return List - */ - public static List getElementsTextChild(Element parentElement, - String namespace, String tagName) { - NodeList elements = parentElement - .getElementsByTagNameNS(namespace, tagName); - //ArrayList 初始化时指定长度提高性能 - List result = new ArrayList<>(elements.getLength()); - for (int i = 0; i < elements.getLength(); i++) { - result.add(getTextChildrenContent((Element) elements.item(i))); + /** + * Gets all descendant elements of the given parentElement with the given namespace and tagname and returns their text child as a list of String. + * + * @param parentElement parentElement + * @param namespace namespace + * @param tagName tagName + * @return List + */ + public static List getElementsTextChild(Element parentElement, + String namespace, String tagName) { + NodeList elements = parentElement + .getElementsByTagNameNS(namespace, tagName); + //ArrayList 初始化时指定长度提高性能 + List result = new ArrayList<>(elements.getLength()); + for (int i = 0; i < elements.getLength(); i++) { + result.add(getTextChildrenContent((Element) elements.item(i))); + } + return result; } - return result; - } - /** - * Finds in the current document the first element with the given namespace and elementName and with the given findAttributeName and findAttributeValue. - * It then returns the value of the given resultAttributeName. - * - * @param document document - * @param namespace namespace - * @param elementName elementName - * @param findAttributeName findAttributeName - * @param findAttributeValue findAttributeValue - * @param resultAttributeName resultAttributeName - * @return String value - */ - public static String getFindAttributeValue(Document document, - String namespace, String elementName, String findAttributeName, - String findAttributeValue, String resultAttributeName) { - NodeList metaTags = document.getElementsByTagNameNS(namespace, elementName); - for (int i = 0; i < metaTags.getLength(); i++) { - Element metaElement = (Element) metaTags.item(i); - if (findAttributeValue - .equalsIgnoreCase(metaElement.getAttribute(findAttributeName)) - && StringUtil - .isNotBlank(metaElement.getAttribute(resultAttributeName))) { - return metaElement.getAttribute(resultAttributeName); - } + /** + * Finds in the current document the first element with the given namespace and elementName and with the given findAttributeName and findAttributeValue. + * It then returns the value of the given resultAttributeName. + * + * @param document document + * @param namespace namespace + * @param elementName elementName + * @param findAttributeName findAttributeName + * @param findAttributeValue findAttributeValue + * @param resultAttributeName resultAttributeName + * @return String value + */ + public static String getFindAttributeValue(Document document, + String namespace, String elementName, String findAttributeName, + String findAttributeValue, String resultAttributeName) { + NodeList metaTags = document.getElementsByTagNameNS(namespace, elementName); + for (int i = 0; i < metaTags.getLength(); i++) { + Element metaElement = (Element) metaTags.item(i); + if (findAttributeValue + .equalsIgnoreCase(metaElement.getAttribute(findAttributeName)) + && StringUtil + .isNotBlank(metaElement.getAttribute(resultAttributeName))) { + return metaElement.getAttribute(resultAttributeName); + } + } + return null; } - return null; - } - /** - * Gets the first element that is a child of the parentElement and has the given namespace and tagName - * - * @param parentElement parentElement - * @param namespace namespace - * @param tagName tagName - * @return Element - */ - public static Element getFirstElementByTagNameNS(Element parentElement, - String namespace, String tagName) { - NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName); - if (nodes.getLength() != 0) { - return (Element) nodes.item(0); + /** + * Gets the first element that is a child of the parentElement and has the given namespace and tagName + * + * @param parentElement parentElement + * @param namespace namespace + * @param tagName tagName + * @return Element + */ + public static NodeList getElementsByTagNameNS(Element parentElement, + String namespace, String tagName) { + NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName); + if (nodes.getLength() != 0) { + return nodes; + } + nodes = parentElement.getElementsByTagName(tagName); + if (nodes.getLength() == 0) { + return null; + } + return nodes; } - nodes= parentElement.getElementsByTagName(tagName); - if (nodes.getLength()==0){ - return null; + /** + * Gets the first element that is a child of the parentElement and has the given namespace and tagName + * + * @param parentElement parentElement + * @param namespace namespace + * @param tagName tagName + * @return Element + */ + public static NodeList getElementsByTagNameNS(Document parentElement, + String namespace, String tagName) { + NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName); + if (nodes.getLength() != 0) { + return nodes; + } + nodes = parentElement.getElementsByTagName(tagName); + if (nodes.getLength() == 0) { + return null; + } + return nodes; } - return (Element) nodes.item(0); - } - /** - * The contents of all Text nodes that are children of the given parentElement. - * The result is trim()-ed. - * - * The reason for this more complicated procedure instead of just returning the data of the firstChild is that - * when the text is Chinese characters then on Android each Characater is represented in the DOM as - * an individual Text node. - * - * @param parentElement parentElement - * @return String value - */ - public static String getTextChildrenContent(Element parentElement) { - if (parentElement == null) { - return null; + /** + * Gets the first element that is a child of the parentElement and has the given namespace and tagName + * + * @param parentElement parentElement + * @param namespace namespace + * @param tagName tagName + * @return Element + */ + public static Element getFirstElementByTagNameNS(Element parentElement, + String namespace, String tagName) { + NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName); + if (nodes.getLength() != 0) { + return (Element) nodes.item(0); + } + nodes = parentElement.getElementsByTagName(tagName); + if (nodes.getLength() == 0) { + return null; + } + return (Element) nodes.item(0); } - StringBuilder result = new StringBuilder(); - NodeList childNodes = parentElement.getChildNodes(); - for (int i = 0; i < childNodes.getLength(); i++) { - Node node = childNodes.item(i); - if ((node == null) || - (node.getNodeType() != Node.TEXT_NODE)) { - continue; - } - result.append(((Text) node).getData()); + + /** + * The contents of all Text nodes that are children of the given parentElement. + * The result is trim()-ed. + *

+ * The reason for this more complicated procedure instead of just returning the data of the firstChild is that + * when the text is Chinese characters then on Android each Characater is represented in the DOM as + * an individual Text node. + * + * @param parentElement parentElement + * @return String value + */ + public static String getTextChildrenContent(Element parentElement) { + if (parentElement == null) { + return null; + } + StringBuilder result = new StringBuilder(); + NodeList childNodes = parentElement.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + Node node = childNodes.item(i); + if ((node == null) || + (node.getNodeType() != Node.TEXT_NODE)) { + continue; + } + result.append(((Text) node).getData()); + } + return result.toString().trim(); } - return result.toString().trim(); - } } diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataReader.java b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataReader.java index c9ce14429..86f3f95c0 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataReader.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataReader.java @@ -22,7 +22,7 @@ import me.ag2s.epublib.util.StringUtil; /** * Reads the package document metadata. - * + *

* In its own separate class because the PackageDocumentReader became a bit large and unwieldy. * * @author paul @@ -30,195 +30,196 @@ import me.ag2s.epublib.util.StringUtil; // package class PackageDocumentMetadataReader extends PackageDocumentBase { - private static final String TAG= PackageDocumentMetadataReader.class.getName(); - - public static Metadata readMetadata(Document packageDocument) { - Metadata result = new Metadata(); - Element metadataElement = DOMUtil - .getFirstElementByTagNameNS(packageDocument.getDocumentElement(), - NAMESPACE_OPF, OPFTags.metadata); - if (metadataElement == null) { - Log.e(TAG,"Package does not contain element " + OPFTags.metadata); - return result; - } - result.setTitles(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.title)); - result.setPublishers(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.publisher)); - result.setDescriptions(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.description)); - result.setRights(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.rights)); - result.setTypes(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.type)); - result.setSubjects(DOMUtil - .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.subject)); - result.setIdentifiers(readIdentifiers(metadataElement)); - result.setAuthors(readCreators(metadataElement)); - result.setContributors(readContributors(metadataElement)); - result.setDates(readDates(metadataElement)); - result.setOtherProperties(readOtherProperties(metadataElement)); - result.setMetaAttributes(readMetaProperties(metadataElement)); - Element languageTag = DOMUtil - .getFirstElementByTagNameNS(metadataElement, NAMESPACE_DUBLIN_CORE, - DCTags.language); - if (languageTag != null) { - result.setLanguage(DOMUtil.getTextChildrenContent(languageTag)); + private static final String TAG = PackageDocumentMetadataReader.class.getName(); + + public static Metadata readMetadata(Document packageDocument) { + Metadata result = new Metadata(); + Element metadataElement = DOMUtil + .getFirstElementByTagNameNS(packageDocument.getDocumentElement(), + NAMESPACE_OPF, OPFTags.metadata); + if (metadataElement == null) { + Log.e(TAG, "Package does not contain element " + OPFTags.metadata); + return result; + } + result.setTitles(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.title)); + result.setPublishers(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.publisher)); + result.setDescriptions(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.description)); + result.setRights(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.rights)); + result.setTypes(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.type)); + result.setSubjects(DOMUtil + .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.subject)); + result.setIdentifiers(readIdentifiers(metadataElement)); + result.setAuthors(readCreators(metadataElement)); + result.setContributors(readContributors(metadataElement)); + result.setDates(readDates(metadataElement)); + result.setOtherProperties(readOtherProperties(metadataElement)); + result.setMetaAttributes(readMetaProperties(metadataElement)); + Element languageTag = DOMUtil + .getFirstElementByTagNameNS(metadataElement, NAMESPACE_DUBLIN_CORE, + DCTags.language); + if (languageTag != null) { + result.setLanguage(DOMUtil.getTextChildrenContent(languageTag)); + } + + return result; } - return result; - } - - /** - * consumes meta tags that have a property attribute as defined in the standard. For example: - * <meta property="rendition:layout">pre-paginated</meta> - * @param metadataElement metadataElement - * @return Map - */ - private static Map readOtherProperties( - Element metadataElement) { - Map result = new HashMap<>(); - - NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); - for (int i = 0; i < metaTags.getLength(); i++) { - Node metaNode = metaTags.item(i); - Node property = metaNode.getAttributes() - .getNamedItem(OPFAttributes.property); - if (property != null) { - String name = property.getNodeValue(); - String value = metaNode.getTextContent(); - result.put(new QName(name), value); - } + /** + * consumes meta tags that have a property attribute as defined in the standard. For example: + * <meta property="rendition:layout">pre-paginated</meta> + * + * @param metadataElement metadataElement + * @return Map + */ + private static Map readOtherProperties( + Element metadataElement) { + Map result = new HashMap<>(); + + NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); + for (int i = 0; i < metaTags.getLength(); i++) { + Node metaNode = metaTags.item(i); + Node property = metaNode.getAttributes() + .getNamedItem(OPFAttributes.property); + if (property != null) { + String name = property.getNodeValue(); + String value = metaNode.getTextContent(); + result.put(new QName(name), value); + } + } + + return result; } - return result; - } - - /** - * consumes meta tags that have a property attribute as defined in the standard. For example: - * <meta property="rendition:layout">pre-paginated</meta> - * @param metadataElement metadataElement - * @return Map - */ - private static Map readMetaProperties( - Element metadataElement) { - Map result = new HashMap<>(); - - NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); - for (int i = 0; i < metaTags.getLength(); i++) { - Element metaElement = (Element) metaTags.item(i); - String name = metaElement.getAttribute(OPFAttributes.name); - String value = metaElement.getAttribute(OPFAttributes.content); - result.put(name, value); + /** + * consumes meta tags that have a property attribute as defined in the standard. For example: + * <meta property="rendition:layout">pre-paginated</meta> + * + * @param metadataElement metadataElement + * @return Map + */ + private static Map readMetaProperties( + Element metadataElement) { + Map result = new HashMap<>(); + + NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); + for (int i = 0; i < metaTags.getLength(); i++) { + Element metaElement = (Element) metaTags.item(i); + String name = metaElement.getAttribute(OPFAttributes.name); + String value = metaElement.getAttribute(OPFAttributes.content); + result.put(name, value); + } + + return result; } - return result; - } + private static String getBookIdId(Document document) { + Element packageElement = DOMUtil + .getFirstElementByTagNameNS(document.getDocumentElement(), + NAMESPACE_OPF, OPFTags.packageTag); + if (packageElement == null) { + return null; + } + return DOMUtil.getAttribute(packageElement, NAMESPACE_OPF, OPFAttributes.uniqueIdentifier); - private static String getBookIdId(Document document) { - Element packageElement = DOMUtil - .getFirstElementByTagNameNS(document.getDocumentElement(), - NAMESPACE_OPF, OPFTags.packageTag); - if (packageElement == null) { - return null; } - return packageElement - .getAttributeNS(NAMESPACE_OPF, OPFAttributes.uniqueIdentifier); - } - - private static List readCreators(Element metadataElement) { - return readAuthors(DCTags.creator, metadataElement); - } - - private static List readContributors(Element metadataElement) { - return readAuthors(DCTags.contributor, metadataElement); - } - - private static List readAuthors(String authorTag, - Element metadataElement) { - NodeList elements = metadataElement - .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, authorTag); - List result = new ArrayList<>(elements.getLength()); - for (int i = 0; i < elements.getLength(); i++) { - Element authorElement = (Element) elements.item(i); - Author author = createAuthor(authorElement); - if (author != null) { - result.add(author); - } + + private static List readCreators(Element metadataElement) { + return readAuthors(DCTags.creator, metadataElement); } - return result; - - } - - private static List readDates(Element metadataElement) { - NodeList elements = metadataElement - .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.date); - List result = new ArrayList<>(elements.getLength()); - for (int i = 0; i < elements.getLength(); i++) { - Element dateElement = (Element) elements.item(i); - Date date; - try { - date = new Date(DOMUtil.getTextChildrenContent(dateElement), - dateElement.getAttributeNS(NAMESPACE_OPF, OPFAttributes.event)); - result.add(date); - } catch (IllegalArgumentException e) { - Log.e(TAG,e.getMessage()); - } + + private static List readContributors(Element metadataElement) { + return readAuthors(DCTags.contributor, metadataElement); } - return result; - } + private static List readAuthors(String authorTag, + Element metadataElement) { + NodeList elements = metadataElement + .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, authorTag); + List result = new ArrayList<>(elements.getLength()); + for (int i = 0; i < elements.getLength(); i++) { + Element authorElement = (Element) elements.item(i); + Author author = createAuthor(authorElement); + if (author != null) { + result.add(author); + } + } + return result; - private static Author createAuthor(Element authorElement) { - String authorString = DOMUtil.getTextChildrenContent(authorElement); - if (StringUtil.isBlank(authorString)) { - return null; } - int spacePos = authorString.lastIndexOf(' '); - Author result; - if (spacePos < 0) { - result = new Author(authorString); - } else { - result = new Author(authorString.substring(0, spacePos), - authorString.substring(spacePos + 1)); + + private static List readDates(Element metadataElement) { + NodeList elements = metadataElement + .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.date); + List result = new ArrayList<>(elements.getLength()); + for (int i = 0; i < elements.getLength(); i++) { + Element dateElement = (Element) elements.item(i); + Date date; + try { + date = new Date(DOMUtil.getTextChildrenContent(dateElement), + DOMUtil.getAttribute(dateElement, NAMESPACE_OPF, OPFAttributes.event)); + result.add(date); + } catch (IllegalArgumentException e) { + Log.e(TAG, e.getMessage()); + } + } + return result; + } - result.setRole( - authorElement.getAttributeNS(NAMESPACE_OPF, OPFAttributes.role)); - return result; - } - - - private static List readIdentifiers(Element metadataElement) { - NodeList identifierElements = metadataElement - .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.identifier); - if (identifierElements.getLength() == 0) { - Log.e(TAG,"Package does not contain element " + DCTags.identifier); - return new ArrayList<>(); + + private static Author createAuthor(Element authorElement) { + String authorString = DOMUtil.getTextChildrenContent(authorElement); + if (StringUtil.isBlank(authorString)) { + return null; + } + int spacePos = authorString.lastIndexOf(' '); + Author result; + if (spacePos < 0) { + result = new Author(authorString); + } else { + result = new Author(authorString.substring(0, spacePos), + authorString.substring(spacePos + 1)); + } + result.setRole( + DOMUtil.getAttribute(authorElement, NAMESPACE_OPF, OPFAttributes.role)); + return result; } - String bookIdId = getBookIdId(metadataElement.getOwnerDocument()); - List result = new ArrayList<>( - identifierElements.getLength()); - for (int i = 0; i < identifierElements.getLength(); i++) { - Element identifierElement = (Element) identifierElements.item(i); - String schemeName = identifierElement - .getAttributeNS(NAMESPACE_OPF, DCAttributes.scheme); - String identifierValue = DOMUtil - .getTextChildrenContent(identifierElement); - if (StringUtil.isBlank(identifierValue)) { - continue; - } - Identifier identifier = new Identifier(schemeName, identifierValue); - if (identifierElement.getAttribute("id").equals(bookIdId)) { - identifier.setBookId(true); - } - result.add(identifier); + + + private static List readIdentifiers(Element metadataElement) { + NodeList identifierElements = metadataElement + .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.identifier); + if (identifierElements.getLength() == 0) { + Log.e(TAG, "Package does not contain element " + DCTags.identifier); + return new ArrayList<>(); + } + String bookIdId = getBookIdId(metadataElement.getOwnerDocument()); + List result = new ArrayList<>( + identifierElements.getLength()); + for (int i = 0; i < identifierElements.getLength(); i++) { + Element identifierElement = (Element) identifierElements.item(i); + String schemeName = DOMUtil.getAttribute(identifierElement, NAMESPACE_OPF, DCAttributes.scheme); + String identifierValue = DOMUtil + .getTextChildrenContent(identifierElement); + if (StringUtil.isBlank(identifierValue)) { + continue; + } + Identifier identifier = new Identifier(schemeName, identifierValue); + if (identifierElement.getAttribute("id").equals(bookIdId)) { + identifier.setBookId(true); + } + result.add(identifier); + } + return result; } - return result; - } } diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java index 5cf8adf1a..eaf0c4687 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java @@ -245,18 +245,18 @@ public class PackageDocumentReader extends PackageDocumentBase { return generateSpineFromResources(resources); } Spine result = new Spine(); - String tocResourceId = DOMUtil - .getAttribute(spineElement, NAMESPACE_OPF, OPFAttributes.toc); - result - .setTocResource(findTableOfContentsResource(tocResourceId, resources)); - NodeList spineNodes = packageDocument - .getElementsByTagNameNS(NAMESPACE_OPF, OPFTags.itemref); - List spineReferences = new ArrayList<>( - spineNodes.getLength()); + String tocResourceId = DOMUtil.getAttribute(spineElement, NAMESPACE_OPF, OPFAttributes.toc); + Log.v(TAG,tocResourceId); + result.setTocResource(findTableOfContentsResource(tocResourceId, resources)); + NodeList spineNodes = DOMUtil.getElementsByTagNameNS(packageDocument, NAMESPACE_OPF, OPFTags.itemref); + if(spineNodes==null){ + Log.e(TAG,"spineNodes is null"); + return result; + } + List spineReferences = new ArrayList<>(spineNodes.getLength()); for (int i = 0; i < spineNodes.getLength(); i++) { Element spineItem = (Element) spineNodes.item(i); - String itemref = DOMUtil - .getAttribute(spineItem, NAMESPACE_OPF, OPFAttributes.idref); + String itemref = DOMUtil.getAttribute(spineItem, NAMESPACE_OPF, OPFAttributes.idref); if (StringUtil.isBlank(itemref)) { Log.e(TAG, "itemref with missing or empty idref"); // XXX continue; @@ -265,6 +265,7 @@ public class PackageDocumentReader extends PackageDocumentBase { if (id == null) { id = itemref; } + Resource resource = resources.getByIdOrHref(id); if (resource == null) { Log.e(TAG, "resource with id '" + id + "' not found"); diff --git a/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java b/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java index df53b0162..5da77b8d2 100644 --- a/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java +++ b/epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java @@ -2,16 +2,6 @@ package me.ag2s.epublib.epub; import android.util.Log; -import me.ag2s.epublib.domain.EpubResourceProvider; -import me.ag2s.epublib.domain.LazyResource; -import me.ag2s.epublib.domain.LazyResourceProvider; -import me.ag2s.epublib.domain.MediaType; -import me.ag2s.epublib.domain.MediaTypes; -import me.ag2s.epublib.domain.Resource; -import me.ag2s.epublib.domain.Resources; -import me.ag2s.epublib.util.CollectionUtil; -import me.ag2s.epublib.util.ResourceUtil; - import java.io.IOException; import java.util.ArrayList; import java.util.Collection; @@ -22,6 +12,16 @@ import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; +import me.ag2s.epublib.domain.EpubResourceProvider; +import me.ag2s.epublib.domain.LazyResource; +import me.ag2s.epublib.domain.LazyResourceProvider; +import me.ag2s.epublib.domain.MediaType; +import me.ag2s.epublib.domain.MediaTypes; +import me.ag2s.epublib.domain.Resource; +import me.ag2s.epublib.domain.Resources; +import me.ag2s.epublib.util.CollectionUtil; +import me.ag2s.epublib.util.ResourceUtil; + /** * Loads Resources from inputStreams, ZipFiles, etc @@ -72,6 +72,12 @@ public class ResourcesLoader { } else { resource = ResourceUtil .createResource(zipEntry, zipFile.getInputStream(zipEntry)); + /*掌上书苑有很多自制书OPF的nameSpace格式不标准,强制修复成正确的格式*/ + if (href.endsWith("opf")) { + String string = new String(resource.getData()).replace("smlns=\"", "xmlns=\""); + resource.setData(string.getBytes()); + } + } if (resource.getMediaType() == MediaTypes.XHTML) { @@ -123,9 +129,15 @@ public class ResourcesLoader { if ((zipEntry == null) || zipEntry.isDirectory()) { continue; } + String href = zipEntry.getName(); // store resource Resource resource = ResourceUtil.createResource(zipEntry, zipInputStream); + ///*掌上书苑有很多自制书OPF的nameSpace格式不标准,强制修复成正确的格式*/ + if (href.endsWith("opf")) { + String string = new String(resource.getData()).replace("smlns=\"", "xmlns=\""); + resource.setData(string.getBytes()); + } if (resource.getMediaType() == MediaTypes.XHTML) { resource.setInputEncoding(defaultHtmlEncoding); }