This is an automated email from the ASF dual-hosted git repository.

tballison pushed a commit to branch TIKA-4790-default-to-sax-ooxml
in repository https://gitbox.apache.org/repos/asf/tika.git

commit 36a448f800a0f794b2acbe642fb5b01f79a3ce70
Author: tallison <[email protected]>
AuthorDate: Wed Jul 15 08:49:31 2026 -0400

    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 +++++------------
 5 files changed, 47 insertions(+), 51 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);

Reply via email to