fixed XSSF and OpenXml4J to read/write relationships with targets starting with '#' (internal locations), see Bugzilla 47504

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@793280 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-07-12 07:18:42 +00:00
parent 9ba354156d
commit 26f18ed27a
9 changed files with 84 additions and 27 deletions

View File

@ -19,6 +19,7 @@ package org.apache.poi;
import java.io.IOException; import java.io.IOException;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.net.URI;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
@ -142,7 +143,7 @@ public class POIXMLDocumentPart {
@Override @Override
public String toString(){ public String toString(){
return packagePart.toString(); return packagePart == null ? null : packagePart.toString();
} }
/** /**
@ -231,17 +232,28 @@ public class POIXMLDocumentPart {
PackageRelationshipCollection rels = packagePart.getRelationships(); PackageRelationshipCollection rels = packagePart.getRelationships();
for (PackageRelationship rel : rels) { for (PackageRelationship rel : rels) {
if(rel.getTargetMode() == TargetMode.INTERNAL){ if(rel.getTargetMode() == TargetMode.INTERNAL){
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); URI uri = rel.getTargetURI();
PackagePart p = packagePart.getPackage().getPart(relName);
PackagePart p;
if(uri.getRawFragment() != null) {
/*
* For internal references (e.g. '#Sheet1!A1') the package part is null
*/
p = null;
} else {
PackagePartName relName = PackagingURIHelper.createPartName(uri);
p = packagePart.getPackage().getPart(relName);
if(p == null) { if(p == null) {
logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI()); logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI());
continue; continue;
} }
}
POIXMLDocumentPart childPart = factory.createDocumentPart(rel, p); POIXMLDocumentPart childPart = factory.createDocumentPart(rel, p);
childPart.parent = this; childPart.parent = this;
addRelation(childPart); addRelation(childPart);
if(p.hasRelationships()) childPart.read(factory); if(p != null && p.hasRelationships()) childPart.read(factory);
} }
} }
} }

View File

@ -161,8 +161,12 @@ public final class ZipPartMarshaller implements PartMarshaller {
PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME, PackageRelationship.TARGET_MODE_ATTRIBUTE_NAME,
"External"); "External");
} else { } else {
URI targetURI = rel.getTargetURI();
targetValue = PackagingURIHelper.relativizeURI( targetValue = PackagingURIHelper.relativizeURI(
sourcePartURI, rel.getTargetURI()).getPath(); sourcePartURI, targetURI).getPath();
if (targetURI.getRawFragment() != null) {
targetValue += "#" + targetURI.getRawFragment();
}
} }
relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME, relElem.addAttribute(PackageRelationship.TARGET_ATTRIBUTE_NAME,
targetValue); targetValue);

View File

@ -22,6 +22,7 @@ import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import java.io.*; import java.io.*;
import java.net.URI;
/** /**
* Provides handy methods to work with OOXML packages * Provides handy methods to work with OOXML packages
@ -83,11 +84,10 @@ public class PackageHelper {
* Creates an empty file in the default temporary-file directory, * Creates an empty file in the default temporary-file directory,
*/ */
public static File createTempFile() throws IOException { public static File createTempFile() throws IOException {
File file = File.createTempFile("poi-ooxml-", ".tmp"); File file = TempFile.createTempFile("poi-ooxml-", ".tmp");
//there is no way to pass an existing file to Package.create(file), //there is no way to pass an existing file to Package.create(file),
//delete first, the file will be re-created in Packe.create(file) //delete first, the file will be re-created in Packe.create(file)
file.delete(); file.delete();
file.deleteOnExit();
return file; return file;
} }
@ -103,12 +103,19 @@ public class PackageHelper {
part_tgt.addExternalRelationship(rel.getTargetURI().toString(), rel.getRelationshipType(), rel.getId()); part_tgt.addExternalRelationship(rel.getTargetURI().toString(), rel.getRelationshipType(), rel.getId());
//external relations don't have associated package parts //external relations don't have associated package parts
continue; continue;
} else {
URI uri = rel.getTargetURI();
if(uri.getRawFragment() != null) {
part_tgt.addRelationship(uri, rel.getTargetMode(), rel.getRelationshipType(), rel.getId());
continue;
} else { } else {
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
p = pkg.getPart(relName); p = pkg.getPart(relName);
part_tgt.addRelationship(p.getPartName(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId());
}
} }
part_tgt.addRelationship(p.getPartName(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId());
PackagePart dest; PackagePart dest;
if(!tgt.containPart(p.getPartName())){ if(!tgt.containPart(p.getPartName())){

View File

@ -35,6 +35,7 @@ import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.internal.ContentTypeManager; import org.apache.poi.openxml4j.opc.internal.ContentTypeManager;
import org.apache.poi.openxml4j.opc.internal.FileHelper; import org.apache.poi.openxml4j.opc.internal.FileHelper;
import org.apache.poi.util.TempFile;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
import org.dom4j.Element; import org.dom4j.Element;
@ -168,6 +169,8 @@ public final class TestPackage extends TestCase {
coreOut.write("<dummy-xml2 />".getBytes()); coreOut.write("<dummy-xml2 />".getBytes());
coreOut.close(); coreOut.close();
//add a relationship with internal target: "#Sheet1!A1"
corePart.addRelationship(new URI("#Sheet1!A1"), TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink", "rId2");
// Check things are as expected // Check things are as expected
PackageRelationshipCollection coreRels = PackageRelationshipCollection coreRels =
@ -181,11 +184,12 @@ public final class TestPackage extends TestCase {
// Save and re-load // Save and re-load
pkg.close(); pkg.close();
FileOutputStream fout = new FileOutputStream(File.createTempFile("testCreatePackageWithCoreDocument", ".zip")); File tmp = TempFile.createTempFile("testCreatePackageWithCoreDocument", ".zip");
FileOutputStream fout = new FileOutputStream(tmp);
fout.write(baos.toByteArray()); fout.write(baos.toByteArray());
fout.close(); fout.close();
pkg = OPCPackage.open(new ByteArrayInputStream(baos.toByteArray())); pkg = OPCPackage.open(tmp.getPath());
//tmp.delete();
// Check still right // Check still right
coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT); coreRels = pkg.getRelationshipsByType(PackageRelationshipTypes.CORE_DOCUMENT);
@ -193,7 +197,15 @@ public final class TestPackage extends TestCase {
coreRel = coreRels.getRelationship(0); coreRel = coreRels.getRelationship(0);
assertEquals("/", coreRel.getSourceURI().toString()); assertEquals("/", coreRel.getSourceURI().toString());
assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString()); assertEquals("/xl/workbook.xml", coreRel.getTargetURI().toString());
assertNotNull(pkg.getPart(coreRel)); corePart = pkg.getPart(coreRel);
assertNotNull(corePart);
PackageRelationshipCollection rels = corePart.getRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink");
assertEquals(1, rels.size());
rel = rels.getRelationship(0);
assertEquals("Sheet1!A1", rel.getTargetURI().getRawFragment());
} }
/** /**

View File

@ -17,9 +17,7 @@
package org.apache.poi.openxml4j.opc; package org.apache.poi.openxml4j.opc;
import java.io.ByteArrayInputStream; import java.io.*;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -254,4 +252,5 @@ public class TestRelationships extends TestCase {
assertEquals("/docProps/core.xml", assertEquals("/docProps/core.xml",
pkg.getRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties").getRelationship(0).getTargetURI().toString()); pkg.getRelationshipsByType("http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties").getRelationship(0).getTargetURI().toString());
} }
} }

View File

@ -30,6 +30,7 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.util.TempFile;
/** /**
* Centralises logic for finding/opening sample files in the src/testcases/org/apache/poi/hssf/hssf/data folder. * Centralises logic for finding/opening sample files in the src/testcases/org/apache/poi/hssf/hssf/data folder.
@ -57,8 +58,7 @@ public class XSSFTestDataSamples {
InputStream is = new ByteArrayInputStream(baos.toByteArray()); InputStream is = new ByteArrayInputStream(baos.toByteArray());
result = new HSSFWorkbook(is); result = new HSSFWorkbook(is);
} else if (wb instanceof XSSFWorkbook) { } else if (wb instanceof XSSFWorkbook) {
File tmp = File.createTempFile("poi-ooxml-", ".xlsx"); File tmp = TempFile.createTempFile("poi-ooxml-", ".xlsx");
tmp.deleteOnExit();
FileOutputStream out = new FileOutputStream(tmp); FileOutputStream out = new FileOutputStream(tmp);
wb.write(out); wb.write(out);
out.close(); out.close();

View File

@ -18,6 +18,7 @@
package org.apache.poi.xssf.usermodel; package org.apache.poi.xssf.usermodel;
import java.io.File; import java.io.File;
import java.util.List;
import junit.framework.TestCase; import junit.framework.TestCase;
@ -28,6 +29,7 @@ import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFITestDataProvider;
import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues; import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
import org.apache.poi.POIXMLDocumentPart;
public class TestXSSFBugs extends BaseTestBugzillaIssues { public class TestXSSFBugs extends BaseTestBugzillaIssues {
@Override @Override
@ -121,4 +123,24 @@ public class TestXSSFBugs extends BaseTestBugzillaIssues {
); );
assertNotNull(drw); assertNotNull(drw);
} }
public void test47504() {
XSSFWorkbook wb = getTestDataProvider().openSampleWorkbook("47504.xlsx");
assertEquals(1, wb.getNumberOfSheets());
XSSFSheet sh = wb.getSheetAt(0);
XSSFDrawing drawing = sh.createDrawingPatriarch();
List<POIXMLDocumentPart> rels = drawing.getRelations();
assertEquals(1, rels.size());
assertEquals("Sheet1!A1", rels.get(0).getPackageRelationship().getTargetURI().getFragment());
// And again, just to be sure
wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
assertEquals(1, wb.getNumberOfSheets());
sh = wb.getSheetAt(0);
drawing = sh.createDrawingPatriarch();
rels = drawing.getRelations();
assertEquals(1, rels.size());
assertEquals("Sheet1!A1", rels.get(0).getPackageRelationship().getTargetURI().getFragment());
}
} }

View File

@ -33,6 +33,7 @@ import org.apache.poi.openxml4j.opc.ContentTypes;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.util.TempFile;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbookPr;
@ -74,7 +75,7 @@ public final class TestXSSFWorkbook extends BaseTestWorkbook {
assertEquals(0, workbook.getSheetAt(2).getFirstRowNum()); assertEquals(0, workbook.getSheetAt(2).getFirstRowNum());
assertEquals(0, workbook.getSheetAt(2).getLastRowNum()); assertEquals(0, workbook.getSheetAt(2).getLastRowNum());
File file = File.createTempFile("poi-", ".xlsx"); File file = TempFile.createTempFile("poi-", ".xlsx");
OutputStream out = new FileOutputStream(file); OutputStream out = new FileOutputStream(file);
workbook.write(out); workbook.write(out);
out.close(); out.close();

Binary file not shown.