Fix for saving custom and extended OOXML properties
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@795587 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
bf76476b0e
commit
9196f6e6dd
@ -33,7 +33,8 @@
|
||||
|
||||
<changes>
|
||||
<release version="3.5-beta7" date="2009-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="fix">47535 - fixed WordExtractor to tolerate files with empty footnote block</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">47540 - Fix for saving custom and extended OOXML properties</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">47535 - Fixed WordExtractor to tolerate files with empty footnote block</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">47517 - Fixed ExtractorFactory to support .xltx and .dotx files</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45556 - Support for extraction of footnotes from docx files</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">45555 - Support for extraction of endnotes from docx files</action>
|
||||
|
@ -0,0 +1,75 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.xssf.usermodel.examples;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.POIXMLProperties;
|
||||
|
||||
/**
|
||||
* How to set extended and custom properties
|
||||
*
|
||||
* @author Yegor Kozlov
|
||||
*/
|
||||
public class WorkbookProperties {
|
||||
|
||||
public static void main(String[]args) throws Exception {
|
||||
|
||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||
workbook.createSheet("Workbook Properties");
|
||||
|
||||
POIXMLProperties props = workbook.getProperties();
|
||||
|
||||
/**
|
||||
* Extended properties are a predefined set of metadata properties
|
||||
* that are specifically applicable to Office Open XML documents.
|
||||
* Extended properties consist of 24 simple properties and 3 complex properties stored in the
|
||||
* part targeted by the relationship of type
|
||||
*/
|
||||
POIXMLProperties.ExtendedProperties ext = props.getExtendedProperties();
|
||||
ext.getUnderlyingProperties().setCompany("Apache Software Foundation");
|
||||
ext.getUnderlyingProperties().setTemplate("XSSF");
|
||||
|
||||
/**
|
||||
* Custom properties enable users to define custom metadata properties
|
||||
* through a set of well-defined data types. For example, a custom
|
||||
* OLE Editor property of type string can be defined as follows:
|
||||
*
|
||||
* <property fmtid="{D5CDD505-2E9C-101B-9397-08002B2CF9AE}" pid="2" name="Editor">
|
||||
* <vt:lpwstr>John Smith</vt:lpwstr>
|
||||
* </property>
|
||||
*/
|
||||
|
||||
POIXMLProperties.CustomProperties cust = props.getCustomProperties();
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
|
||||
property = cust.getUnderlyingProperties().addNewProperty();
|
||||
|
||||
property.setFmtid("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}");
|
||||
property.setPid(2);
|
||||
property.setName("Editor");
|
||||
property.setLpwstr("John Smith");
|
||||
|
||||
FileOutputStream out = new FileOutputStream("workbook.xlsx");
|
||||
workbook.write(out);
|
||||
out.close();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -157,9 +157,13 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{
|
||||
* Get the document properties. This gives you access to the
|
||||
* core ooxml properties, and the extended ooxml properties.
|
||||
*/
|
||||
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException {
|
||||
public POIXMLProperties getProperties() {
|
||||
if(properties == null) {
|
||||
properties = new POIXMLProperties(pkg);
|
||||
try {
|
||||
properties = new POIXMLProperties(pkg);
|
||||
} catch (Exception e){
|
||||
throw new POIXMLException(e);
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
@ -197,6 +201,9 @@ public abstract class POIXMLDocument extends POIXMLDocumentPart{
|
||||
//force all children to commit their changes into the underlying OOXML Package
|
||||
onSave();
|
||||
|
||||
//save extended and custom properties
|
||||
getProperties().commit();
|
||||
|
||||
getPackage().save(stream);
|
||||
}
|
||||
|
||||
|
@ -17,12 +17,17 @@
|
||||
package org.apache.poi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.apache.poi.openxml4j.opc.OPCPackage;
|
||||
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
|
||||
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.apache.poi.openxml4j.opc.*;
|
||||
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument;
|
||||
|
||||
/**
|
||||
* Wrapper around the two different kinds of OOXML properties
|
||||
@ -33,8 +38,22 @@ public class POIXMLProperties {
|
||||
private CoreProperties core;
|
||||
private ExtendedProperties ext;
|
||||
private CustomProperties cust;
|
||||
|
||||
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
|
||||
|
||||
private PackagePart extPart;
|
||||
private PackagePart custPart;
|
||||
|
||||
|
||||
private static final org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument NEW_EXT_INSTANCE;
|
||||
private static final org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument NEW_CUST_INSTANCE;
|
||||
static {
|
||||
NEW_EXT_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance();
|
||||
NEW_EXT_INSTANCE.addNewProperties();
|
||||
|
||||
NEW_CUST_INSTANCE = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance();
|
||||
NEW_CUST_INSTANCE.addNewProperties();
|
||||
}
|
||||
|
||||
public POIXMLProperties(OPCPackage docPackage) throws IOException, OpenXML4JException, XmlException {
|
||||
this.pkg = docPackage;
|
||||
|
||||
// Core properties
|
||||
@ -44,24 +63,28 @@ public class POIXMLProperties {
|
||||
PackageRelationshipCollection extRel =
|
||||
pkg.getRelationshipsByType(POIXMLDocument.EXTENDED_PROPERTIES_REL_TYPE);
|
||||
if(extRel.size() == 1) {
|
||||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
|
||||
pkg.getPart( extRel.getRelationship(0) ).getInputStream()
|
||||
extPart = pkg.getPart( extRel.getRelationship(0));
|
||||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.parse(
|
||||
extPart.getInputStream()
|
||||
);
|
||||
ext = new ExtendedProperties(props);
|
||||
} else {
|
||||
ext = new ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument.Factory.newInstance());
|
||||
}
|
||||
extPart = null;
|
||||
ext = new ExtendedProperties((org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument)NEW_EXT_INSTANCE.copy());
|
||||
}
|
||||
|
||||
// Custom properties
|
||||
PackageRelationshipCollection custRel =
|
||||
pkg.getRelationshipsByType(POIXMLDocument.CUSTOM_PROPERTIES_REL_TYPE);
|
||||
if(custRel.size() == 1) {
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
|
||||
pkg.getPart( custRel.getRelationship(0) ).getInputStream()
|
||||
custPart = pkg.getPart( custRel.getRelationship(0));
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props = org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.parse(
|
||||
custPart.getInputStream()
|
||||
);
|
||||
cust = new CustomProperties(props);
|
||||
} else {
|
||||
cust = new CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument.Factory.newInstance());
|
||||
custPart = null;
|
||||
cust = new CustomProperties((org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument)NEW_CUST_INSTANCE.copy());
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,11 +110,44 @@ public class POIXMLProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes out the ooxml properties into the supplied,
|
||||
* new Package
|
||||
* Commit changes to the underlying OPC package
|
||||
*/
|
||||
public void write(OPCPackage pkg) {
|
||||
// TODO
|
||||
public void commit() throws IOException{
|
||||
|
||||
if(extPart == null && !NEW_EXT_INSTANCE.toString().equals(ext.props.toString())){
|
||||
try {
|
||||
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/app.xml");
|
||||
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties");
|
||||
extPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.extended-properties+xml");
|
||||
} catch (InvalidFormatException e){
|
||||
throw new POIXMLException(e);
|
||||
}
|
||||
}
|
||||
if(custPart == null && !NEW_CUST_INSTANCE.toString().equals(cust.props.toString())){
|
||||
try {
|
||||
PackagePartName prtname = PackagingURIHelper.createPartName("/docProps/custom.xml");
|
||||
pkg.addRelationship(prtname, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties");
|
||||
custPart = pkg.createPart(prtname, "application/vnd.openxmlformats-officedocument.custom-properties+xml");
|
||||
} catch (InvalidFormatException e){
|
||||
throw new POIXMLException(e);
|
||||
}
|
||||
}
|
||||
if(extPart != null){
|
||||
XmlOptions xmlOptions = new XmlOptions(POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes", "vt");
|
||||
xmlOptions.setSaveSuggestedPrefixes(map);
|
||||
|
||||
OutputStream out = extPart.getOutputStream();
|
||||
ext.props.save(out, xmlOptions);
|
||||
out.close();
|
||||
}
|
||||
if(custPart != null){
|
||||
OutputStream out = custPart.getOutputStream();
|
||||
cust.props.save(out, POIXMLDocumentPart.DEFAULT_XML_OPTIONS);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,10 +178,6 @@ public class POIXMLProperties {
|
||||
private org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props;
|
||||
private ExtendedProperties(org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.PropertiesDocument props) {
|
||||
this.props = props;
|
||||
|
||||
if(props.getProperties() == null) {
|
||||
props.addNewProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties getUnderlyingProperties() {
|
||||
@ -140,10 +192,6 @@ public class POIXMLProperties {
|
||||
private org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props;
|
||||
private CustomProperties(org.openxmlformats.schemas.officeDocument.x2006.customProperties.PropertiesDocument props) {
|
||||
this.props = props;
|
||||
|
||||
if(props.getProperties() == null) {
|
||||
props.addNewProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties getUnderlyingProperties() {
|
||||
|
134
src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
Executable file
134
src/ooxml/testcases/org/apache/poi/TestPOIXMLProperties.java
Executable file
@ -0,0 +1,134 @@
|
||||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
|
||||
package org.apache.poi;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* Test setting extended and custom OOXML properties
|
||||
*/
|
||||
public class TestPOIXMLProperties extends TestCase {
|
||||
public void testWorkbookExtendedProperties() throws Exception {
|
||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||
POIXMLProperties props = workbook.getProperties();
|
||||
assertNotNull(props);
|
||||
|
||||
org.apache.poi.POIXMLProperties.ExtendedProperties properties =
|
||||
props.getExtendedProperties();
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
|
||||
ctProps = properties.getUnderlyingProperties();
|
||||
|
||||
|
||||
String appVersion = "3.5 beta";
|
||||
String application = "POI";
|
||||
|
||||
ctProps.setApplication(application);
|
||||
ctProps.setAppVersion(appVersion);
|
||||
|
||||
ctProps = null;
|
||||
properties = null;
|
||||
props = null;
|
||||
|
||||
XSSFWorkbook newWorkbook =
|
||||
XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
assertTrue(workbook != newWorkbook);
|
||||
|
||||
|
||||
POIXMLProperties newProps = newWorkbook.getProperties();
|
||||
assertNotNull(newProps);
|
||||
org.apache.poi.POIXMLProperties.ExtendedProperties newProperties =
|
||||
newProps.getExtendedProperties();
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.extendedProperties.CTProperties
|
||||
newCtProps = newProperties.getUnderlyingProperties();
|
||||
|
||||
assertEquals(application, newCtProps.getApplication());
|
||||
assertEquals(appVersion, newCtProps.getAppVersion());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testWorkbookCustomProperties() throws Exception {
|
||||
XSSFWorkbook workbook = new XSSFWorkbook();
|
||||
POIXMLProperties props = workbook.getProperties();
|
||||
assertNotNull(props);
|
||||
|
||||
org.apache.poi.POIXMLProperties.CustomProperties properties =
|
||||
props.getCustomProperties();
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
|
||||
ctProps = properties.getUnderlyingProperties();
|
||||
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
|
||||
property = ctProps.addNewProperty();
|
||||
|
||||
|
||||
String fmtid =
|
||||
"{A1A1A1A1A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1-A1A1A1A1A1A1A1A1}";
|
||||
int pId = 1;
|
||||
String name = "testProperty";
|
||||
String stringValue = "testValue";
|
||||
|
||||
|
||||
property.setFmtid(fmtid);
|
||||
property.setPid(pId);
|
||||
property.setName(name);
|
||||
property.setBstr(stringValue);
|
||||
|
||||
|
||||
property = null;
|
||||
ctProps = null;
|
||||
properties = null;
|
||||
props = null;
|
||||
|
||||
XSSFWorkbook newWorkbook =
|
||||
XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
|
||||
assertTrue(workbook != newWorkbook);
|
||||
|
||||
|
||||
POIXMLProperties newProps = newWorkbook.getProperties();
|
||||
assertNotNull(newProps);
|
||||
org.apache.poi.POIXMLProperties.CustomProperties newProperties =
|
||||
newProps.getCustomProperties();
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperties
|
||||
newCtProps = newProperties.getUnderlyingProperties();
|
||||
|
||||
assertEquals(1, newCtProps.getPropertyArray().length);
|
||||
|
||||
|
||||
org.openxmlformats.schemas.officeDocument.x2006.customProperties.CTProperty
|
||||
newpProperty = newCtProps.getPropertyArray()[0];
|
||||
|
||||
assertEquals(fmtid, newpProperty.getFmtid());
|
||||
assertEquals(pId, newpProperty.getPid());
|
||||
assertEquals(name, newpProperty.getName());
|
||||
assertEquals(stringValue, newpProperty.getBstr());
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user