Author: fanningpj
Date: Thu Jan 21 21:04:24 2021
New Revision: 1885770

URL: http://svn.apache.org/viewvc?rev=1885770&view=rev
Log:
[bug-65096] XLSX Streaming XML not correctly reading multiple inline Strings

Added:
    
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
   (with props)
    poi/trunk/test-data/spreadsheet/InlineString.xlsx   (with props)
Modified:
    
poi/trunk/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java

Modified: 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java?rev=1885770&r1=1885769&r2=1885770&view=diff
==============================================================================
--- 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
 (original)
+++ 
poi/trunk/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFSheetXMLHandler.java
 Thu Jan 21 21:04:24 2021
@@ -204,7 +204,9 @@ public class XSSFSheetXMLHandler extends
        if (isTextTag(localName)) {
            vIsOpen = true;
            // Clear contents cache
-           value.setLength(0);
+           if (!isIsOpen) {
+               value.setLength(0);
+           }
        } else if ("is".equals(localName)) {
           // Inline string outer tag
           isIsOpen = true;
@@ -307,86 +309,19 @@ public class XSSFSheetXMLHandler extends
            return;
        }
 
-       String thisStr = null;
-
        // v => contents of a cell
        if (isTextTag(localName)) {
            vIsOpen = false;
 
-           // Process the value contents as required, now we have it all
-           switch (nextDataType) {
-               case BOOLEAN:
-                   char first = value.charAt(0);
-                   thisStr = first == '0' ? "FALSE" : "TRUE";
-                   break;
-
-               case ERROR:
-                   thisStr = "ERROR:" + value;
-                   break;
-
-               case FORMULA:
-                   if(formulasNotResults) {
-                      thisStr = formula.toString();
-                   } else {
-                      String fv = value.toString();
-
-                      if (this.formatString != null) {
-                         try {
-                            // Try to use the value as a formattable number
-                            double d = Double.parseDouble(fv);
-                            thisStr = formatter.formatRawCellContents(d, 
this.formatIndex, this.formatString);
-                         } catch(NumberFormatException e) {
-                            // Formula is a String result not a Numeric one
-                            thisStr = fv;
-                         }
-                      } else {
-                         // No formatting applied, just do raw value in all 
cases
-                         thisStr = fv;
-                      }
-                   }
-                   break;
-
-               case INLINE_STRING:
-                   // TODO: Can these ever have formatting on them?
-                   XSSFRichTextString rtsi = new 
XSSFRichTextString(value.toString());
-                   thisStr = rtsi.toString();
-                   break;
-
-               case SST_STRING:
-                   String sstIndex = value.toString();
-                   try {
-                       int idx = Integer.parseInt(sstIndex);
-                       RichTextString rtss = sharedStringsTable.getItemAt(idx);
-                       thisStr = rtss.toString();
-                   }
-                   catch (NumberFormatException ex) {
-                       LOG.log(POILogger.ERROR, "Failed to parse SST index '", 
sstIndex, ex);
-                   }
-                   break;
-
-               case NUMBER:
-                   String n = value.toString();
-                   if (this.formatString != null && n.length() > 0)
-                       thisStr = 
formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, 
this.formatString);
-                   else
-                       thisStr = n;
-                   break;
-
-               default:
-                   thisStr = "(TODO: Unexpected type: " + nextDataType + ")";
-                   break;
+           if (!isIsOpen) {
+               outputCell();
            }
-
-           // Do we have a comment for this cell?
-           checkForEmptyCellComments(EmptyCellCommentsCheckType.CELL);
-           XSSFComment comment = comments != null ? 
comments.findCellComment(new CellAddress(cellRef)) : null;
-
-           // Output
-           output.cell(cellRef, thisStr, comment);
        } else if ("f".equals(localName)) {
           fIsOpen = false;
        } else if ("is".equals(localName)) {
           isIsOpen = false;
+           outputCell();
+           value.setLength(0);
        } else if ("row".equals(localName)) {
           // Handle any "missing" cells which had comments attached
           checkForEmptyCellComments(EmptyCellCommentsCheckType.END_OF_ROW);
@@ -433,6 +368,81 @@ public class XSSFSheetXMLHandler extends
        }
    }
 
+   private void outputCell() {
+       String thisStr = null;
+
+       // Process the value contents as required, now we have it all
+       switch (nextDataType) {
+           case BOOLEAN:
+               char first = value.charAt(0);
+               thisStr = first == '0' ? "FALSE" : "TRUE";
+               break;
+
+           case ERROR:
+               thisStr = "ERROR:" + value;
+               break;
+
+           case FORMULA:
+               if(formulasNotResults) {
+                   thisStr = formula.toString();
+               } else {
+                   String fv = value.toString();
+
+                   if (this.formatString != null) {
+                       try {
+                           // Try to use the value as a formattable number
+                           double d = Double.parseDouble(fv);
+                           thisStr = formatter.formatRawCellContents(d, 
this.formatIndex, this.formatString);
+                       } catch(NumberFormatException e) {
+                           // Formula is a String result not a Numeric one
+                           thisStr = fv;
+                       }
+                   } else {
+                       // No formatting applied, just do raw value in all cases
+                       thisStr = fv;
+                   }
+               }
+               break;
+
+           case INLINE_STRING:
+               // TODO: Can these ever have formatting on them?
+               XSSFRichTextString rtsi = new 
XSSFRichTextString(value.toString());
+               thisStr = rtsi.toString();
+               break;
+
+           case SST_STRING:
+               String sstIndex = value.toString();
+               try {
+                   int idx = Integer.parseInt(sstIndex);
+                   RichTextString rtss = sharedStringsTable.getItemAt(idx);
+                   thisStr = rtss.toString();
+               }
+               catch (NumberFormatException ex) {
+                   LOG.log(POILogger.ERROR, "Failed to parse SST index '", 
sstIndex, ex);
+               }
+               break;
+
+           case NUMBER:
+               String n = value.toString();
+               if (this.formatString != null && n.length() > 0)
+                   thisStr = 
formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, 
this.formatString);
+               else
+                   thisStr = n;
+               break;
+
+           default:
+               thisStr = "(TODO: Unexpected type: " + nextDataType + ")";
+               break;
+       }
+
+       // Do we have a comment for this cell?
+       checkForEmptyCellComments(EmptyCellCommentsCheckType.CELL);
+       XSSFComment comment = comments != null ? comments.findCellComment(new 
CellAddress(cellRef)) : null;
+
+       // Output
+       output.cell(cellRef, thisStr, comment);
+   }
+
    /**
     * Do a check for, and output, comments in otherwise empty cells.
     */

Added: 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
URL: 
http://svn.apache.org/viewvc/poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java?rev=1885770&view=auto
==============================================================================
--- 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
 (added)
+++ 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
 Thu Jan 21 21:04:24 2021
@@ -0,0 +1,55 @@
+package org.apache.poi.xssf.eventusermodel;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.util.XMLHelper;
+import 
org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
+import org.apache.poi.xssf.usermodel.XSSFComment;
+import org.junit.jupiter.api.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+import java.io.InputStream;
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class TestXSSFSheetXMLHandler {
+    private static final POIDataSamples _ssTests = 
POIDataSamples.getSpreadSheetInstance();
+
+    @Test
+    public void testInlineString() throws Exception {
+        try (OPCPackage xlsxPackage = 
OPCPackage.open(_ssTests.openResourceAsStream("InlineString.xlsx"))) {
+            final XSSFReader reader = new XSSFReader(xlsxPackage);
+
+            final Iterator<InputStream> iter = reader.getSheetsData();
+
+            try (InputStream stream = iter.next()) {
+                final XMLReader sheetParser = 
XMLHelper.getSaxParserFactory().newSAXParser().getXMLReader();
+
+                sheetParser.setContentHandler(new 
XSSFSheetXMLHandler(reader.getStylesTable(),
+                        new ReadOnlySharedStringsTable(xlsxPackage), new 
SheetContentsHandler() {
+
+                    int cellCount = 0;
+
+                    @Override
+                    public void startRow(final int rowNum) {
+                    }
+
+                    @Override
+                    public void endRow(final int rowNum) {
+                    }
+
+                    @Override
+                    public void cell(final String cellReference, final String 
formattedValue,
+                                     final XSSFComment comment) {
+                        assertEquals("\uD83D\uDE1Cmore text", formattedValue);
+                        assertEquals(cellCount++, 0);
+                    }
+                }, false));
+
+                sheetParser.parse(new InputSource(stream));
+            }
+        }
+    }
+}

Propchange: 
poi/trunk/src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFSheetXMLHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: poi/trunk/test-data/spreadsheet/InlineString.xlsx
URL: 
http://svn.apache.org/viewvc/poi/trunk/test-data/spreadsheet/InlineString.xlsx?rev=1885770&view=auto
==============================================================================
Binary file - no diff available.

Propchange: poi/trunk/test-data/spreadsheet/InlineString.xlsx
------------------------------------------------------------------------------
--- svn:mime-type (added)
+++ svn:mime-type Thu Jan 21 21:04:24 2021
@@ -0,0 +1 @@
+application/vnd.openxmlformats-officedocument.spreadsheetml.sheet



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@poi.apache.org
For additional commands, e-mail: commits-h...@poi.apache.org

Reply via email to