因为在toc.ncx中navPoint节点存在嵌套,所有使用递归的方式找出所有navPoint节点,并通过chapterLevel标明层级关系。
关键代码如下:
private void parseNcxFile() throws SAXException, IOException {
if ("".equals(ncx)) {
return;
}
EpubManifestItem manifestItem = manifestItemMap.get(ncx);
String ncxPath = manifestItem.href;
String ncxFile = ncxPath;
MM.sysout("ncxFile: " + ncxFile);
File file = new File(ncxFile);
InputStream is = new FileInputStream(file);
Document document = mDocumentBuilder.parse(is);
NodeList navPointElements = document.getElementsByTagName("navPoint");
MM.sysout("navPointElements大小:" + navPointElements.getLength());
ArrayList<Node> theNavPointsList = new ArrayList<Node>(); // 获取父节点为navMap的所有navPoint
for (int m = 0; m < navPointElements.getLength(); m++) {
Node item = navPointElements.item(m);
Node parentNode = item.getParentNode();
// 判断父节点是否为navMap
if ("navMap".equals(parentNode.getNodeName())) {
theNavPointsList.add(item);
}
}
MM.sysout("父节点为navMap的navPoint集合大小:" + theNavPointsList.size());
// Map<String, String> titleDictionary = new HashMap<String, String>(); // 存放目录标题的字典
// Map<String, Integer> chapterLevelDictionary = new HashMap<String, Integer>(); // 存放目录等级的字典(显示到UI上时要根据目录的等级来排列)
// getChapterTitle(theNavPointsList, titleDictionary, chapterLevelDictionary);
// MM.sysout("titleDictionary大小:" + titleDictionary.size());
// // 遍历Map 第三种:推荐,尤其是容量大时
// for (Map.Entry<String, String> titleEntry : titleDictionary.entrySet()) {
// MM.sysout("key= " + titleEntry.getKey() + " and value= " + titleEntry.getValue());
// }
// MM.sysout("chapterLevelDictionary大小:" + chapterLevelDictionary.size());
// for (Map.Entry<String, Integer> chapterLevelEntry : chapterLevelDictionary.entrySet()) {
// MM.sysout("key= " + chapterLevelEntry.getKey() + " and value= " + chapterLevelEntry.getValue());
// }
navPointItemMap = new TreeMap<Integer, EpubNavPointItem>();
getChapterTitle(theNavPointsList, navPointItemMap);
MM.sysout("navPointItemMap大小:" + navPointItemMap.size());
// for (Map.Entry<Integer, EpubNavPointItem> navPointItemEntry : navPointItemMap.entrySet()) {
// EpubNavPointItem value = navPointItemEntry.getValue();
// MM.sysout("key=" + navPointItemEntry.getKey() + " and value=" + value.getChapterLevel() + " " + value.getText());
// }
DocinApplication.getInstance().navPointItemMap = navPointItemMap;
}
/**
* @param theNavPoints
* 一级目录数组
* @param titleDictionary
* 存放目录标题的字典
* @param chapterLevelDictionary
* 存放目录等级的字典(显示到UI上时要根据目录的等级来排列)
* @throws SAXException
* @throws IOException
*/
// private void getChapterTitle(ArrayList<Node> theNavPoints, Map<String, String> titleDictionary, Map<String, Integer> chapterLevelDictionary) throws SAXException, IOException {
private void getChapterTitle(ArrayList<Node> theNavPoints, Map<Integer, EpubNavPointItem> navPointItemMap) throws SAXException, IOException {
if (theNavPoints != null && theNavPoints.size() > 0) {
for (int i = 0; i < theNavPoints.size(); i++) {
Node item = theNavPoints.get(i);
if (!("navPoint".equals(item.getNodeName()))) {
continue;
}
Element element = (Element) item; // 一个navPoint中包含的东西
int order = Integer.parseInt(element.getAttribute("playOrder"));
Element contentElement = (Element) element.getElementsByTagName("content").item(0);
String href = contentElement.getAttribute("src"); // 章节地址src
Element navLabel = (Element) element.getElementsByTagName("navLabel").item(0); // 获得navLabel节点
Element textNode = (Element) navLabel.getElementsByTagName("text").item(0); // 获得text节点
String title = textNode.getTextContent();
// titleDictionary.put(href, title);
// chapterLevelDictionary.put(href, chapterLevel);
EpubNavPointItem navPointItem = new EpubNavPointItem();
navPointItem.playOrder = order;
navPointItem.text = title;
navPointItem.content = this.epubBaseDir + "/" + href;
navPointItem.chapterLevel = chapterLevel;
navPointItemMap.put(navPointItem.playOrder, navPointItem);
// MM.sysout("navPoint: 层级(" + chapterLevel + "), 排序(" + order + "), 标题(" + title + "), 索引( " + navPointItem.content + ")");
// 获取嵌套的navPoint,递归
// NodeList secondNavPoints = element.getElementsByTagName("navPoint");
NodeList secondNavPoints = element.getChildNodes();
ArrayList<Node> secondNavPointsList = new ArrayList<Node>();
if (secondNavPoints != null && secondNavPoints.getLength() > 0) {
// MM.sysout("secondeNavPoints的大小:" + secondNavPoints.getLength());
for (int n = 0; n < secondNavPoints.getLength(); n++) {
Node secondItem = secondNavPoints.item(n);
secondNavPointsList.add(secondItem);
}
chapterLevel++;
// getChapterTitle(secondNavPointsList, titleDictionary, chapterLevelDictionary);
getChapterTitle(secondNavPointsList, navPointItemMap);
}
}
chapterLevel--; // 每跳出一次递归就减1
}
}
River《webview实现epub阅读器详解》讨论帖:http://www.eoeandroid.com/thread-240122-1-1.html
iPhone开发中对epub图书ncx文件的解析:http://www.cocoachina.com/bbs/read.php?tid=145360