This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch branch_3x
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/branch_3x by this push:
new 3cecc5b22e TIKA-4790 -- make sax parsing default in 3.x (#2957)
3cecc5b22e is described below
commit 3cecc5b22ee966b285a68f94974b648ecef3bcb7
Author: Tim Allison <[email protected]>
AuthorDate: Wed Jul 15 16:54:53 2026 -0400
TIKA-4790 -- make sax parsing default in 3.x (#2957)
* TIKA-4790 -- make sax parsing default in 3.x
---
CHANGES.txt | 10 +++----
.../tika/parser/microsoft/OfficeParserConfig.java | 20 +++++++-------
.../parser/microsoft/ooxml/OOXMLParserTest.java | 31 ++++++++++++++++------
.../parser/microsoft/ooxml/SXSLFExtractorTest.java | 13 +++------
.../parser/microsoft/ooxml/SXWPFExtractorTest.java | 24 +++++------------
.../standard/RecursiveMetadataResourceTest.java | 4 ++-
6 files changed, 50 insertions(+), 52 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 106fe2a36c..626793f7e4 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,11 +4,11 @@ Release 3.3.2 - (unreleased)
/status endpoints are selected; the server refuses to start otherwise.
Previously
listing the endpoint was treated as sufficient consent (TIKA-4760).
- * Port the 4.x SAX-based OOXML parsers to 3.x. The docx/pptx/xlsx/vsdx SAX
parsers
- gain field-code hyperlink extraction, inlined footnotes/endnotes/comments,
- balanced-XHTML recovery on error, and XMLBeans-free xlsx/xlsb reading. The
SAX
- docx/pptx parsers stay opt-in via useSAXDocxExtractor/useSAXPptxExtractor,
so DOM
- remains the default (TIKA-4692, TIKA-4708).
+ * Port the 4.x SAX-based OOXML parsers to 3.x and make SAX default.
+ The docx/pptx/xlsx/vsdx SAX parsers gain field-code hyperlink extraction,
+ inlined footnotes/endnotes/comments, balanced-XHTML recovery on error, and
XMLBeans-free
+ xlsx/xlsb reading. The DOM docx/pptx parsers can still be configured via
+ useSAXDocxExtractor/useSAXPptxExtractor (TIKA-4692, TIKA-4708, TIKA-4790).
Release 3.3.1 - 5/20/2026
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParserConfig.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParserConfig.java
index feeaae1b51..ffa7dd3a02 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParserConfig.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OfficeParserConfig.java
@@ -32,8 +32,8 @@ public class OfficeParserConfig implements Serializable {
private boolean includeSlideMasterContent = true;
private boolean concatenatePhoneticRuns = true;
- private boolean useSAXDocxExtractor = false;
- private boolean useSAXPptxExtractor = false;
+ private boolean useSAXDocxExtractor = true;
+ private boolean useSAXPptxExtractor = true;
private boolean preferAlternateContentChoice = true;
@@ -142,11 +142,11 @@ public class OfficeParserConfig implements Serializable {
}
/**
- * Use the experimental SAX-based streaming DOCX parser?
- * If set to <code>false</code>, the classic parser will be used; if
<code>true</code>,
- * the new experimental parser will be used.
+ * Use the SAX-based streaming DOCX parser?
+ * If set to <code>true</code>, the SAX-based streaming parser will be
used;
+ * if <code>false</code>, the classic DOM parser will be used.
* <p/>
- * Default: <code>false</code> (classic DOM parser)
+ * Default: <code>true</code> (SAX streaming parser)
*
* @param useSAXDocxExtractor
*/
@@ -159,11 +159,11 @@ public class OfficeParserConfig implements Serializable {
}
/**
- * Use the experimental SAX-based streaming DOCX parser?
- * If set to <code>false</code>, the classic parser will be used; if
<code>true</code>,
- * the new experimental parser will be used.
+ * Use the SAX-based streaming PPTX parser?
+ * If set to <code>true</code>, the SAX-based streaming parser will be
used;
+ * if <code>false</code>, the classic DOM parser will be used.
* <p/>
- * Default: <code>false</code> (classic DOM parser)
+ * Default: <code>true</code> (SAX streaming parser)
*
* @param useSAXPptxExtractor
*/
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParserTest.java
index b5504dc6ed..8185a41985 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/OOXMLParserTest.java
@@ -374,13 +374,26 @@ public class OOXMLParserTest extends
MultiThreadedTikaTest {
assertContains("<div class=\"endnote\">", xmlResult.xml);
}
+ /**
+ * The SAX extractors are the default as of Tika 3.x. A handful of tests
below
+ * assert on markup that only the classic DOM extractors produce, so they
force DOM.
+ */
+ private static ParseContext domParseContext() {
+ OfficeParserConfig config = new OfficeParserConfig();
+ config.setUseSAXDocxExtractor(false);
+ config.setUseSAXPptxExtractor(false);
+ ParseContext context = new ParseContext();
+ context.set(OfficeParserConfig.class, config);
+ return context;
+ }
+
/**
* Test that the word converter is able to generate the
* correct HTML for the document
*/
@Test
public void testWordHTML() throws Exception {
- XMLResult result = getXML("testWORD.docx");
+ XMLResult result = getXML("testWORD.docx", domParseContext());
String xml = result.xml;
Metadata metadata = result.metadata;
assertEquals("application/vnd.openxmlformats-officedocument.wordprocessingml.document",
@@ -409,7 +422,7 @@ public class OOXMLParserTest extends MultiThreadedTikaTest {
// Paragraphs with other styles
assertTrue(xml.contains("<p class=\"signature\">This one"));
- result = getXML("testWORD_3imgs.docx");
+ result = getXML("testWORD_3imgs.docx", domParseContext());
xml = result.xml;
// Images 2-4 (there is no 1!)
@@ -425,7 +438,7 @@ public class OOXMLParserTest extends MultiThreadedTikaTest {
// TIKA-692: test document containing multiple
// character runs within a bold tag:
- xml = getXML("testWORD_bold_character_runs.docx").xml;
+ xml = getXML("testWORD_bold_character_runs.docx",
domParseContext()).xml;
// Make sure bold text arrived as single
// contiguous string even though Word parser
@@ -434,7 +447,7 @@ public class OOXMLParserTest extends MultiThreadedTikaTest {
// TIKA-692: test document containing multiple
// character runs within a bold tag:
- xml = getXML("testWORD_bold_character_runs2.docx").xml;
+ xml = getXML("testWORD_bold_character_runs2.docx",
domParseContext()).xml;
// Make sure bold text arrived as single
// contiguous string even though Word parser
@@ -537,14 +550,14 @@ public class OOXMLParserTest extends
MultiThreadedTikaTest {
@Test
public void testTextDecorationNested() throws Exception {
- String xml = getXML("testWORD_various.docx").xml;
+ String xml = getXML("testWORD_various.docx", domParseContext()).xml;
assertContains("<i>ita<s>li</s>c</i>", xml);
assertContains("<i>ita<s>l<u>i</u></s>c</i>", xml);
assertContains("<i><u>unde<s>r</s>line</u></i>", xml);
//confirm that spaces aren't added for </s> and </u>
- String txt = getText("testWORD_various.docx");
+ String txt = getText("testWORD_various.docx", new Metadata(),
domParseContext());
assertContainsCount("italic", txt, 3);
assertNotContained("ita ", txt);
@@ -708,8 +721,10 @@ public class OOXMLParserTest extends MultiThreadedTikaTest
{
@Test
public void testSkipHeaderFooter() throws Exception {
//now test turning off header/footer
+ //header/footer suppression for pptx is only implemented in the DOM
extractor
OfficeParserConfig config = new OfficeParserConfig();
config.setIncludeHeadersAndFooters(false);
+ config.setUseSAXPptxExtractor(false);
ParseContext context = new ParseContext();
context.set(OfficeParserConfig.class, config);
String xml = getXML("testPPT_various.pptx", context).xml;
@@ -904,7 +919,7 @@ public class OOXMLParserTest extends MultiThreadedTikaTest {
// TIKA-997:
@Test
public void testEmbeddedZipInPPTX() throws Exception {
- String xml = getXML("test_embedded_zip.pptx").xml;
+ String xml = getXML("test_embedded_zip.pptx", domParseContext()).xml;
int h = xml.indexOf("<div class=\"embedded\" id=\"slide1_rId3\" />");
int i = xml.indexOf("Send me a note");
int j = xml.indexOf("<div class=\"embedded\" id=\"slide2_rId4\" />");
@@ -977,7 +992,7 @@ public class OOXMLParserTest extends MultiThreadedTikaTest {
// TIKA-1032:
@Test
public void testEmbeddedPPTXTwoSlides() throws Exception {
- String xml = getXML("testPPT_embedded_two_slides.pptx").xml;
+ String xml = getXML("testPPT_embedded_two_slides.pptx",
domParseContext()).xml;
assertContains("<div class=\"embedded\" id=\"slide1_rId7\" />", xml);
assertContains("<div class=\"embedded\" id=\"slide2_rId7\" />", xml);
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXSLFExtractorTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXSLFExtractorTest.java
index 48de3013ee..534413c894 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXSLFExtractorTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXSLFExtractorTest.java
@@ -51,10 +51,9 @@ public class SXSLFExtractorTest extends TikaTest {
@BeforeEach
public void setUp() {
+ //SAX is the default OOXML extractor as of Tika 3.x; an unconfigured
+ //context exercises (and verifies) that default.
parseContext = new ParseContext();
- officeParserConfig.setUseSAXPptxExtractor(true);
- parseContext.set(OfficeParserConfig.class, officeParserConfig);
-
}
@Test
@@ -345,7 +344,6 @@ public class SXSLFExtractorTest extends TikaTest {
//the actual slide's xml, not just in the master slide.
OfficeParserConfig config = new OfficeParserConfig();
config.setIncludeSlideMasterContent(false);
- config.setUseSAXPptxExtractor(true);
ParseContext context = new ParseContext();
context.set(OfficeParserConfig.class, config);
String xml = getXML("testPPT_masterFooter.pptx", context).xml;
@@ -364,7 +362,6 @@ public class SXSLFExtractorTest extends TikaTest {
//now test turning off master content
OfficeParserConfig config = new OfficeParserConfig();
config.setIncludeSlideMasterContent(false);
- config.setUseSAXPptxExtractor(true);
ParseContext context = new ParseContext();
context.set(OfficeParserConfig.class, config);
@@ -379,7 +376,6 @@ public class SXSLFExtractorTest extends TikaTest {
//now test turning off master content
OfficeParserConfig config = new OfficeParserConfig();
config.setIncludeSlideMasterContent(false);
- config.setUseSAXPptxExtractor(true);
ParseContext context = new ParseContext();
context.set(OfficeParserConfig.class, config);
@@ -397,9 +393,7 @@ public class SXSLFExtractorTest extends TikaTest {
ParseContext context = new ParseContext();
context.set(Locale.class, Locale.US);
- OfficeParserConfig officeParserConfig = new OfficeParserConfig();
- officeParserConfig.setUseSAXPptxExtractor(true);
- context.set(OfficeParserConfig.class, officeParserConfig);
+ context.set(OfficeParserConfig.class, new OfficeParserConfig());
getXML("testPPT_custom_props.pptx", metadata, parseContext);
assertEquals("application/vnd.openxmlformats-officedocument.presentationml.presentation",
@@ -529,7 +523,6 @@ public class SXSLFExtractorTest extends TikaTest {
ParseContext context = new ParseContext();
OfficeParserConfig officeParserConfig = new OfficeParserConfig();
officeParserConfig.setExtractMacros(true);
- officeParserConfig.setUseSAXPptxExtractor(true);
context.set(OfficeParserConfig.class, officeParserConfig);
Metadata minExpected = new Metadata();
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXWPFExtractorTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXWPFExtractorTest.java
index 65a73faf3a..e5a17032d9 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXWPFExtractorTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/test/java/org/apache/tika/parser/microsoft/ooxml/SXWPFExtractorTest.java
@@ -54,12 +54,9 @@ public class SXWPFExtractorTest extends TikaTest {
@BeforeEach
public void setUp() {
+ //SAX is the default OOXML extractor as of Tika 3.x; an unconfigured
+ //context exercises (and verifies) that default.
parseContext = new ParseContext();
- OfficeParserConfig officeParserConfig = new OfficeParserConfig();
- officeParserConfig.setUseSAXDocxExtractor(true);
- officeParserConfig.setUseSAXPptxExtractor(true);
- parseContext.set(OfficeParserConfig.class, officeParserConfig);
-
}
@Test
@@ -479,7 +476,6 @@ public class SXWPFExtractorTest extends TikaTest {
ParseContext pc = new ParseContext();
OfficeParserConfig officeParserConfig = new OfficeParserConfig();
officeParserConfig.setIncludeDeletedContent(true);
- officeParserConfig.setUseSAXDocxExtractor(true);
officeParserConfig.setIncludeMoveFromContent(true);
pc.set(OfficeParserConfig.class, officeParserConfig);
@@ -505,7 +501,6 @@ public class SXWPFExtractorTest extends TikaTest {
ParseContext pc = new ParseContext();
OfficeParserConfig officeParserConfig = new OfficeParserConfig();
officeParserConfig.setIncludeShapeBasedContent(false);
- officeParserConfig.setUseSAXDocxExtractor(true);
pc.set(OfficeParserConfig.class, officeParserConfig);
String xml = getXML("testWORD_text_box.docx", pc).xml;
assertContains("This text is directly in the body of the document.",
xml);
@@ -572,11 +567,8 @@ public class SXWPFExtractorTest extends TikaTest {
Metadata m = new Metadata();
PasswordProvider passwordProvider = metadata -> "tika";
- OfficeParserConfig opc = new OfficeParserConfig();
- opc.setUseSAXDocxExtractor(true);
ParseContext passwordContext = new ParseContext();
passwordContext.set(org.apache.tika.parser.PasswordProvider.class,
passwordProvider);
- passwordContext.set(OfficeParserConfig.class, opc);
for (Map.Entry<String, String> e : tests.entrySet()) {
assertContains(e.getValue(), getXML(e.getKey(),
passwordContext).xml);
}
@@ -725,7 +717,6 @@ public class SXWPFExtractorTest extends TikaTest {
ParseContext context = new ParseContext();
OfficeParserConfig officeParserConfig = new OfficeParserConfig();
officeParserConfig.setExtractMacros(true);
- officeParserConfig.setUseSAXDocxExtractor(true);
context.set(OfficeParserConfig.class, officeParserConfig);
metadataList = getRecursiveMetadata("testWORD_macros.docm", context);
@@ -802,7 +793,6 @@ public class SXWPFExtractorTest extends TikaTest {
ParseContext parseContext = new ParseContext();
OfficeParserConfig officeParserConfig = new OfficeParserConfig();
officeParserConfig.setIncludeHeadersAndFooters(false);
- officeParserConfig.setUseSAXDocxExtractor(true);
parseContext.set(OfficeParserConfig.class, officeParserConfig);
String xml = getXML("testWORD_various.docx", parseContext).xml;
assertNotContained("This is the header text.", xml);
@@ -811,15 +801,13 @@ public class SXWPFExtractorTest extends TikaTest {
@Test
public void testDOCXPhoneticStrings() throws Exception {
- OfficeParserConfig config = new OfficeParserConfig();
- config.setUseSAXDocxExtractor(true);
- ParseContext parseContext = new ParseContext();
- parseContext.set(OfficeParserConfig.class, config);
assertContains("\u6771\u4EAC (\u3068\u3046\u304D\u3087\u3046)",
- getXML("testWORD_phonetic.docx", parseContext).xml);
-
+ getXML("testWORD_phonetic.docx").xml);
+ OfficeParserConfig config = new OfficeParserConfig();
config.setConcatenatePhoneticRuns(false);
+ ParseContext parseContext = new ParseContext();
+ parseContext.set(OfficeParserConfig.class, config);
String xml = getXML("testWORD_phonetic.docx", parseContext).xml;
assertContains("\u6771\u4EAC", xml);
assertNotContained("\u3068", xml);
diff --git
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
index 103187e50d..a601dfc856 100644
---
a/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
+++
b/tika-server/tika-server-standard/src/test/java/org/apache/tika/server/standard/RecursiveMetadataResourceTest.java
@@ -119,10 +119,12 @@ public class RecursiveMetadataResourceTest extends
CXFTestBase {
.get(0)
.getValues(TikaCoreProperties.TIKA_PARSED_BY);
//make sure the CompressorParser doesn't show up here
- assertEquals(3, parsedBy.length);
+ assertEquals(4, parsedBy.length);
assertEquals("org.apache.tika.parser.CompositeParser", parsedBy[0]);
assertEquals("org.apache.tika.parser.DefaultParser", parsedBy[1]);
assertEquals("org.apache.tika.parser.microsoft.ooxml.OOXMLParser",
parsedBy[2]);
+
assertEquals("org.apache.tika.parser.microsoft.ooxml.xwpf.XWPFEventBasedWordExtractor",
+ parsedBy[3]);
//test that the rest is as it should be
assertEquals(12, metadataList.size());