]> source.dussan.org Git - poi.git/commitdiff
bug 61034: Call to XSSFReader.getSheetsData() returns duplicate sheets.
authorJaven O'Neal <onealj@apache.org>
Sat, 29 Apr 2017 17:27:17 +0000 (17:27 +0000)
committerJaven O'Neal <onealj@apache.org>
Sat, 29 Apr 2017 17:27:17 +0000 (17:27 +0000)
Thanks to Mauricio Eastmond for the Excel test file and unit test.
Thanks to Sebastian Wikalinski for isolating the problem and providing a patch.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1793223 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java
src/ooxml/testcases/org/apache/poi/xssf/eventusermodel/TestXSSFReader.java
src/testcases/org/apache/poi/POITestCase.java
test-data/spreadsheet/61034.xlsx [new file with mode: 0644]

index 68a85df546dcfbbf5a89d0c10f8affa6ecf980f9..d82c70d3d5ecdee3a33af0d18a5c3a11725724df 100644 (file)
@@ -428,15 +428,18 @@ public class XSSFReader {
 
         @Override
         public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {
-            if (localName.toLowerCase(Locale.US).equals(SHEET)) {
+            if (localName.equalsIgnoreCase(SHEET)) {
                 String name = null;
                 String id = null;
                 for (int i = 0; i < attrs.getLength(); i++) {
-                    if (attrs.getLocalName(i).toLowerCase(Locale.US).equals(NAME)) {
+                    final String attrName = attrs.getLocalName(i);
+                    if (attrName.equalsIgnoreCase(NAME)) {
                         name = attrs.getValue(i);
-                    } else if (attrs.getLocalName(i).toLowerCase(Locale.US).equals(ID)) {
+                    } else if (attrName.equalsIgnoreCase(ID)) {
                         id = attrs.getValue(i);
                     }
+                }
+                if (name != null && id != null) {
                     sheetRefs.add(new XSSFSheetRef(id, name));
                 }
             }
index 1ddd1f045884544c816d45ab426b1ed8917cab0b..0221bcca5b9bb4b456cd3ef9f7fcdeb608bcd141 100644 (file)
 package org.apache.poi.xssf.eventusermodel;
 
 import static org.apache.poi.POITestCase.assertContains;
+import static org.apache.poi.POITestCase.assertNotContained;
 
 import java.io.InputStream;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+import java.util.HashSet;
 
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.POIXMLException;
@@ -267,4 +270,31 @@ public final class TestXSSFReader extends TestCase {
 
         pkg.close();
     }
+
+    /**
+     * bug 61304: Call to XSSFReader.getSheetsData() returns duplicate sheets.
+     *
+     * The problem seems to be caused only by those xlsx files which have a specific
+     * order of the attributes inside the &lt;sheet&gt; tag of workbook.xml 
+     *
+     * Example (which causes the problems):
+     * &lt;sheet name="Sheet6" r:id="rId6" sheetId="4"/&gt;
+     *
+     * While this one works correctly:
+     * &lt;sheet name="Sheet6" sheetId="4" r:id="rId6"/&gt;
+     */
+    public void test61034() throws Exception {
+        OPCPackage pkg = XSSFTestDataSamples.openSamplePackage("61034.xlsx");
+        XSSFReader reader = new XSSFReader(pkg);
+        XSSFReader.SheetIterator iter = (XSSFReader.SheetIterator) reader.getSheetsData();
+        Set<String> seen = new HashSet<String>();
+        while (iter.hasNext()) {
+            InputStream stream = iter.next();
+            String sheetName = iter.getSheetName();
+            assertNotContained(seen, sheetName);
+            seen.add(sheetName);
+            stream.close();
+        }
+        pkg.close();
+    }
 }
index a82b69ababedb6b301482fb177de0af0a83a5e26..88c6eb69eeeca30a51a99021b5dcf088cffeb007 100644 (file)
@@ -30,6 +30,7 @@ import static org.hamcrest.CoreMatchers.containsString;
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.CoreMatchers.endsWith;
 import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.hasItem;
 
 import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.Field;
@@ -41,6 +42,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.poi.util.SuppressForbidden;
 import org.apache.poi.util.Internal;
@@ -110,6 +112,13 @@ public final class POITestCase {
         }
         fail("Unable to find " + key + " in " + map);
     }
+
+    public static <T> void assertNotContained(Set<T> set, T element) {
+        assertThat(set, not(hasItem(element)));
+        /*if (set.contains(element)) {
+            fail("Set should not contain " + element);
+        }*/
+    }
      
     /**
      * Utility method to get the value of a private/protected field.
diff --git a/test-data/spreadsheet/61034.xlsx b/test-data/spreadsheet/61034.xlsx
new file mode 100644 (file)
index 0000000..cd2c5e5
Binary files /dev/null and b/test-data/spreadsheet/61034.xlsx differ