support for custom XML mappings in XSSF, see Bugzilla 47520

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@794539 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yegor Kozlov 2009-07-16 05:46:14 +00:00
parent 9424d59da3
commit 8a3095d0b6
16 changed files with 1703 additions and 6 deletions

View File

@ -33,6 +33,7 @@
<changes>
<release version="3.5-beta7" date="2009-??-??">
<action dev="POI-DEVELOPERS" type="add">47520 - Initial support for custom XML mappings in XSSF</action>
<action dev="POI-DEVELOPERS" type="fix">47460 - Fixed NPE when retrieving core properties from a newly created workbook</action>
<action dev="POI-DEVELOPERS" type="fix">47498 - Fixed HyperlinkRecord to properly handle URL monikers</action>
<action dev="POI-DEVELOPERS" type="fix">47504 - Fixed XSSFWorkbook to read files with hyperlinks to document locations</action>

View File

@ -0,0 +1,42 @@
/* ====================================================================
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 org.apache.poi.xssf.extractor.XSSFExportToXml;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFMap;
import java.io.ByteArrayOutputStream;
/**
* Print all custom XML mappings registered in the given workbook
*/
public class CustomXMLMapping {
public static void main(String[] args) throws Exception {
XSSFWorkbook wb = new XSSFWorkbook(args[0]);
for (XSSFMap map : wb.getCustomXMLMappings()) {
XSSFExportToXml exporter = new XSSFExportToXml(map);
ByteArrayOutputStream os = new ByteArrayOutputStream();
exporter.exportToXML(os, true);
String xml = os.toString("UTF-8");
System.out.println(xml);
}
}
}

View File

@ -0,0 +1,544 @@
/* ====================================================================
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.extractor;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xssf.model.Table;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFMap;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
*
* Maps an XLSX to an XML according to one of the mapping defined.
*
*
* The output XML Schema must respect this limitations:
*
* <ul>
* <li> all mandatory elements and attributes must be mapped </li>
*
* <li> no &lt;any&gt; in complex type/element declaration </li>
* <li> no &lt;anyAttribute&gt; attributes declaration </li>
* <li> no recursive structures: recursive structures can't be nested more than one level </li>
* <li> no abstract elements: abstract complex types can be declared but must not be used in elements. </li>
* <li> no mixed content: an element can't contain simple text and child element(s) together </li>
* <li> no &lt;substitutionGroup&gt; in complex type/element declaration </li>
* </ul>
*
* @author Roberto Manicardi
*
*
*
*/
public class XSSFExportToXml implements Comparator<String>{
private XSSFMap map;
/**
* Creates a new exporter and sets the mapping to be used when generating the XML output document
*
* @param map the mapping rule to be used
*/
public XSSFExportToXml(XSSFMap map){
this.map = map;
}
/**
*
* Exports the data in an XML stream
*
* @param os OutputStream in which will contain the output XML
* @param validate if true, validates the XML againts the XML Schema
* @throws SAXException
*/
public void exportToXML(OutputStream os, boolean validate) throws SAXException{
exportToXML(os,"UTF-8", validate);
}
private Document getEmptyDocument() throws ParserConfigurationException{
DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
return doc;
}
/**
* Exports the data in an XML stream
*
* @param os OutputStream in which will contain the output XML
* @param encoding the output charset encoding
* @param validate if true, validates the XML againts the XML Schema
* @throws SAXException
* @throws InvalidFormatException
*/
public void exportToXML(OutputStream os, String encoding, boolean validate) throws SAXException{
List<XSSFSingleXmlCell> singleXMLCells = map.getRelatedSingleXMLCell();
List<Table> tables = map.getRelatedTables();
String rootElement = map.getCtMap().getRootElement();
try{
Document doc = getEmptyDocument();
Element root = null;
if(isNamespaceDeclared()){
root=doc.createElementNS(getNamespace(),rootElement);
}else{
root=doc.createElement(rootElement);
}
doc.appendChild(root);
List<String> xpaths = new Vector<String>();
Map<String,XSSFSingleXmlCell> singleXmlCellsMappings = new HashMap<String,XSSFSingleXmlCell>();
Map<String,Table> tableMappings = new HashMap<String,Table>();
for(XSSFSingleXmlCell simpleXmlCell : singleXMLCells){
xpaths.add(simpleXmlCell.getXpath());
singleXmlCellsMappings.put(simpleXmlCell.getXpath(), simpleXmlCell);
}
for(Table table : tables){
String commonXPath = table.getCommonXpath();
xpaths.add(commonXPath);
tableMappings.put(commonXPath, table);
}
Collections.sort(xpaths,this);
for(String xpath : xpaths){
XSSFSingleXmlCell simpleXmlCell = singleXmlCellsMappings.get(xpath);
Table table = tableMappings.get(xpath);
if(!xpath.matches(".*\\[.*")){
// Exports elements and attributes mapped with simpleXmlCell
if(simpleXmlCell!=null){
XSSFCell cell = simpleXmlCell.getReferencedCell();
if(cell!=null){
Node currentNode = getNodeByXPath(xpath,doc.getFirstChild(),doc,false);
STXmlDataType.Enum dataType = simpleXmlCell.getXmlDataType();
mapCellOnNode(cell,currentNode,dataType);
}
}
// Exports elements and attributes mapped with tables
if(table!=null){
List<XSSFXmlColumnPr> tableColumns = table.getXmlColumnPrs();
XSSFSheet sheet = table.getXSSFSheet();
int startRow = table.getStartCellReference().getRow();
// In mappings created with Microsoft Excel the first row contains the table header and must be skipped
startRow +=1;
int endRow = table.getEndCellReference().getRow();
for(int i = startRow; i<= endRow; i++){
XSSFRow row = sheet.getRow(i);
Node tableRootNode = getNodeByXPath(table.getCommonXpath(),doc.getFirstChild(),doc,true);
short startColumnIndex = table.getStartCellReference().getCol();
for(int j = startColumnIndex; j<= table.getEndCellReference().getCol();j++){
XSSFCell cell = row.getCell(j);
if(cell!=null){
XSSFXmlColumnPr pointer = tableColumns.get(j-startColumnIndex);
String localXPath = pointer.getLocalXPath();
Node currentNode = getNodeByXPath(localXPath,tableRootNode,doc,false);
STXmlDataType.Enum dataType = pointer.getXmlDataType();
mapCellOnNode(cell,currentNode,dataType);
}
}
}
}
}else{
// TODO: implement filtering management in xpath
}
}
boolean isValid = true;
if(validate){
isValid =isValid(doc);
}
if(isValid){
/////////////////
//Output the XML
//set up a transformer
TransformerFactory transfac = TransformerFactory.newInstance();
Transformer trans = transfac.newTransformer();
trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
trans.setOutputProperty(OutputKeys.INDENT, "yes");
trans.setOutputProperty(OutputKeys.ENCODING, encoding);
//create string from xml tree
StreamResult result = new StreamResult(os);
DOMSource source = new DOMSource(doc);
trans.transform(source, result);
}
}catch(ParserConfigurationException e){
e.printStackTrace();
}catch(TransformerException e){
e.printStackTrace();
}
}
/**
* Validate the generated XML against the XML Schema associated with the XSSFMap
*
* @param xml the XML to validate
* @return
*/
private boolean isValid(Document xml) throws SAXException{
boolean isValid = false;
try{
String language = XMLConstants.W3C_XML_SCHEMA_NS_URI;
SchemaFactory factory = SchemaFactory.newInstance(language);
Source source = new DOMSource(map.getSchema());
Schema schema = factory.newSchema(source);
Validator validator = schema.newValidator();
validator.validate(new DOMSource(xml));
//if no exceptions where raised, the document is valid
isValid=true;
}catch(IOException e){
e.printStackTrace();
}
return isValid;
}
private void mapCellOnNode(XSSFCell cell, Node node, STXmlDataType.Enum outputDataType){
String value ="";
switch (cell.getCellType()){
case XSSFCell.CELL_TYPE_STRING: value = cell.getStringCellValue(); break;
case XSSFCell.CELL_TYPE_BOOLEAN: value += cell.getBooleanCellValue(); break;
case XSSFCell.CELL_TYPE_ERROR: value = cell.getErrorCellString();
case XSSFCell.CELL_TYPE_FORMULA: value = cell.getStringCellValue(); break;
case XSSFCell.CELL_TYPE_NUMERIC: value += cell.getRawValue(); break;
default: ;
}
if(node instanceof Element){
Element currentElement = (Element) node;
currentElement.setTextContent(value);
}else{
node.setNodeValue(value);
}
}
private String removeNamespace(String elementName){
return elementName.matches(".*:.*")?elementName.split(":")[1]:elementName;
}
private Node getNodeByXPath(String xpath,Node rootNode,Document doc,boolean createMultipleInstances){
String[] xpathTokens = xpath.split("/");
Node currentNode =rootNode;
// The first token is empty, the second is the root node
for(int i =2; i<xpathTokens.length;i++){
String axisName = removeNamespace(xpathTokens[i]);
if(!axisName.startsWith("@")){
NodeList list =currentNode.getChildNodes();
Node selectedNode = null;
if(!(createMultipleInstances && i==xpathTokens.length-1) ){
// select the last child node only if we need to map to a single cell
selectedNode = selectNode(axisName, list);
}
if(selectedNode==null){
selectedNode = createElement(doc, currentNode, axisName);
}
currentNode = selectedNode;
}else{
Node attribute = createAttribute(doc, currentNode, axisName);
currentNode = attribute;
}
}
return currentNode;
}
private Node createAttribute(Document doc, Node currentNode, String axisName) {
String attributeName = axisName.substring(1);
NamedNodeMap attributesMap = currentNode.getAttributes();
Node attribute = attributesMap.getNamedItem(attributeName);
if(attribute==null){
attribute = doc.createAttribute(attributeName);
attributesMap.setNamedItem(attribute);
}
return attribute;
}
private Node createElement(Document doc, Node currentNode, String axisName) {
Node selectedNode;
if(isNamespaceDeclared()){
selectedNode =doc.createElementNS(getNamespace(),axisName);
}else{
selectedNode =doc.createElement(axisName);
}
currentNode.appendChild(selectedNode);
return selectedNode;
}
private Node selectNode(String axisName, NodeList list) {
Node selectedNode = null;
for(int j=0;j<list.getLength();j++){
Node node = list.item(j);
if(node.getNodeName().equals(axisName)){
selectedNode=node;
break;
}
}
return selectedNode;
}
private boolean isNamespaceDeclared(){
String schemaNamespace = getNamespace();
return schemaNamespace!=null && !schemaNamespace.equals("");
}
private String getNamespace(){
return map.getCTSchema().getNamespace();
}
/**
* Compares two xpaths to define an ordering according to the XML Schema
*
*/
public int compare(String leftXpath, String rightXpath) {
int result = 0;
Node xmlSchema = map.getSchema();
String[] leftTokens = leftXpath.split("/");
String[] rightTokens = rightXpath.split("/");
int minLenght = leftTokens.length< rightTokens.length? leftTokens.length : rightTokens.length;
Node localComplexTypeRootNode = xmlSchema;
for(int i =1;i <minLenght; i++){
String leftElementName =leftTokens[i];
String rightElementName = rightTokens[i];
if(leftElementName.equals(rightElementName)){
Node complexType = getComplexTypeForElement(leftElementName, xmlSchema,localComplexTypeRootNode);
localComplexTypeRootNode = complexType;
}else{
int leftIndex = indexOfElementInComplexType(leftElementName,localComplexTypeRootNode);
int rightIndex = indexOfElementInComplexType(rightElementName,localComplexTypeRootNode);
if(leftIndex!=-1 && rightIndex!=-1){
if( leftIndex < rightIndex){
result = -1;
}if( leftIndex > rightIndex){
result = 1;
}
}else{
// NOTE: the xpath doesn't match correctly in the schema
}
}
}
return result;
}
private int indexOfElementInComplexType(String elementName,Node complexType){
NodeList list = complexType.getChildNodes();
int indexOf = -1;
for(int i=0; i< list.getLength();i++){
Node node = list.item(i);
if(node instanceof Element){
if(node.getLocalName().equals("element")){
Node nameAttribute = node.getAttributes().getNamedItem("name");
if(nameAttribute.getNodeValue().equals(removeNamespace(elementName))){
indexOf = i;
break;
}
}
}
}
return indexOf;
}
private Node getComplexTypeForElement(String elementName,Node xmlSchema,Node localComplexTypeRootNode){
Node complexTypeNode = null;
String elementNameWithoutNamespace = removeNamespace(elementName);
NodeList list = localComplexTypeRootNode.getChildNodes();
String complexTypeName = "";
for(int i=0; i< list.getLength();i++){
Node node = list.item(i);
if( node instanceof Element){
if(node.getLocalName().equals("element")){
Node nameAttribute = node.getAttributes().getNamedItem("name");
if(nameAttribute.getNodeValue().equals(elementNameWithoutNamespace)){
Node complexTypeAttribute = node.getAttributes().getNamedItem("type");
if(complexTypeAttribute!=null){
complexTypeName = complexTypeAttribute.getNodeValue();
break;
}
}
}
}
}
// Note: we expect that all the complex types are defined at root level
if(!complexTypeName.equals("")){
NodeList complexTypeList = xmlSchema.getChildNodes();
for(int i=0; i< complexTypeList.getLength();i++){
Node node = list.item(i);
if( node instanceof Element){
if(node.getLocalName().equals("complexType")){
Node nameAttribute = node.getAttributes().getNamedItem("name");
if(nameAttribute.getNodeValue().equals(complexTypeName)){
NodeList complexTypeChildList =node.getChildNodes();
for(int j=0; j<complexTypeChildList.getLength();j++){
Node sequence = complexTypeChildList.item(j);
if( sequence instanceof Element){
if(sequence.getLocalName().equals("sequence")){
complexTypeNode = sequence;
break;
}
}
}
if(complexTypeNode!=null){
break;
}
}
}
}
}
}
return complexTypeNode;
}
}

View File

@ -0,0 +1,148 @@
/* ====================================================================
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.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.xssf.usermodel.XSSFMap;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMap;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMapInfo;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSchema;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.MapInfoDocument;
/**
*
* This class implements the Custom XML Mapping Part (Open Office XML Part 1:
* chapter 12.3.6)
*
* An instance of this part type contains a schema for an XML file, and
* information on the behavior that is used when allowing this custom XML schema
* to be mapped into the spreadsheet.
*
* @author Roberto Manicardi
*/
public class MapInfo extends POIXMLDocumentPart {
private CTMapInfo mapInfo;
private Map<Integer, XSSFMap> maps ;
public MapInfo() {
super();
mapInfo = CTMapInfo.Factory.newInstance();
}
public MapInfo(PackagePart part, PackageRelationship rel)
throws IOException {
super(part, rel);
readFrom(part.getInputStream());
}
public void readFrom(InputStream is) throws IOException {
try {
MapInfoDocument doc = MapInfoDocument.Factory.parse(is);
mapInfo = doc.getMapInfo();
maps= new HashMap<Integer, XSSFMap>();
for(CTMap map :mapInfo.getMapArray()){
maps.put((int)map.getID(), new XSSFMap(map,this));
}
} catch (XmlException e) {
throw new IOException(e.getLocalizedMessage());
}
}
/**
* Returns the parent XSSFWorkbook
*
* @return the parent XSSFWorkbook
*/
public XSSFWorkbook getWorkbook() {
return (XSSFWorkbook)getParent();
}
/**
*
* @return the internal data object
*/
public CTMapInfo getCTMapInfo(){
return mapInfo;
}
/**
* Gets the CTSchema buy it's ID
* @param schemaId the schema ID
* @return
*/
public CTSchema getCTSchemaById(String schemaId){
CTSchema xmlSchema = null;
CTSchema[] schemas = mapInfo.getSchemaArray();
for(CTSchema schema: schemas){
if(schema.getID().equals(schemaId)){
xmlSchema = schema;
break;
}
}
return xmlSchema;
}
public XSSFMap getXSSFMapById(int id){
return maps.get(id);
}
/**
*
* @return all the mappings configured in this document
*/
public Collection<XSSFMap> getAllXSSFMaps(){
return maps.values();
}
protected void writeTo(OutputStream out) throws IOException {
MapInfoDocument doc = MapInfoDocument.Factory.newInstance();
doc.setMapInfo(mapInfo);
doc.save(out, DEFAULT_XML_OPTIONS);
}
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
writeTo(out);
out.close();
}
}

View File

@ -0,0 +1,106 @@
/* ====================================================================
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.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Vector;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSingleXmlCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSingleXmlCells;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SingleXmlCellsDocument;
/**
*
* This class implements the Single Cell Tables Part (Open Office XML Part 4:
* chapter 3.5.2)
*
*
* @author Roberto Manicardi
*/
public class SingleXmlCells extends POIXMLDocumentPart {
private CTSingleXmlCells singleXMLCells;
public SingleXmlCells() {
super();
singleXMLCells = CTSingleXmlCells.Factory.newInstance();
}
public SingleXmlCells(PackagePart part, PackageRelationship rel)
throws IOException {
super(part, rel);
readFrom(part.getInputStream());
}
public void readFrom(InputStream is) throws IOException {
try {
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.parse(is);
singleXMLCells = doc.getSingleXmlCells();
} catch (XmlException e) {
throw new IOException(e.getLocalizedMessage());
}
}
public XSSFSheet getXSSFSheet(){
return (XSSFSheet) getParent();
}
protected void writeTo(OutputStream out) throws IOException {
SingleXmlCellsDocument doc = SingleXmlCellsDocument.Factory.newInstance();
doc.setSingleXmlCells(singleXMLCells);
doc.save(out, DEFAULT_XML_OPTIONS);
}
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
writeTo(out);
out.close();
}
public CTSingleXmlCells getCTSingleXMLCells(){
return singleXMLCells;
}
/**
*
* @return all the SimpleXmlCell contained in this SingleXmlCells element
*/
public List<XSSFSingleXmlCell> getAllSimpleXmlCell(){
List<XSSFSingleXmlCell> list = new Vector<XSSFSingleXmlCell>();
CTSingleXmlCell[] singleXMLCellArray = singleXMLCells.getSingleXmlCellArray();
for(CTSingleXmlCell singleXmlCell: singleXMLCellArray){
list.add(new XSSFSingleXmlCell(singleXmlCell,this));
}
return list;
}
}

View File

@ -0,0 +1,248 @@
/* ====================================================================
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.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.TableDocument;
/**
*
* This class implements the Table Part (Open Office XML Part 4:
* chapter 3.5.1)
*
* This implementation works under the assumption that a table contains mappings to a subtree of an XML.
* The root element of this subtree an occur multiple times (one for each row of the table). The child nodes
* of the root element can be only attributes or element with maxOccurs=1 property set
*
*
* @author Roberto Manicardi
*/
public class Table extends POIXMLDocumentPart {
private CTTable ctTable;
private List<XSSFXmlColumnPr> xmlColumnPr;
private CellReference startCellReference;
private CellReference endCellReference;
private String commonXPath;
public Table() {
super();
ctTable = CTTable.Factory.newInstance();
}
public Table(PackagePart part, PackageRelationship rel)
throws IOException {
super(part, rel);
readFrom(part.getInputStream());
}
public void readFrom(InputStream is) throws IOException {
try {
TableDocument doc = TableDocument.Factory.parse(is);
ctTable = doc.getTable();
} catch (XmlException e) {
throw new IOException(e.getLocalizedMessage());
}
}
public XSSFSheet getXSSFSheet(){
return (XSSFSheet) getParent();
}
public void writeTo(OutputStream out) throws IOException {
TableDocument doc = TableDocument.Factory.newInstance();
doc.setTable(ctTable);
doc.save(out, DEFAULT_XML_OPTIONS);
}
@Override
protected void commit() throws IOException {
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
writeTo(out);
out.close();
}
public CTTable getCTTable(){
return ctTable;
}
/**
* Checks if this Table element contains even a single mapping to the map identified by id
* @param id the XSSFMap ID
* @return true if the Table element contain mappings
*/
public boolean mapsTo(long id){
boolean maps =false;
List<XSSFXmlColumnPr> pointers = getXmlColumnPrs();
for(XSSFXmlColumnPr pointer: pointers){
if(pointer.getMapId()==id){
maps=true;
break;
}
}
return maps;
}
/**
*
* Calculates the xpath of the root element for the table. This will be the common part
* of all the mapping's xpaths
*
* @return the xpath of the table's root element
*/
public String getCommonXpath() {
if(commonXPath == null){
String[] commonTokens ={};
for(CTTableColumn column :ctTable.getTableColumns().getTableColumnArray()){
if(column.getXmlColumnPr()!=null){
String xpath = column.getXmlColumnPr().getXpath();
String[] tokens = xpath.split("/");
if(commonTokens.length==0){
commonTokens = tokens;
}else{
int maxLenght = commonTokens.length>tokens.length? tokens.length:commonTokens.length;
for(int i =0; i<maxLenght;i++){
if(!commonTokens[i].equals(tokens[i])){
List<String> subCommonTokens = Arrays.asList(commonTokens).subList(0, i);
String[] container = {};
commonTokens = subCommonTokens.toArray(container);
break;
}
}
}
}
}
commonXPath ="";
for(int i = 1 ; i< commonTokens.length;i++){
commonXPath +="/"+commonTokens[i];
}
}
return commonXPath;
}
public List<XSSFXmlColumnPr> getXmlColumnPrs() {
if(xmlColumnPr==null){
xmlColumnPr = new Vector<XSSFXmlColumnPr>();
for(CTTableColumn column:ctTable.getTableColumns().getTableColumnArray()){
if(column.getXmlColumnPr()!=null){
XSSFXmlColumnPr columnPr = new XSSFXmlColumnPr(this,column,column.getXmlColumnPr());
xmlColumnPr.add(columnPr);
}
}
}
return xmlColumnPr;
}
/**
* the number of mapped table columns (see Open Office XML Part 4: chapter 3.5.1.4)
* @return
*/
public long getNumerOfMappedColumns(){
return ctTable.getTableColumns().getCount();
}
/**
* The reference for the cell in the top-left part of the table
* (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
* @return
*/
public CellReference getStartCellReference() {
if(startCellReference==null){
String ref = ctTable.getRef();
String[] boundaries = ref.split(":");
String from = boundaries[0];
startCellReference = new CellReference(from);
}
return startCellReference;
}
/**
* The reference for the cell in the bottom-right part of the table
* (see Open Office XML Part 4: chapter 3.5.1.2, attribute ref)
* @return
*/
public CellReference getEndCellReference() {
if(endCellReference==null){
String ref = ctTable.getRef();
String[] boundaries = ref.split(":");
String from = boundaries[1];
endCellReference = new CellReference(from);
}
return endCellReference;
}
/**
* Gets the total number of rows in the selection. (Note: in this version autofiltering is ignored)
* @return
*/
public int getRowCount(){
CellReference from = getStartCellReference();
CellReference to = getEndCellReference();
int rowCount = -1;
if (from!=null && to!=null){
rowCount = to.getRow()-from.getRow();
}
return rowCount;
}
}

View File

@ -0,0 +1,120 @@
/* ====================================================================
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;
import java.util.List;
import java.util.Vector;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.xssf.model.MapInfo;
import org.apache.poi.xssf.model.SingleXmlCells;
import org.apache.poi.xssf.model.Table;
import org.apache.poi.xssf.usermodel.helpers.XSSFSingleXmlCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMap;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSchema;
import org.w3c.dom.Node;
/**
* This class implements the Map element (Open Office XML Part 4:
* chapter 3.16.2)
* <p/>
* This element contains all of the properties related to the XML map,
* and the behaviors expected during data refresh operations.
*
* @author Roberto Manicardi
*/
public class XSSFMap {
private CTMap ctMap;
private MapInfo mapInfo;
public XSSFMap(CTMap ctMap, MapInfo mapInfo) {
this.ctMap = ctMap;
this.mapInfo = mapInfo;
}
public CTMap getCtMap() {
return ctMap;
}
public CTSchema getCTSchema() {
String schemaId = ctMap.getSchemaID();
return mapInfo.getCTSchemaById(schemaId);
}
public Node getSchema() {
Node xmlSchema = null;
CTSchema schema = getCTSchema();
xmlSchema = schema.getDomNode().getFirstChild();
return xmlSchema;
}
/**
* @return the list of Single Xml Cells that provide a map rule to this mapping.
*/
public List<XSSFSingleXmlCell> getRelatedSingleXMLCell() {
List<XSSFSingleXmlCell> relatedSimpleXmlCells = new Vector<XSSFSingleXmlCell>();
int sheetNumber = mapInfo.getWorkbook().getNumberOfSheets();
for (int i = 0; i < sheetNumber; i++) {
XSSFSheet sheet = mapInfo.getWorkbook().getSheetAt(i);
for (POIXMLDocumentPart p : sheet.getRelations()) {
if (p instanceof SingleXmlCells) {
SingleXmlCells singleXMLCells = (SingleXmlCells) p;
for (XSSFSingleXmlCell cell : singleXMLCells.getAllSimpleXmlCell()) {
if (cell.getMapId() == ctMap.getID()) {
relatedSimpleXmlCells.add(cell);
}
}
}
}
}
return relatedSimpleXmlCells;
}
/**
* @return the list of all Tables that provide a map rule to this mapping
*/
public List<Table> getRelatedTables() {
List<Table> tables = new Vector<Table>();
int sheetNumber = mapInfo.getWorkbook().getNumberOfSheets();
for (int i = 0; i < sheetNumber; i++) {
XSSFSheet sheet = mapInfo.getWorkbook().getSheetAt(i);
for (POIXMLDocumentPart p : sheet.getRelations()) {
if (p.getPackageRelationship().getRelationshipType().equals(XSSFRelation.TABLE.getRelation())) {
Table table = (Table) p;
if (table.mapsTo(ctMap.getID())) {
tables.add(table);
}
}
}
}
return tables;
}
}

View File

@ -25,10 +25,13 @@ import java.util.HashMap;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.POIXMLRelation;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.xssf.model.MapInfo;
import org.apache.poi.xssf.model.SingleXmlCells;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.xssf.model.CalculationChain;
import org.apache.poi.xssf.model.Table;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
@ -93,6 +96,28 @@ public final class XSSFRelation extends POIXMLRelation {
"/xl/drawings/vmlDrawing#.vml",
null
);
public static final XSSFRelation CUSTOM_XML_MAPPINGS = new XSSFRelation(
"application/xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/xmlMaps",
"/xl/xmlMaps.xml",
MapInfo.class
);
public static final XSSFRelation SINGLE_XML_CELLS = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.spreadsheetml.tableSingleCells+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/tableSingleCells",
"/tables/tableSingleCells#.xml",
SingleXmlCells.class
);
public static final XSSFRelation TABLE = new XSSFRelation(
"application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/table",
"/tables/table#.xml",
Table.class
);
public static final XSSFRelation IMAGES = new XSSFRelation(
null,
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",

View File

@ -22,12 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.regex.Pattern;
import javax.xml.namespace.QName;
@ -56,6 +51,8 @@ import org.apache.poi.util.PackageHelper;
import org.apache.poi.xssf.model.CalculationChain;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.model.MapInfo;
import org.apache.poi.xssf.extractor.XSSFExportToXml;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
@ -106,6 +103,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
*/
private CalculationChain calcChain;
/**
* A collection of custom XML mappings
*/
private MapInfo mapInfo;
/**
* Used to keep track of the data formatter so that all
* createDataFormatter calls return the same one for a given
@ -174,6 +176,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
if(p instanceof SharedStringsTable) sharedStringSource = (SharedStringsTable)p;
else if(p instanceof StylesTable) stylesSource = (StylesTable)p;
else if(p instanceof CalculationChain) calcChain = (CalculationChain)p;
else if(p instanceof MapInfo) mapInfo = (MapInfo)p;
else if (p instanceof XSSFSheet) {
shIdMap.put(p.getPackageRelationship().getId(), (XSSFSheet)p);
}
@ -1282,4 +1285,11 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X
return calcChain;
}
/**
*
* @return a collection of custom XML mappings defined in this workbook
*/
public Collection<XSSFMap> getCustomXMLMappings(){
return mapInfo == null ? new ArrayList<XSSFMap>() : mapInfo.getAllXSSFMaps();
}
}

View File

@ -0,0 +1,84 @@
/* ====================================================================
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.helpers;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xssf.model.SingleXmlCells;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSingleXmlCell;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlCellPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType.Enum;
/**
*
* This class is a wrapper around the CTSingleXmlCell (Open Office XML Part 4:
* chapter 3.5.2.1)
*
*
* @author Roberto Manicardi
*
*/
public class XSSFSingleXmlCell {
private CTSingleXmlCell singleXmlCell;
private SingleXmlCells parent;
public XSSFSingleXmlCell(CTSingleXmlCell singleXmlCell, SingleXmlCells parent){
this.singleXmlCell = singleXmlCell;
this.parent = parent;
}
/**
* Gets the XSSFCell referenced by the R attribute
* @return the referenced XSSFCell, null if the cell reference is invalid
*/
public XSSFCell getReferencedCell(){
XSSFCell cell = null;
CellReference cellReference = new CellReference(singleXmlCell.getR());
XSSFRow row = parent.getXSSFSheet().getRow(cellReference.getRow());
cell = row.getCell(cellReference.getCol());
return cell;
}
public String getXpath(){
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr();
CTXmlPr xmlPr = xmlCellPr.getXmlPr();
String xpath = xmlPr.getXpath();
return xpath;
}
public long getMapId(){
return singleXmlCell.getXmlCellPr().getXmlPr().getMapId();
}
public Enum getXmlDataType() {
CTXmlCellPr xmlCellPr = singleXmlCell.getXmlCellPr();
CTXmlPr xmlPr = xmlCellPr.getXmlPr();
return xmlPr.getXmlDataType();
}
}

View File

@ -0,0 +1,65 @@
/* ====================================================================
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.helpers;
import org.apache.poi.xssf.model.Table;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXmlColumnPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STXmlDataType.Enum;
/**
*
* This class is a wrapper around the CTXmlColumnPr (Open Office XML Part 4:
* chapter 3.5.1.7)
*
*
* @author Roberto Manicardi
*/
public class XSSFXmlColumnPr {
private Table table;
private CTTableColumn ctTableColumn;
private CTXmlColumnPr ctXmlColumnPr;
public XSSFXmlColumnPr(Table table ,CTTableColumn ctTableColum,CTXmlColumnPr ctXmlColumnPr){
this.table = table;
this.ctTableColumn = ctTableColum;
this.ctXmlColumnPr = ctXmlColumnPr;
}
public long getMapId(){
return ctXmlColumnPr.getMapId();
}
public String getLocalXPath(){
String localXPath = "";
int numberOfCommonXPathAxis = table.getCommonXpath().split("/").length-1;
String[] xPathTokens = ctXmlColumnPr.getXpath().split("/");
for(int i=numberOfCommonXPathAxis; i<xPathTokens.length;i++){
localXPath += "/" +xPathTokens[i];
}
return localXPath;
}
public Enum getXmlDataType() {
return ctXmlColumnPr.getXmlDataType();
}
}

View File

@ -0,0 +1,220 @@
/* ====================================================================
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.extractor;
import java.io.ByteArrayOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import junit.framework.TestCase;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.model.MapInfo;
import org.apache.poi.xssf.usermodel.XSSFMap;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
/**
*
* @author Roberto Manicardi
*
*/
public class TestXSSFExportToXML extends TestCase{
public void testExportToXML() throws Exception{
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXmlMappings.xlsx");
MapInfo mapInfo = null;
for(POIXMLDocumentPart p : wb.getRelations()){
if(p instanceof MapInfo){
mapInfo = (MapInfo) p;
XSSFMap map = mapInfo.getXSSFMapById(1);
XSSFExportToXml exporter = new XSSFExportToXml(map);
ByteArrayOutputStream os = new ByteArrayOutputStream();
exporter.exportToXML(os,true);
String xml = os.toString("UTF-8");
assertNotNull(xml);
assertTrue(!xml.equals(""));
String docente = xml.split("<DOCENTE>")[1].split("</DOCENTE>")[0].trim();
String nome = xml.split("<NOME>")[1].split("</NOME>")[0].trim();
String tutor = xml.split("<TUTOR>")[1].split("</TUTOR>")[0].trim();
String cdl = xml.split("<CDL>")[1].split("</CDL>")[0].trim();
String durata = xml.split("<DURATA>")[1].split("</DURATA>")[0].trim();
String argomento = xml.split("<ARGOMENTO>")[1].split("</ARGOMENTO>")[0].trim();
String progetto = xml.split("<PROGETTO>")[1].split("</PROGETTO>")[0].trim();
String crediti = xml.split("<CREDITI>")[1].split("</CREDITI>")[0].trim();
assertEquals("ro",docente);
assertEquals("ro",nome);
assertEquals("ds",tutor);
assertEquals("gs",cdl);
assertEquals("g",durata);
assertEquals("gvvv",argomento);
assertEquals("aaaa",progetto);
assertEquals("aa",crediti);
}
}
}
public void testExportToXMLInverseOrder() throws Exception{
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXmlMappings-inverse-order.xlsx");
MapInfo mapInfo = null;
for(POIXMLDocumentPart p : wb.getRelations()){
if(p instanceof MapInfo){
mapInfo = (MapInfo) p;
XSSFMap map = mapInfo.getXSSFMapById(1);
XSSFExportToXml exporter = new XSSFExportToXml(map);
ByteArrayOutputStream os = new ByteArrayOutputStream();
exporter.exportToXML(os,true);
String xml = os.toString("UTF-8");
assertNotNull(xml);
assertTrue(!xml.equals(""));
String docente = xml.split("<DOCENTE>")[1].split("</DOCENTE>")[0].trim();
String nome = xml.split("<NOME>")[1].split("</NOME>")[0].trim();
String tutor = xml.split("<TUTOR>")[1].split("</TUTOR>")[0].trim();
String cdl = xml.split("<CDL>")[1].split("</CDL>")[0].trim();
String durata = xml.split("<DURATA>")[1].split("</DURATA>")[0].trim();
String argomento = xml.split("<ARGOMENTO>")[1].split("</ARGOMENTO>")[0].trim();
String progetto = xml.split("<PROGETTO>")[1].split("</PROGETTO>")[0].trim();
String crediti = xml.split("<CREDITI>")[1].split("</CREDITI>")[0].trim();
assertEquals("aa",nome);
assertEquals("aaaa",docente);
assertEquals("gvvv",tutor);
assertEquals("g",cdl);
assertEquals("gs",durata);
assertEquals("ds",argomento);
assertEquals("ro",progetto);
assertEquals("ro",crediti);
}
}
}
public void testXPathOrdering() throws Exception{
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXmlMappings-inverse-order.xlsx");
MapInfo mapInfo = null;
for(POIXMLDocumentPart p : wb.getRelations()){
if(p instanceof MapInfo){
mapInfo = (MapInfo) p;
XSSFMap map = mapInfo.getXSSFMapById(1);
XSSFExportToXml exporter = new XSSFExportToXml(map);
assertEquals(1,exporter.compare("/CORSO/DOCENTE", "/CORSO/NOME"));
assertEquals(-1,exporter.compare("/CORSO/NOME", "/CORSO/DOCENTE"));
}
}
}
public void testMultiTable() throws Exception{
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXMLMappings-complex-type.xlsx");
for(POIXMLDocumentPart p : wb.getRelations()){
if(p instanceof MapInfo){
MapInfo mapInfo = (MapInfo) p;
XSSFMap map = mapInfo.getXSSFMapById(2);
assertNotNull(map);
XSSFExportToXml exporter = new XSSFExportToXml(map);
ByteArrayOutputStream os = new ByteArrayOutputStream();
exporter.exportToXML(os,true);
String xml = os.toString("UTF-8");
assertNotNull(xml);
String[] regexConditions = { "<MapInfo",
"</MapInfo>",
"<Schema ID=\"1\" Namespace=\"\" SchemaRef=\"\"/>",
"<Schema ID=\"4\" Namespace=\"\" SchemaRef=\"\"/>",
"DataBinding",
"Map Append=\"false\" AutoFit=\"false\" ID=\"1\"",
"Map Append=\"false\" AutoFit=\"false\" ID=\"5\""
};
for(String condition : regexConditions){
Pattern pattern = Pattern.compile(condition);
Matcher matcher = pattern.matcher(xml);
assertTrue(matcher.find());
}
}
}
}
}

View File

@ -0,0 +1,84 @@
/* ====================================================================
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.model;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.xssf.XSSFTestDataSamples;
import org.apache.poi.xssf.usermodel.XSSFMap;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSchema;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTMapInfo;
import org.w3c.dom.Node;
import junit.framework.TestCase;
/**
* @author Roberto Manicardi
*/
public class TestMapInfo extends TestCase {
public void testMapInfoExists() throws Exception {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("CustomXmlMappings.xlsx");
MapInfo mapInfo = null;
SingleXmlCells singleXMLCells = null;
for (POIXMLDocumentPart p : wb.getRelations()) {
if (p instanceof MapInfo) {
mapInfo = (MapInfo) p;
CTMapInfo ctMapInfo = mapInfo.getCTMapInfo();
assertNotNull(ctMapInfo);
CTSchema[] schemas = ctMapInfo.getSchemaArray();
assertEquals(1, schemas.length);
for (XSSFMap map : mapInfo) {
Node xmlSchema = map.getSchema();
assertNotNull(xmlSchema);
}
}
}
XSSFSheet sheet1 = wb.getSheetAt(0);
for (POIXMLDocumentPart p : sheet1.getRelations()) {
if (p instanceof SingleXmlCells) {
singleXMLCells = (SingleXmlCells) p;
}
}
assertNotNull(mapInfo);
assertNotNull(singleXMLCells);
}
}