pull/957/head
ag2s20150909 4 years ago
parent 77a1dbe7f4
commit 31ee3400b4
  1. 26
      app/src/main/java/io/legado/app/model/localBook/EpubFile.kt
  2. 254
      epublib/src/main/java/me/ag2s/epublib/epub/DOMUtil.java
  3. 353
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentMetadataReader.java
  4. 21
      epublib/src/main/java/me/ag2s/epublib/epub/PackageDocumentReader.java
  5. 32
      epublib/src/main/java/me/ag2s/epublib/epub/ResourcesLoader.java

@ -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("<error>")) 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()
}

@ -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<String>
*/
public static List<String> getElementsTextChild(Element parentElement,
String namespace, String tagName) {
NodeList elements = parentElement
.getElementsByTagNameNS(namespace, tagName);
//ArrayList 初始化时指定长度提高性能
List<String> 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<String>
*/
public static List<String> getElementsTextChild(Element parentElement,
String namespace, String tagName) {
NodeList elements = parentElement
.getElementsByTagNameNS(namespace, tagName);
//ArrayList 初始化时指定长度提高性能
List<String> 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.
* <p>
* 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();
}
}

@ -22,7 +22,7 @@ import me.ag2s.epublib.util.StringUtil;
/**
* Reads the package document metadata.
*
* <p>
* 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:
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt;
* @param metadataElement metadataElement
* @return Map<QName, String>
*/
private static Map<QName, String> readOtherProperties(
Element metadataElement) {
Map<QName, String> 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:
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt;
*
* @param metadataElement metadataElement
* @return Map<QName, String>
*/
private static Map<QName, String> readOtherProperties(
Element metadataElement) {
Map<QName, String> 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:
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt;
* @param metadataElement metadataElement
* @return Map<String, String>
*/
private static Map<String, String> readMetaProperties(
Element metadataElement) {
Map<String, String> 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:
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt;
*
* @param metadataElement metadataElement
* @return Map<String, String>
*/
private static Map<String, String> readMetaProperties(
Element metadataElement) {
Map<String, String> 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<Author> readCreators(Element metadataElement) {
return readAuthors(DCTags.creator, metadataElement);
}
private static List<Author> readContributors(Element metadataElement) {
return readAuthors(DCTags.contributor, metadataElement);
}
private static List<Author> readAuthors(String authorTag,
Element metadataElement) {
NodeList elements = metadataElement
.getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, authorTag);
List<Author> 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<Author> readCreators(Element metadataElement) {
return readAuthors(DCTags.creator, metadataElement);
}
return result;
}
private static List<Date> readDates(Element metadataElement) {
NodeList elements = metadataElement
.getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.date);
List<Date> 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<Author> readContributors(Element metadataElement) {
return readAuthors(DCTags.contributor, metadataElement);
}
return result;
}
private static List<Author> readAuthors(String authorTag,
Element metadataElement) {
NodeList elements = metadataElement
.getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, authorTag);
List<Author> 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<Date> readDates(Element metadataElement) {
NodeList elements = metadataElement
.getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.date);
List<Date> 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<Identifier> 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<Identifier> 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<Identifier> 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<Identifier> 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;
}
}

@ -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<SpineReference> 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<SpineReference> 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");

@ -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);
}

Loading…
Cancel
Save