Add handling of alternate content elements

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1803397 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2017-07-29 23:08:15 +00:00
parent 73d041eb7c
commit 1c1c384c16
1 changed files with 56 additions and 15 deletions

View File

@ -34,6 +34,7 @@ import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; 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.openxml4j.opc.PackageNamespaces;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackagePartName;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
@ -47,9 +48,14 @@ import org.apache.poi.sl.usermodel.Sheet;
import org.apache.poi.util.Beta; import org.apache.poi.util.Beta;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal; import org.apache.poi.util.Removal;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions; import org.apache.xmlbeans.XmlOptions;
import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData; import org.openxmlformats.schemas.presentationml.x2006.main.CTCommonSlideData;
import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector; import org.openxmlformats.schemas.presentationml.x2006.main.CTConnector;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame; import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
@ -61,6 +67,8 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
@Beta @Beta
public abstract class XSLFSheet extends POIXMLDocumentPart public abstract class XSLFSheet extends POIXMLDocumentPart
implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> { implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
private static POILogger LOG = POILogFactory.getLogger(XSLFSheet.class);
private XSLFCommonSlideData _commonSlideData; private XSLFCommonSlideData _commonSlideData;
private XSLFDrawing _drawing; private XSLFDrawing _drawing;
private List<XSLFShape> _shapes; private List<XSLFShape> _shapes;
@ -98,21 +106,44 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
protected static List<XSLFShape> buildShapes(CTGroupShape spTree, XSLFSheet sheet){ protected static List<XSLFShape> buildShapes(CTGroupShape spTree, XSLFSheet sheet){
List<XSLFShape> shapes = new ArrayList<XSLFShape>(); List<XSLFShape> shapes = new ArrayList<XSLFShape>();
for(XmlObject ch : spTree.selectPath("*")){ XmlCursor cur = spTree.newCursor();
if(ch instanceof CTShape){ // simple shape try {
XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, sheet); for (boolean b=cur.toFirstChild();b;b=cur.toNextSibling()) {
shapes.add(shape); XmlObject ch = cur.getObject();
} else if (ch instanceof CTGroupShape){ if(ch instanceof CTShape){
shapes.add(new XSLFGroupShape((CTGroupShape)ch, sheet)); // simple shape
} else if (ch instanceof CTConnector){ XSLFAutoShape shape = XSLFAutoShape.create((CTShape)ch, sheet);
shapes.add(new XSLFConnectorShape((CTConnector)ch, sheet)); shapes.add(shape);
} else if (ch instanceof CTPicture){ } else if (ch instanceof CTGroupShape){
shapes.add(new XSLFPictureShape((CTPicture)ch, sheet)); shapes.add(new XSLFGroupShape((CTGroupShape)ch, sheet));
} else if (ch instanceof CTGraphicalObjectFrame){ } else if (ch instanceof CTConnector){
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, sheet); shapes.add(new XSLFConnectorShape((CTConnector)ch, sheet));
shapes.add(shape); } else if (ch instanceof CTPicture){
shapes.add(new XSLFPictureShape((CTPicture)ch, sheet));
} else if (ch instanceof CTGraphicalObjectFrame){
XSLFGraphicFrame shape = XSLFGraphicFrame.create((CTGraphicalObjectFrame)ch, sheet);
shapes.add(shape);
} else if (ch instanceof XmlAnyTypeImpl) {
// TODO: the link of the XLSF classes to the xml beans objects will
// be broken, when the elements are parsed a second time.
// Unfortunately, the xml schema type can't be set of the alternate
// content element
cur.push();
if (cur.toChild(PackageNamespaces.MARKUP_COMPATIBILITY, "Choice") && cur.toFirstChild()) {
try {
CTGroupShape grp = CTGroupShape.Factory.parse(cur.newXMLStreamReader());
shapes.addAll(buildShapes(grp, sheet));
} catch (XmlException e) {
LOG.log(POILogger.DEBUG, "unparsable alternate content", e);
}
}
cur.pop();
}
} }
} finally {
cur.dispose();
} }
return shapes; return shapes;
} }
@ -263,10 +294,12 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
* *
* @return an iterator over the shapes in this sheet * @return an iterator over the shapes in this sheet
*/ */
@Override
public Iterator<XSLFShape> iterator(){ public Iterator<XSLFShape> iterator(){
return getShapes().iterator(); return getShapes().iterator();
} }
@Override
public void addShape(XSLFShape shape) { public void addShape(XSLFShape shape) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Adding a shape from a different container is not supported -" "Adding a shape from a different container is not supported -"
@ -283,6 +316,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
* @throws IllegalArgumentException if the type of the specified shape * @throws IllegalArgumentException if the type of the specified shape
* is incompatible with this sheet (optional) * is incompatible with this sheet (optional)
*/ */
@Override
public boolean removeShape(XSLFShape xShape) { public boolean removeShape(XSLFShape xShape) {
XmlObject obj = xShape.getXmlObject(); XmlObject obj = xShape.getXmlObject();
CTGroupShape spTree = getSpTree(); CTGroupShape spTree = getSpTree();
@ -308,6 +342,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
* Removes all of the elements from this container (optional operation). * Removes all of the elements from this container (optional operation).
* The container will be empty after this call returns. * The container will be empty after this call returns.
*/ */
@Override
public void clear() { public void clear() {
List<XSLFShape> shapes = new ArrayList<XSLFShape>(getShapes()); List<XSLFShape> shapes = new ArrayList<XSLFShape>(getShapes());
for(XSLFShape shape : shapes){ for(XSLFShape shape : shapes){
@ -322,12 +357,15 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
XmlObject root = getXmlObject(); XmlObject root = getXmlObject();
XmlObject[] sp = root.selectPath( XmlObject[] sp = root.selectPath(
"declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:spTree"); "declare namespace p='http://schemas.openxmlformats.org/presentationml/2006/main' .//*/p:spTree");
if(sp.length == 0) throw new IllegalStateException("CTGroupShape was not found"); if(sp.length == 0) {
throw new IllegalStateException("CTGroupShape was not found");
}
_spTree = (CTGroupShape)sp[0]; _spTree = (CTGroupShape)sp[0];
} }
return _spTree; return _spTree;
} }
@Override
protected final void commit() throws IOException { protected final void commit() throws IOException {
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS); XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
String docName = getRootElementName(); String docName = getRootElementName();
@ -442,7 +480,9 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
XSLFSimpleShape getPlaceholder(CTPlaceholder ph) { XSLFSimpleShape getPlaceholder(CTPlaceholder ph) {
XSLFSimpleShape shape = null; XSLFSimpleShape shape = null;
if(ph.isSetIdx()) shape = getPlaceholderById((int)ph.getIdx()); if(ph.isSetIdx()) {
shape = getPlaceholderById((int)ph.getIdx());
}
if (shape == null && ph.isSetType()) { if (shape == null && ph.isSetType()) {
shape = getPlaceholderByType(ph.getType().intValue()); shape = getPlaceholderByType(ph.getType().intValue());
@ -520,6 +560,7 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
* Sheets that support the notion of master (slide, slideLayout) should override it and * Sheets that support the notion of master (slide, slideLayout) should override it and
* check this setting in the sheet XML * check this setting in the sheet XML
*/ */
@Override
public boolean getFollowMasterGraphics(){ public boolean getFollowMasterGraphics(){
return false; return false;
} }