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 input ?: return null
FileUtils.writeInputStream(file, input) 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) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
} }

@ -1,135 +1,177 @@
package me.ag2s.epublib.epub; 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.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.w3c.dom.Text; 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. * Utility methods for working with the DOM.
* *
* @author paul * @author paul
*
*/ */
// package // package
class DOMUtil { 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. * 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 element element
* @param namespace namespace * @param namespace namespace
* @param attribute attribute * @param attribute attribute
* @return String Attribute * @return String Attribute
*/ */
public static String getAttribute(Element element, String namespace, public static String getAttribute(Element element, String namespace,
String attribute) { String attribute) {
String result = element.getAttributeNS(namespace, attribute); String result = element.getAttributeNS(namespace, attribute);
if (StringUtil.isEmpty(result)) { if (StringUtil.isEmpty(result)) {
result = element.getAttribute(attribute); 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. * 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 parentElement parentElement
* @param namespace namespace * @param namespace namespace
* @param tagName tagName * @param tagName tagName
* @return List<String> * @return List<String>
*/ */
public static List<String> getElementsTextChild(Element parentElement, public static List<String> getElementsTextChild(Element parentElement,
String namespace, String tagName) { String namespace, String tagName) {
NodeList elements = parentElement NodeList elements = parentElement
.getElementsByTagNameNS(namespace, tagName); .getElementsByTagNameNS(namespace, tagName);
//ArrayList 初始化时指定长度提高性能 //ArrayList 初始化时指定长度提高性能
List<String> result = new ArrayList<>(elements.getLength()); List<String> result = new ArrayList<>(elements.getLength());
for (int i = 0; i < elements.getLength(); i++) { for (int i = 0; i < elements.getLength(); i++) {
result.add(getTextChildrenContent((Element) elements.item(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. * 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. * It then returns the value of the given resultAttributeName.
* *
* @param document document * @param document document
* @param namespace namespace * @param namespace namespace
* @param elementName elementName * @param elementName elementName
* @param findAttributeName findAttributeName * @param findAttributeName findAttributeName
* @param findAttributeValue findAttributeValue * @param findAttributeValue findAttributeValue
* @param resultAttributeName resultAttributeName * @param resultAttributeName resultAttributeName
* @return String value * @return String value
*/ */
public static String getFindAttributeValue(Document document, public static String getFindAttributeValue(Document document,
String namespace, String elementName, String findAttributeName, String namespace, String elementName, String findAttributeName,
String findAttributeValue, String resultAttributeName) { String findAttributeValue, String resultAttributeName) {
NodeList metaTags = document.getElementsByTagNameNS(namespace, elementName); NodeList metaTags = document.getElementsByTagNameNS(namespace, elementName);
for (int i = 0; i < metaTags.getLength(); i++) { for (int i = 0; i < metaTags.getLength(); i++) {
Element metaElement = (Element) metaTags.item(i); Element metaElement = (Element) metaTags.item(i);
if (findAttributeValue if (findAttributeValue
.equalsIgnoreCase(metaElement.getAttribute(findAttributeName)) .equalsIgnoreCase(metaElement.getAttribute(findAttributeName))
&& StringUtil && StringUtil
.isNotBlank(metaElement.getAttribute(resultAttributeName))) { .isNotBlank(metaElement.getAttribute(resultAttributeName))) {
return 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 * Gets the first element that is a child of the parentElement and has the given namespace and tagName
* *
* @param parentElement parentElement * @param parentElement parentElement
* @param namespace namespace * @param namespace namespace
* @param tagName tagName * @param tagName tagName
* @return Element * @return Element
*/ */
public static Element getFirstElementByTagNameNS(Element parentElement, public static NodeList getElementsByTagNameNS(Element parentElement,
String namespace, String tagName) { String namespace, String tagName) {
NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName); NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName);
if (nodes.getLength() != 0) { if (nodes.getLength() != 0) {
return (Element) nodes.item(0); return nodes;
}
nodes = parentElement.getElementsByTagName(tagName);
if (nodes.getLength() == 0) {
return null;
}
return nodes;
} }
nodes= parentElement.getElementsByTagName(tagName); /**
if (nodes.getLength()==0){ * Gets the first element that is a child of the parentElement and has the given namespace and tagName
return null; *
* @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. * Gets the first element that is a child of the parentElement and has the given namespace and tagName
* The result is trim()-ed. *
* * @param parentElement parentElement
* The reason for this more complicated procedure instead of just returning the data of the firstChild is that * @param namespace namespace
* when the text is Chinese characters then on Android each Characater is represented in the DOM as * @param tagName tagName
* an individual Text node. * @return Element
* */
* @param parentElement parentElement public static Element getFirstElementByTagNameNS(Element parentElement,
* @return String value String namespace, String tagName) {
*/ NodeList nodes = parentElement.getElementsByTagNameNS(namespace, tagName);
public static String getTextChildrenContent(Element parentElement) { if (nodes.getLength() != 0) {
if (parentElement == null) { return (Element) nodes.item(0);
return null; }
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++) { * The contents of all Text nodes that are children of the given parentElement.
Node node = childNodes.item(i); * The result is trim()-ed.
if ((node == null) || * <p>
(node.getNodeType() != Node.TEXT_NODE)) { * The reason for this more complicated procedure instead of just returning the data of the firstChild is that
continue; * when the text is Chinese characters then on Android each Characater is represented in the DOM as
} * an individual Text node.
result.append(((Text) node).getData()); *
* @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. * Reads the package document metadata.
* * <p>
* In its own separate class because the PackageDocumentReader became a bit large and unwieldy. * In its own separate class because the PackageDocumentReader became a bit large and unwieldy.
* *
* @author paul * @author paul
@ -30,195 +30,196 @@ import me.ag2s.epublib.util.StringUtil;
// package // package
class PackageDocumentMetadataReader extends PackageDocumentBase { class PackageDocumentMetadataReader extends PackageDocumentBase {
private static final String TAG= PackageDocumentMetadataReader.class.getName(); private static final String TAG = PackageDocumentMetadataReader.class.getName();
public static Metadata readMetadata(Document packageDocument) { public static Metadata readMetadata(Document packageDocument) {
Metadata result = new Metadata(); Metadata result = new Metadata();
Element metadataElement = DOMUtil Element metadataElement = DOMUtil
.getFirstElementByTagNameNS(packageDocument.getDocumentElement(), .getFirstElementByTagNameNS(packageDocument.getDocumentElement(),
NAMESPACE_OPF, OPFTags.metadata); NAMESPACE_OPF, OPFTags.metadata);
if (metadataElement == null) { if (metadataElement == null) {
Log.e(TAG,"Package does not contain element " + OPFTags.metadata); Log.e(TAG, "Package does not contain element " + OPFTags.metadata);
return result; return result;
} }
result.setTitles(DOMUtil result.setTitles(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.title)); DCTags.title));
result.setPublishers(DOMUtil result.setPublishers(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.publisher)); DCTags.publisher));
result.setDescriptions(DOMUtil result.setDescriptions(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.description)); DCTags.description));
result.setRights(DOMUtil result.setRights(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.rights)); DCTags.rights));
result.setTypes(DOMUtil result.setTypes(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.type)); DCTags.type));
result.setSubjects(DOMUtil result.setSubjects(DOMUtil
.getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE, .getElementsTextChild(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.subject)); DCTags.subject));
result.setIdentifiers(readIdentifiers(metadataElement)); result.setIdentifiers(readIdentifiers(metadataElement));
result.setAuthors(readCreators(metadataElement)); result.setAuthors(readCreators(metadataElement));
result.setContributors(readContributors(metadataElement)); result.setContributors(readContributors(metadataElement));
result.setDates(readDates(metadataElement)); result.setDates(readDates(metadataElement));
result.setOtherProperties(readOtherProperties(metadataElement)); result.setOtherProperties(readOtherProperties(metadataElement));
result.setMetaAttributes(readMetaProperties(metadataElement)); result.setMetaAttributes(readMetaProperties(metadataElement));
Element languageTag = DOMUtil Element languageTag = DOMUtil
.getFirstElementByTagNameNS(metadataElement, NAMESPACE_DUBLIN_CORE, .getFirstElementByTagNameNS(metadataElement, NAMESPACE_DUBLIN_CORE,
DCTags.language); DCTags.language);
if (languageTag != null) { if (languageTag != null) {
result.setLanguage(DOMUtil.getTextChildrenContent(languageTag)); 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;
/** *
* consumes meta tags that have a property attribute as defined in the standard. For example: * @param metadataElement metadataElement
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt; * @return Map<QName, String>
* @param metadataElement metadataElement */
* @return Map<QName, String> private static Map<QName, String> readOtherProperties(
*/ Element metadataElement) {
private static Map<QName, String> readOtherProperties( Map<QName, String> result = new HashMap<>();
Element metadataElement) {
Map<QName, String> result = new HashMap<>(); NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta);
for (int i = 0; i < metaTags.getLength(); i++) {
NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); Node metaNode = metaTags.item(i);
for (int i = 0; i < metaTags.getLength(); i++) { Node property = metaNode.getAttributes()
Node metaNode = metaTags.item(i); .getNamedItem(OPFAttributes.property);
Node property = metaNode.getAttributes() if (property != null) {
.getNamedItem(OPFAttributes.property); String name = property.getNodeValue();
if (property != null) { String value = metaNode.getTextContent();
String name = property.getNodeValue(); result.put(new QName(name), value);
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;
/** *
* consumes meta tags that have a property attribute as defined in the standard. For example: * @param metadataElement metadataElement
* &lt;meta property="rendition:layout"&gt;pre-paginated&lt;/meta&gt; * @return Map<String, String>
* @param metadataElement metadataElement */
* @return Map<String, String> private static Map<String, String> readMetaProperties(
*/ Element metadataElement) {
private static Map<String, String> readMetaProperties( Map<String, String> result = new HashMap<>();
Element metadataElement) {
Map<String, String> result = new HashMap<>(); NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta);
for (int i = 0; i < metaTags.getLength(); i++) {
NodeList metaTags = metadataElement.getElementsByTagName(OPFTags.meta); Element metaElement = (Element) metaTags.item(i);
for (int i = 0; i < metaTags.getLength(); i++) { String name = metaElement.getAttribute(OPFAttributes.name);
Element metaElement = (Element) metaTags.item(i); String value = metaElement.getAttribute(OPFAttributes.content);
String name = metaElement.getAttribute(OPFAttributes.name); result.put(name, value);
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> 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);
}
} }
return result;
private static List<Author> readContributors(Element metadataElement) {
} return readAuthors(DCTags.contributor, metadataElement);
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());
}
} }
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; private static List<Date> readDates(Element metadataElement) {
if (spacePos < 0) { NodeList elements = metadataElement
result = new Author(authorString); .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.date);
} else { List<Date> result = new ArrayList<>(elements.getLength());
result = new Author(authorString.substring(0, spacePos), for (int i = 0; i < elements.getLength(); i++) {
authorString.substring(spacePos + 1)); 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)); private static Author createAuthor(Element authorElement) {
return result; String authorString = DOMUtil.getTextChildrenContent(authorElement);
} if (StringUtil.isBlank(authorString)) {
return null;
}
private static List<Identifier> readIdentifiers(Element metadataElement) { int spacePos = authorString.lastIndexOf(' ');
NodeList identifierElements = metadataElement Author result;
.getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.identifier); if (spacePos < 0) {
if (identifierElements.getLength() == 0) { result = new Author(authorString);
Log.e(TAG,"Package does not contain element " + DCTags.identifier); } else {
return new ArrayList<>(); 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()); private static List<Identifier> readIdentifiers(Element metadataElement) {
for (int i = 0; i < identifierElements.getLength(); i++) { NodeList identifierElements = metadataElement
Element identifierElement = (Element) identifierElements.item(i); .getElementsByTagNameNS(NAMESPACE_DUBLIN_CORE, DCTags.identifier);
String schemeName = identifierElement if (identifierElements.getLength() == 0) {
.getAttributeNS(NAMESPACE_OPF, DCAttributes.scheme); Log.e(TAG, "Package does not contain element " + DCTags.identifier);
String identifierValue = DOMUtil return new ArrayList<>();
.getTextChildrenContent(identifierElement); }
if (StringUtil.isBlank(identifierValue)) { String bookIdId = getBookIdId(metadataElement.getOwnerDocument());
continue; List<Identifier> result = new ArrayList<>(
} identifierElements.getLength());
Identifier identifier = new Identifier(schemeName, identifierValue); for (int i = 0; i < identifierElements.getLength(); i++) {
if (identifierElement.getAttribute("id").equals(bookIdId)) { Element identifierElement = (Element) identifierElements.item(i);
identifier.setBookId(true); String schemeName = DOMUtil.getAttribute(identifierElement, NAMESPACE_OPF, DCAttributes.scheme);
} String identifierValue = DOMUtil
result.add(identifier); .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); return generateSpineFromResources(resources);
} }
Spine result = new Spine(); Spine result = new Spine();
String tocResourceId = DOMUtil String tocResourceId = DOMUtil.getAttribute(spineElement, NAMESPACE_OPF, OPFAttributes.toc);
.getAttribute(spineElement, NAMESPACE_OPF, OPFAttributes.toc); Log.v(TAG,tocResourceId);
result result.setTocResource(findTableOfContentsResource(tocResourceId, resources));
.setTocResource(findTableOfContentsResource(tocResourceId, resources)); NodeList spineNodes = DOMUtil.getElementsByTagNameNS(packageDocument, NAMESPACE_OPF, OPFTags.itemref);
NodeList spineNodes = packageDocument if(spineNodes==null){
.getElementsByTagNameNS(NAMESPACE_OPF, OPFTags.itemref); Log.e(TAG,"spineNodes is null");
List<SpineReference> spineReferences = new ArrayList<>( return result;
spineNodes.getLength()); }
List<SpineReference> spineReferences = new ArrayList<>(spineNodes.getLength());
for (int i = 0; i < spineNodes.getLength(); i++) { for (int i = 0; i < spineNodes.getLength(); i++) {
Element spineItem = (Element) spineNodes.item(i); Element spineItem = (Element) spineNodes.item(i);
String itemref = DOMUtil String itemref = DOMUtil.getAttribute(spineItem, NAMESPACE_OPF, OPFAttributes.idref);
.getAttribute(spineItem, NAMESPACE_OPF, OPFAttributes.idref);
if (StringUtil.isBlank(itemref)) { if (StringUtil.isBlank(itemref)) {
Log.e(TAG, "itemref with missing or empty idref"); // XXX Log.e(TAG, "itemref with missing or empty idref"); // XXX
continue; continue;
@ -265,6 +265,7 @@ public class PackageDocumentReader extends PackageDocumentBase {
if (id == null) { if (id == null) {
id = itemref; id = itemref;
} }
Resource resource = resources.getByIdOrHref(id); Resource resource = resources.getByIdOrHref(id);
if (resource == null) { if (resource == null) {
Log.e(TAG, "resource with id '" + id + "' not found"); Log.e(TAG, "resource with id '" + id + "' not found");

@ -2,16 +2,6 @@ package me.ag2s.epublib.epub;
import android.util.Log; 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.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -22,6 +12,16 @@ import java.util.zip.ZipException;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream; 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 * Loads Resources from inputStreams, ZipFiles, etc
@ -72,6 +72,12 @@ public class ResourcesLoader {
} else { } else {
resource = ResourceUtil resource = ResourceUtil
.createResource(zipEntry, zipFile.getInputStream(zipEntry)); .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) { if (resource.getMediaType() == MediaTypes.XHTML) {
@ -123,9 +129,15 @@ public class ResourcesLoader {
if ((zipEntry == null) || zipEntry.isDirectory()) { if ((zipEntry == null) || zipEntry.isDirectory()) {
continue; continue;
} }
String href = zipEntry.getName();
// store resource // store resource
Resource resource = ResourceUtil.createResource(zipEntry, zipInputStream); 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) { if (resource.getMediaType() == MediaTypes.XHTML) {
resource.setInputEncoding(defaultHtmlEncoding); resource.setInputEncoding(defaultHtmlEncoding);
} }

Loading…
Cancel
Save