From 85f48374603f5cfae20f8cac744f477ba5d45d63 Mon Sep 17 00:00:00 2001 From: mnovozhilov Date: Tue, 16 Dec 2025 13:50:58 +0500 Subject: [PATCH 1/3] =?UTF-8?q?Fix=20Bug=2066263=20=E2=80=94=20Add=20suppo?= =?UTF-8?q?rt=20for=20SDT=20row=20in=20tables?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../poi/xwpf/usermodel/XWPFParagraph.java | 47 +++++++++++++- .../apache/poi/xwpf/usermodel/XWPFTable.java | 63 +++++++++++++++---- 2 files changed, 95 insertions(+), 15 deletions(-) diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java index 0fb903ab441..dd26e8bca1f 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java @@ -138,10 +138,26 @@ private void buildRunsInOrderFromXml(XmlObject object) { if (o instanceof CTSdtBlock) { XWPFSDT cc = new XWPFSDT((CTSdtBlock) o, part); iruns.add(cc); + CTSdtContentBlock content = ((CTSdtBlock)o).getSdtContent(); + if (content != null) { + for (CTP ctp : content.getPList()) { + processCTRs(ctp.getRList()); + } + } } if (o instanceof CTSdtRun) { - XWPFSDT cc = new XWPFSDT((CTSdtRun) o, part); - iruns.add(cc); + if (o instanceof CTSdtRun) { + XWPFSDT cc = new XWPFSDT((CTSdtRun)o, part); + iruns.add(cc); + + CTSdtContentRun sdtContent = ((CTSdtRun)o).getSdtContent(); + if (sdtContent != null) + { + processCTRs(sdtContent.getRList()); + } + + processSdtRuns(); + } } if (o instanceof CTRunTrackChange) { final CTRunTrackChange parentRecord = (CTRunTrackChange) o; @@ -164,6 +180,33 @@ private void buildRunsInOrderFromXml(XmlObject object) { } } + private void processCTRs(List ctrs) { + if (ctrs == null) { + return; + } + for (CTR ctr : ctrs) { + if (ctr.getRPr() != null) { + runs.add(new XWPFRun(ctr, (IRunBody)this)); + } + } + } + + private void processSdtRuns() { + try (XmlCursor cursor = getCTP().newCursor()) { + cursor.selectPath("child::*"); + + while (cursor.toNextSelection()) { + XmlObject xmlObject = cursor.getObject(); + if (xmlObject instanceof CTSdtRun) { + CTSdtContentRun content = ((CTSdtRun)xmlObject).getSdtContent(); + if (content != null) { + processCTRs(content.getRList()); + } + } + } + } + } + @Internal public CTP getCTP() { return paragraph; diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java index 33fc2a8d635..ca03c9670ee 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java @@ -29,6 +29,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.apache.poi.ooxml.util.POIXMLUnits; import org.apache.poi.util.Internal; import org.apache.poi.util.Units; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBorder; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJcTable; @@ -168,24 +170,59 @@ public XWPFTable(CTTbl table, IBody part, boolean initRow) { createEmptyTable(table); } - for (CTRow row : table.getTrList()) { - StringBuilder rowText = new StringBuilder(); - XWPFTableRow tabRow = new XWPFTableRow(row, this); - tableRows.add(tabRow); - for (CTTc cell : row.getTcList()) { - for (CTP ctp : cell.getPList()) { - XWPFParagraph p = new XWPFParagraph(ctp, part); - if (rowText.length() > 0) { - rowText.append('\t'); + try (XmlCursor cursor = table.newCursor()) { + cursor.selectPath("./*"); + while (cursor.toNextSelection()) { + XmlObject xmlObject = cursor.getObject(); + if (xmlObject instanceof CTRow) { + processCTRow((CTRow)xmlObject); + } + else if (xmlObject instanceof CTSdtRow) { + List rows = new ArrayList<>(); + collectCTRowsInnerSdtRow((CTSdtRow)xmlObject, rows); + for (CTRow row : rows) + { + processCTRow(row); } - rowText.append(p.getText()); } } - if (rowText.length() > 0) { - this.text.append(rowText); - this.text.append('\n'); + } + } + + private void processCTRow(CTRow row) { + StringBuilder rowText = new StringBuilder(); + XWPFTableRow tableRow = new XWPFTableRow(row, this); + tableRows.add(tableRow); + for (CTTc cell : row.getTcList()) { + for (CTP ctp : cell.getPList()) { + XWPFParagraph p = new XWPFParagraph(ctp, part); + if (rowText.length() > 0) { + rowText.append('\t'); + } + rowText.append(p.getText()); } } + if (rowText.length() > 0) { + this.text.append(rowText); + this.text.append('\n'); + } + } + + private void collectCTRowsInnerSdtRow(CTSdtRow sdtRow, List rows) { + CTSdtContentRow sdtContent = sdtRow.getSdtContent(); + if (sdtContent == null) { + return; + } + + List rowsInnerSdtContent = sdtContent.getTrList(); + if (!rowsInnerSdtContent.isEmpty()) { + rows.addAll(rowsInnerSdtContent); + return; + } + + for (CTSdtRow innerSdt : sdtContent.getSdtList()) { + collectCTRowsInnerSdtRow(innerSdt, rows); + } } private void createEmptyTable(CTTbl table) { From e0f3da1f11cf4947c024ef5b023bbd4f0dcd90ff Mon Sep 17 00:00:00 2001 From: mnovozhilov Date: Tue, 16 Dec 2025 15:34:40 +0500 Subject: [PATCH 2/3] remove repeated if --- .../main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java index dd26e8bca1f..831f86e5321 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java @@ -146,7 +146,6 @@ private void buildRunsInOrderFromXml(XmlObject object) { } } if (o instanceof CTSdtRun) { - if (o instanceof CTSdtRun) { XWPFSDT cc = new XWPFSDT((CTSdtRun)o, part); iruns.add(cc); @@ -157,7 +156,6 @@ private void buildRunsInOrderFromXml(XmlObject object) { } processSdtRuns(); - } } if (o instanceof CTRunTrackChange) { final CTRunTrackChange parentRecord = (CTRunTrackChange) o; From 5c75ebe886eefb6cee7e553f868f4c726545f055 Mon Sep 17 00:00:00 2001 From: mnovozhilov Date: Tue, 16 Dec 2025 16:25:48 +0500 Subject: [PATCH 3/3] add missing imports --- .../src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java index ca03c9670ee..4f0e4d1a29c 100644 --- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java +++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTable.java @@ -36,6 +36,8 @@ Licensed to the Apache Software Foundation (ASF) under one or more import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTJcTable; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtContentRow; +import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtRow; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTString; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTblBorders;