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

Modify Apache Tika parsing of ODF and old (1997-2003) MS Word docs?

我正在开发一个应用程序,它将对不同格式的大文件进行 Lucene 索引(将它们分成多个 org.apache.lucene.document.Documents)。至少在初始方法中,每个 "Lucene Document" 包含一个 "paragraph".

作为一般规则,Apache Tika 似乎是这方面的天赐之物:您只需向它扔一个文档,它就会吸出所有格式的文本。

但我想详细了解它如何处理更棘手的方面,在我第一次看它如何处理脚注和尾注的过程中,我发现在 .docx 文件中它会给出这个"line",对于有 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 给你多个 "lines":

|Tecum optime|
|, deinde etiam|
| cum mediocri amico|
|.|
...

|??|
| ? Sed quoniam et advesperascit et mihi ad villam revertendum est, nunc quidem 
hactenus; Quod si ita sit, cur opera philosophiae sit danda nescio. |
|??|
| ? Si quae forte-possumus. Immo videri fortasse. |
|??|
| ? 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. |

... 它不仅将原始的 "paragraph" 分成几行,在每个脚注引用处中断,而且还将所有脚注推到处理的末尾。

通过 .docx 文件处理,您可以提取脚注并轻松地将它们 link 到它们所属的句子中。 .doc 处理的方式当然对我的索引目的毫无帮助。事实上,我真的看不出有什么方法可以将最初的 4 "lines" 识别为真正属于同一个 parapraph。

也许可以预料,Tika 对 .doc 等过时格式的处理并不是那么出色。我现在打算看看这里涉及的实际源代码,假设我可以在 Gradle 下载的很多很多源 jar 中找到它,而不是调整代码是否有更多 "conventional" 修改 Tika 对给定格式的解析的方法?我做了一些搜索,但一无所获。

当然,另一种方法可能是将 .doc 文件(和 .odt 文件,见下文)转换为 .docx "on the fly" 以获得更高质量的解析。

PS 解析 LibreOffice .odt 文件(开放文档格式,ODF),一种非过时的格式,同样有问题。 特别是,footnote/endnote-containing 行同样被分成多行。

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

首先,Apache 人员似乎并不真的想让你 fiddle 使用 Tika classes。

在尝试调整 MS Word 97-2003 格式(又名 .doc)的处理时,这里涉及的主要 class 是 HWPFDocument("Horrible Word Processing Format")。 Apache POI 项目的一部分,与 Tika 捆绑在一起。

这个 class 通常会从 .doc 文件中获取 InputStream 并且似乎将文件的不同元素分开而无益,因此脚注等似乎是分开存储的从文本中。 HWPFDocumentfinal,这只是问题的开始:这里的许多文件依赖于包中或 sub-packages 中的其他 classes,其中许多是 final 或不是 public(或 protected)。我得出的结论是,我基本上必须克隆整个 org.apache.poi.hwpf 包,对其进行修改并再次打包。我不会被打扰。

.odt (ODF) 文件类型 最终对我来说真的更重要:non-obsolete 和 non-Micro$oft。这里关键的 class 结果是 org.apache.tika.parser.odf.OpenDocumentContentParser。这里的问题是它包含一个 private final 内部 class (即他们 真的 不想让你子 class 它甚至使用它的实例出于某种原因!)称为 OpenDocumentElementMappingContentHandler,它最终实现了 org.xml.sax.ContentHandler。这里涉及数百个(好吧,很多)ContentHandler-实施 classes,其中许多 "decorators"。但最终你需要做的是复制这个 class OpenDocumentContentParser 的整个代码,然后把里面的 class 弄乱。我这样做是为了在 startElementendElement 处,根据参数 qName 的值,它切换到或退出可能值 "parse mode" [=64] =] "NOTE_CITATION" or "NODE BODY" ...并且在此模式设置的基础上可以取消调用

super.endElement(namespaceURI, localName, qName);

endElement 中。正是这个 super 调用似乎触发了一个字符串的结尾和下一个字符串的开头。要在输出文本中放置脚注编号或正文 beginning/ending 的文本指示,您可以创建 String injectedText 然后转到

super.characters( injectedText.toCharArray(), 0, injectedText.length());

如果合适的话。这是因为实际上 的最终 ContentHandlerToTextContentHandler 的一个实例, characters( ... )其方法只是将 chars 序列添加到 java.io.Writer 实例(是的,我也从未听说过:非常简单)。

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