Java 修改ODF和旧(1997-2003)MS Word文档的Apache Tika解析?

Java 修改ODF和旧(1997-2003)MS Word文档的Apache Tika解析?,java,parsing,ms-word,lucene,apache-tika,Java,Parsing,Ms Word,Lucene,Apache Tika,我正在开发一个应用程序,可以对不同格式的大文件(将它们拆分为多个org.apache.Lucene.document.Documents)进行Lucene索引。至少在最初的方法中,每个“Lucene文件”由一个“段落”组成 一般来说,ApacheTika似乎是天赐良机:您只需向它抛出一个文档,它似乎会吸出所有文本,无论其格式如何 但我想获得一些关于它如何处理更复杂方面的详细知识,在我第一次看它如何处理脚注和尾注的过程中,我发现,在.docx文件中,它会给出以下“行”,对于有3个脚注的行: |Te

我正在开发一个应用程序,可以对不同格式的大文件(将它们拆分为多个org.apache.Lucene.document.Documents)进行Lucene索引。至少在最初的方法中,每个“Lucene文件”由一个“段落”组成

一般来说,ApacheTika似乎是天赐良机:您只需向它抛出一个文档,它似乎会吸出所有文本,无论其格式如何

但我想获得一些关于它如何处理更复杂方面的详细知识,在我第一次看它如何处理脚注和尾注的过程中,我发现,在.docx文件中,它会给出以下“行”,对于有3个脚注的行:

|Tecum optime[footnoteRef:2], deinde etiam[footnoteRef:3] cum mediocri amico[footnoteRef:4]. 
[2: Sed quoniam et advesperascit et mihi ad villam revertendum est, nunc quidem hactenus; 
Quod si ita sit, cur opera philosophiae sit danda nescio.] [3: Si quae forte-possumus. 
Immo videri fortasse.] [4: Huius ego nunc auctoritatem [sequens idem faciam]. Confecta 
res esset. Primum Theophrasti, Strato, physicum se voluit; Ut proverbia non nulla veriora 
sint quam vestra dogmata.]|
(请注意,“|”字符由我的代码添加以清晰显示)

。。。对于相同的.doc格式文件,Tika为您提供了多个“行”:

。。。它不仅将原始“段落”拆分为几行,在每个脚注引用处断开,而且还将所有脚注推到处理的末尾

通过.docx文件处理,您可以提取脚注,并轻松地将它们链接到它们所属的句子。对于我的索引目的来说,.doc处理的方式当然是毫无帮助的。事实上,我真的看不到一种方法,那就是最初的4条“线”可以被识别为真正属于同一个参数

也许可以预料,Tika对.doc等过时格式的处理并没有那么出色。我现在打算看看这里涉及的实际源代码,假设我可以在Gradle下载的许多源jar中找到它,但是除了调整代码,还有没有更“传统”的方法来修改Tika对给定格式的解析?我找了些东西,但什么也没找到

当然,另一种方法可能是将.doc文件(和.odt文件,见下文)转换为.docx“动态”,以实现更高质量的解析


PS解析LibreOffice.odt文件(开放文档格式,ODF),一种非过时的格式,同样存在问题。特别是,包含行的脚注/尾注同样被拆分为多行。

几天后,我的发现供感兴趣的人参考

首先,Apache人员似乎并不真正想让您摆弄Tika类

当尝试调整MS Word 97-2003格式(aka.doc)的处理时,这里涉及的主要类是
HWPFDocument
(“可怕的文字处理格式”)。ApachePOI项目的一部分,它与Tika捆绑在一起

该类通常从.doc文件中获取
InputStream
,并且似乎将文件的不同元素分割成了毫无帮助的部分,因此脚注等似乎与文本分开存储
HWPFDocument
final
,这只是问题的开始:这里的许多文件依赖于包或子包中的其他类,其中许多是
final
或不是
public
(或
受保护的
)。我得出的结论是,我基本上必须克隆整个
org.apache.poi.hwpf
包,对其进行修改并重新打包。我不会被打扰的

最终,.odt(ODF)文件类型对我来说更加重要:非过时和非微型$oft。这里的关键类是
org.apache.tika.parser.odf.OpenDocumentContentParser
。这里的问题是,它包含一个名为
OpenDocumentElementMappingContentHandler
private final
内部类(也就是说,他们真的不希望您对它进行子类化,甚至出于某种原因不希望您使用它的实例!),该类最终实现了
org.xml.sax.ContentHandler
。这里涉及数百个(好吧,很多)实现类的
ContentHandler
,其中很多是“decorator”。但最终您需要做的是复制这个类的整个代码
OpenDocumentContentParser
,然后处理内部类。我这样做是为了在
startElement
endElement
上,根据参数
qName
的值,它切换到或退出可能值“未定义”、“注释引用”或“节点体”的“解析模式”。。。并在此模式设置的基础上取消呼叫

super.endElement(namespaceURI, localName, qName);
endElement
中。正是这个
super
调用触发了一个字符串的结束和下一个字符串的开始。要在输出文本中显示脚注编号或正文的开头/结尾,可以创建
字符串injectedText
,然后转到

super.characters( injectedText.toCharArray(), 0, injectedText.length());
在适当的情况下。这是因为最终的
ContentHandler
实际上做了一些事情
ToTextContentHandler
的一个实例,
字符(…)
方法只是将一系列
字符添加到
java.io.Writer
实例中(是的,我也从未听说过:非常简单)


希望这有帮助。现在,我已经将我的这个新类提交给Tika项目,看看他们是否喜欢它的外观。

使用.doc解析器可以省去你在罐子里挖东西的麻烦!这看起来是个很好的建议。但实际上,在我的Tika API(1.14)org.apache.Tika.parser.microsoft.WordExtractor中,它只是从对象扩展而来。()我将查看该类的代码……您是否有可能在中引发错误,并将更改上载到ODF解析器?然后我们可以把这些改进带到蒂卡!哇,很荣幸被邀请。。。我会这样做的。现在(.odt footnotes/endnotes)运行得很好:就像.docx处理一样,只是我发现出于某种原因,Tika.docx解析器将.docx中的脚注“1”报告为脚注“2”,脚注“2”报告为“3”,等等:我的.odt解析器正确地得到了这些数字。将引发两个错误。。。
super.characters( injectedText.toCharArray(), 0, injectedText.length());