epub书籍中关于.ncx的解析

因为在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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值