nodejs实现一个word文档解析器思路详解

2020-06-17 06:55:36易采站长站整理

 

那么到底怎么样才是一个 Paragraph 呢,其实很简单,仔细观察word文档,见到下图中的小箭头了么,每个小箭头前面的内容就是一个段落,那么下图中一共有16个 Paragraph ,当然有些段落是空的,没有任何内容

 

我们再来研究xml的结构,收起展开的xml,如下图,发现 <w:p></w:p> 这么个标签就是表示的一个段落,中间还有些 <w:p>

藏在表格内,这么一看表格前面3个段落,后面3个段落,和上图是对应的

 

因此, 我们就可以提取出每个段落的文本并返回一个数组,每一项就是一个段落的内容 ,这样就能够完整的解析出整个word的内容,关键在于如何提取每个 <w:p> 的内容,我们继续展开一个 <w:p> 进行观察,如下图,发现内容虽多,其实文本都保存在 <w:t> 中间,因此思路就清晰了, 首先用正则表达式提取出所有<w:p>的内容,再针对每个<w:p>的内容,进行进一步正则提取,提取出其里面所有<w:t>的内容,并拼接在一起构成一个段落的总内容

 

具体代码

下面是具体的提取代码


//参数是word文件名,第二个参数是回调表示解析完成
var parser = function parseWordDocument(absoluteWordPath,callback){
//返回内容的数组
var resultList = [];
//如果文件存在
fs.exists(absoluteWordPath, function(exists){
if(exists){
//解压缩
const zip = new admZip(absoluteWordPath);
//将document.xml(解压缩后得到的文件)读取为text内容
var contentXml = zip.readAsText("word/document.xml");
//正则匹配出对应的<w:p>里面的内容,方法是先匹配<w:p>,再匹配里面的<w:t>,将匹配到的加起来即可
//注意?表示非贪婪模式(尽可能少匹配字符),否则只能匹配到一个<w:p></w:p>
var matchedWP = contentXml.match(/<w:p.*?>.*?</w:p>/gi);
//继续匹配每个<w:p></w:p>里面的<w:t>,这里必须判断matchedWP存在否则报错
if(matchedWP){
matchedWP.forEach(function(wpItem){
//注意这里<w:t>的匹配,有可能是<w:t xml:space="preserve">这种格式,需要特殊处理
var matchedWT = wpItem.match(/(<w:t>.*?</w:t>)|(<w:ts.[^>]*?>.*?</w:t>)/gi);
var textContent = '';
if(matchedWT){
matchedWT.forEach(function(wtItem){
//如果不是<w:t xml:space="preserve">格式
if(wtItem.indexOf('xml:space')===-1){
textContent+=wtItem.slice(5,-6);