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:
parent
9ba354156d
commit
26f18ed27a
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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())){
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
BIN
src/testcases/org/apache/poi/hssf/data/47504.xlsx
Executable file
BIN
src/testcases/org/apache/poi/hssf/data/47504.xlsx
Executable file
Binary file not shown.
Loading…
Reference in New Issue
Block a user