Patch from bug #51486 from Mike McEuen (with a few whitespace tweaks) - XWPF support for adding footnotes
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1144308 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
361fe3eb42
commit
7f5bd44d98
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.8-beta4" date="2011-??-??">
|
<release version="3.8-beta4" date="2011-??-??">
|
||||||
|
<action dev="poi-developers" type="add">51486 - XWPF support for adding new footnotes</action>
|
||||||
<action dev="poi-developers" type="fix">48065 - Problems with save output of HWPF (losing formatting)</action>
|
<action dev="poi-developers" type="fix">48065 - Problems with save output of HWPF (losing formatting)</action>
|
||||||
<action dev="poi-developers" type="fix">47563 - Exception when working with table</action>
|
<action dev="poi-developers" type="fix">47563 - Exception when working with table</action>
|
||||||
<action dev="poi-developers" type="fix">47287 - StringIndexOutOfBoundsException in CharacterRun.replaceText()</action>
|
<action dev="poi-developers" type="fix">47287 - StringIndexOutOfBoundsException in CharacterRun.replaceText()</action>
|
||||||
|
@ -100,10 +100,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
protected List<IBodyElement> bodyElements = new ArrayList<IBodyElement>();
|
protected List<IBodyElement> bodyElements = new ArrayList<IBodyElement>();
|
||||||
protected List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
|
protected List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
|
||||||
protected Map<Long, List<XWPFPictureData>> packagePictures = new HashMap<Long, List<XWPFPictureData>>();
|
protected Map<Long, List<XWPFPictureData>> packagePictures = new HashMap<Long, List<XWPFPictureData>>();
|
||||||
protected Map<Integer, XWPFFootnote> footnotes = new HashMap<Integer, XWPFFootnote>();
|
|
||||||
protected Map<Integer, XWPFFootnote> endnotes = new HashMap<Integer, XWPFFootnote>();
|
protected Map<Integer, XWPFFootnote> endnotes = new HashMap<Integer, XWPFFootnote>();
|
||||||
protected XWPFNumbering numbering;
|
protected XWPFNumbering numbering;
|
||||||
protected XWPFStyles styles;
|
protected XWPFStyles styles;
|
||||||
|
protected XWPFFootnotes footnotes;
|
||||||
|
|
||||||
/** Handles the joy of different headers/footers for different pages */
|
/** Handles the joy of different headers/footers for different pages */
|
||||||
private XWPFHeaderFooterPolicy headerFooterPolicy;
|
private XWPFHeaderFooterPolicy headerFooterPolicy;
|
||||||
@ -216,9 +216,11 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
String relation = p.getPackageRelationship().getRelationshipType();
|
String relation = p.getPackageRelationship().getRelationshipType();
|
||||||
if (relation.equals(XWPFRelation.FOOTNOTE.getRelation())) {
|
if (relation.equals(XWPFRelation.FOOTNOTE.getRelation())) {
|
||||||
FootnotesDocument footnotesDocument = FootnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
|
FootnotesDocument footnotesDocument = FootnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
|
||||||
|
this.footnotes = (XWPFFootnotes)p;
|
||||||
|
this.footnotes.onDocumentRead();
|
||||||
|
|
||||||
for(CTFtnEdn ctFtnEdn : footnotesDocument.getFootnotes().getFootnoteList()) {
|
for(CTFtnEdn ctFtnEdn : footnotesDocument.getFootnotes().getFootnoteList()) {
|
||||||
footnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn));
|
footnotes.addFootnote(ctFtnEdn);
|
||||||
}
|
}
|
||||||
} else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())){
|
} else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())){
|
||||||
EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
|
EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream());
|
||||||
@ -349,15 +351,15 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public XWPFFootnote getFootnoteByID(int id) {
|
public XWPFFootnote getFootnoteByID(int id) {
|
||||||
return footnotes.get(id);
|
return footnotes.getFootnoteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public XWPFFootnote getEndnoteByID(int id) {
|
public XWPFFootnote getEndnoteByID(int id) {
|
||||||
return endnotes.get(id);
|
return endnotes.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<XWPFFootnote> getFootnotes() {
|
public List<XWPFFootnote> getFootnotes() {
|
||||||
return Collections.unmodifiableCollection(footnotes == null ? new ArrayList<XWPFFootnote>() : footnotes.values());
|
return footnotes.getFootnotesList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public XWPFHyperlink[] getHyperlinks() {
|
public XWPFHyperlink[] getHyperlinks() {
|
||||||
@ -745,14 +747,30 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
|
|||||||
return styles;
|
return styles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an empty footnotes element for the document if one does not already exist
|
||||||
|
* @return footnotes
|
||||||
|
*/
|
||||||
|
public XWPFFootnotes createFootnotes() {
|
||||||
|
if(footnotes == null) {
|
||||||
|
FootnotesDocument footnotesDoc = FootnotesDocument.Factory.newInstance();
|
||||||
|
|
||||||
public XWPFFootnote addEndnote(CTFtnEdn note) {
|
XWPFRelation relation = XWPFRelation.FOOTNOTE;
|
||||||
XWPFFootnote footnote = new XWPFFootnote(this, note);
|
int i = getRelationIndex(relation);
|
||||||
footnotes.put(note.getId().intValue(), footnote);
|
|
||||||
return footnote;
|
XWPFFootnotes wrapper = (XWPFFootnotes)createRelationship(relation, XWPFFactory.getInstance(), i);
|
||||||
|
wrapper.setFootnotes(footnotesDoc.addNewFootnotes());
|
||||||
|
footnotes = wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
return footnotes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
public XWPFFootnote addFootnote(CTFtnEdn note) {
|
||||||
|
return footnotes.addFootnote(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XWPFFootnote addEndnote(CTFtnEdn note) {
|
||||||
XWPFFootnote endnote = new XWPFFootnote(this, note);
|
XWPFFootnote endnote = new XWPFFootnote(this, note);
|
||||||
endnotes.put(note.getId().intValue(), endnote);
|
endnotes.put(note.getId().intValue(), endnote);
|
||||||
return endnote;
|
return endnote;
|
||||||
|
@ -20,11 +20,31 @@ import java.util.ArrayList;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
|
import org.apache.xmlbeans.XmlCursor;
|
||||||
|
import org.apache.xmlbeans.XmlObject;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTbl;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
|
||||||
|
|
||||||
public class XWPFFootnote implements Iterable<XWPFParagraph> {
|
public class XWPFFootnote implements Iterable<XWPFParagraph>,IBody {
|
||||||
private List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
|
private List<XWPFParagraph> paragraphs = new ArrayList<XWPFParagraph>();
|
||||||
|
private List<XWPFTable> tables= new ArrayList<XWPFTable>();
|
||||||
|
private List<XWPFPictureData> pictures = new ArrayList<XWPFPictureData>();
|
||||||
|
private List<IBodyElement> bodyElements = new ArrayList<IBodyElement>();
|
||||||
|
|
||||||
|
private CTFtnEdn ctFtnEdn;
|
||||||
|
private XWPFFootnotes footnotes;
|
||||||
|
|
||||||
|
public XWPFFootnote(CTFtnEdn note, XWPFFootnotes xFootnotes) {
|
||||||
|
footnotes = xFootnotes;
|
||||||
|
ctFtnEdn = note;
|
||||||
|
for (CTP p : ctFtnEdn.getPList()) {
|
||||||
|
paragraphs.add(new XWPFParagraph(p, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public XWPFFootnote(XWPFDocument document, CTFtnEdn body) {
|
public XWPFFootnote(XWPFDocument document, CTFtnEdn body) {
|
||||||
for (CTP p : body.getPList()) {
|
for (CTP p : body.getPList()) {
|
||||||
@ -40,4 +60,276 @@ public class XWPFFootnote implements Iterable<XWPFParagraph> {
|
|||||||
return paragraphs.iterator();
|
return paragraphs.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<XWPFTable> getTables() {
|
||||||
|
return tables;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<XWPFPictureData> getPictures() {
|
||||||
|
return pictures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IBodyElement> getBodyElements() {
|
||||||
|
return bodyElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CTFtnEdn getCTFtnEdn() {
|
||||||
|
return ctFtnEdn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCTFtnEdn(CTFtnEdn footnote) {
|
||||||
|
ctFtnEdn = footnote;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param position in table array
|
||||||
|
* @return The table at position pos
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTableArray(int)
|
||||||
|
*/
|
||||||
|
public XWPFTable getTableArray(int pos) {
|
||||||
|
if(pos > 0 && pos < tables.size()){
|
||||||
|
return tables.get(pos);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inserts an existing XWPFTable to the arrays bodyElements and tables
|
||||||
|
* @param pos
|
||||||
|
* @param table
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertTable(int pos, XWPFTable table)
|
||||||
|
*/
|
||||||
|
public void insertTable(int pos, XWPFTable table) {
|
||||||
|
bodyElements.add(pos, table);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < ctFtnEdn.getTblList().size(); i++) {
|
||||||
|
CTTbl tbl = ctFtnEdn.getTblArray(i);
|
||||||
|
if(tbl == table.getCTTbl()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tables.add(i, table);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if there is a corresponding {@link XWPFTable} of the parameter ctTable in the tableList of this header
|
||||||
|
* the method will return this table
|
||||||
|
* if there is no corresponding {@link XWPFTable} the method will return null
|
||||||
|
* @param ctTable
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTable(CTTbl ctTable)
|
||||||
|
*/
|
||||||
|
public XWPFTable getTable(CTTbl ctTable){
|
||||||
|
for (XWPFTable table : tables) {
|
||||||
|
if(table==null)
|
||||||
|
return null;
|
||||||
|
if(table.getCTTbl().equals(ctTable))
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if there is a corresponding {@link XWPFParagraph} of the parameter ctTable in the paragraphList of this header or footer
|
||||||
|
* the method will return this paragraph
|
||||||
|
* if there is no corresponding {@link XWPFParagraph} the method will return null
|
||||||
|
* @param p is instance of CTP and is searching for an XWPFParagraph
|
||||||
|
* @return null if there is no XWPFParagraph with an corresponding CTPparagraph in the paragraphList of this header or footer
|
||||||
|
* XWPFParagraph with the correspondig CTP p
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraph(CTP p)
|
||||||
|
*/
|
||||||
|
public XWPFParagraph getParagraph(CTP p){
|
||||||
|
for (XWPFParagraph paragraph : paragraphs) {
|
||||||
|
if(paragraph.getCTP().equals(p))
|
||||||
|
return paragraph;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the paragraph that holds
|
||||||
|
* the text of the header or footer.
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getParagraphArray(int pos)
|
||||||
|
*/
|
||||||
|
public XWPFParagraph getParagraphArray(int pos) {
|
||||||
|
|
||||||
|
return paragraphs.get(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the TableCell which belongs to the TableCell
|
||||||
|
* @param cell
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getTableCell(CTTc cell)
|
||||||
|
*/
|
||||||
|
public XWPFTableCell getTableCell(CTTc cell) {
|
||||||
|
XmlCursor cursor = cell.newCursor();
|
||||||
|
cursor.toParent();
|
||||||
|
XmlObject o = cursor.getObject();
|
||||||
|
if(!(o instanceof CTRow)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CTRow row = (CTRow)o;
|
||||||
|
cursor.toParent();
|
||||||
|
o = cursor.getObject();
|
||||||
|
cursor.dispose();
|
||||||
|
if(! (o instanceof CTTbl)){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
CTTbl tbl = (CTTbl) o;
|
||||||
|
XWPFTable table = getTable(tbl);
|
||||||
|
if(table == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
XWPFTableRow tableRow = table.getRow(row);
|
||||||
|
if(row == null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tableRow.getTableCell(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verifies that cursor is on the right position
|
||||||
|
* @param cursor
|
||||||
|
*/
|
||||||
|
private boolean isCursorInFtn(XmlCursor cursor) {
|
||||||
|
XmlCursor verify = cursor.newCursor();
|
||||||
|
verify.toParent();
|
||||||
|
if(verify.getObject() == this.ctFtnEdn){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public POIXMLDocumentPart getOwner(){
|
||||||
|
return footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param cursor
|
||||||
|
* @return the inserted table
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewTbl(XmlCursor cursor)
|
||||||
|
*/
|
||||||
|
public XWPFTable insertNewTbl(XmlCursor cursor) {
|
||||||
|
if(isCursorInFtn(cursor)){
|
||||||
|
String uri = CTTbl.type.getName().getNamespaceURI();
|
||||||
|
String localPart = "tbl";
|
||||||
|
cursor.beginElement(localPart,uri);
|
||||||
|
cursor.toParent();
|
||||||
|
CTTbl t = (CTTbl)cursor.getObject();
|
||||||
|
XWPFTable newT = new XWPFTable(t, this);
|
||||||
|
cursor.removeXmlContents();
|
||||||
|
XmlObject o = null;
|
||||||
|
while(!(o instanceof CTTbl)&&(cursor.toPrevSibling())){
|
||||||
|
o = cursor.getObject();
|
||||||
|
}
|
||||||
|
if(!(o instanceof CTTbl)){
|
||||||
|
tables.add(0, newT);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
int pos = tables.indexOf(getTable((CTTbl)o))+1;
|
||||||
|
tables.add(pos,newT);
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
cursor = t.newCursor();
|
||||||
|
while(cursor.toPrevSibling()){
|
||||||
|
o =cursor.getObject();
|
||||||
|
if(o instanceof CTP || o instanceof CTTbl)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
bodyElements.add(i, newT);
|
||||||
|
cursor = t.newCursor();
|
||||||
|
cursor.toEndToken();
|
||||||
|
return newT;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a new paragraph at position of the cursor
|
||||||
|
* @param cursor
|
||||||
|
* @return the inserted paragraph
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#insertNewParagraph(XmlCursor cursor)
|
||||||
|
*/
|
||||||
|
public XWPFParagraph insertNewParagraph(XmlCursor cursor){
|
||||||
|
if(isCursorInFtn(cursor)){
|
||||||
|
String uri = CTP.type.getName().getNamespaceURI();
|
||||||
|
String localPart = "p";
|
||||||
|
cursor.beginElement(localPart,uri);
|
||||||
|
cursor.toParent();
|
||||||
|
CTP p = (CTP)cursor.getObject();
|
||||||
|
XWPFParagraph newP = new XWPFParagraph(p, this);
|
||||||
|
XmlObject o = null;
|
||||||
|
while(!(o instanceof CTP)&&(cursor.toPrevSibling())){
|
||||||
|
o = cursor.getObject();
|
||||||
|
}
|
||||||
|
if((!(o instanceof CTP)) || (CTP)o == p){
|
||||||
|
paragraphs.add(0, newP);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
int pos = paragraphs.indexOf(getParagraph((CTP)o))+1;
|
||||||
|
paragraphs.add(pos,newP);
|
||||||
|
}
|
||||||
|
int i=0;
|
||||||
|
cursor.toCursor(p.newCursor());
|
||||||
|
while(cursor.toPrevSibling()){
|
||||||
|
o =cursor.getObject();
|
||||||
|
if(o instanceof CTP || o instanceof CTTbl)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
bodyElements.add(i, newP);
|
||||||
|
cursor.toCursor(p.newCursor());
|
||||||
|
cursor.toEndToken();
|
||||||
|
return newP;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a new table to the end of the footnote
|
||||||
|
* @param table
|
||||||
|
* @return the added XWPFTable
|
||||||
|
*/
|
||||||
|
public XWPFTable addNewTbl(CTTbl table) {
|
||||||
|
CTTbl newTable = ctFtnEdn.addNewTbl();
|
||||||
|
newTable.set(table);
|
||||||
|
XWPFTable xTable = new XWPFTable(newTable, this);
|
||||||
|
tables.add(xTable);
|
||||||
|
return xTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a new paragraph to the end of the footnote
|
||||||
|
* @param paragraph
|
||||||
|
* @return the added XWPFParagraph
|
||||||
|
*/
|
||||||
|
public XWPFParagraph addNewParagraph(CTP paragraph) {
|
||||||
|
CTP newPara = ctFtnEdn.addNewP();
|
||||||
|
newPara.set(paragraph);
|
||||||
|
XWPFParagraph xPara = new XWPFParagraph(newPara, this);
|
||||||
|
paragraphs.add(xPara);
|
||||||
|
return xPara;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getXWPFDocument()
|
||||||
|
*/
|
||||||
|
public XWPFDocument getXWPFDocument() {
|
||||||
|
return footnotes.getXWPFDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the Part, to which the body belongs, which you need for adding relationship to other parts
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
||||||
|
*/
|
||||||
|
public POIXMLDocumentPart getPart() {
|
||||||
|
return footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the PartType of the body
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPartType()
|
||||||
|
*/
|
||||||
|
public BodyType getPartType() {
|
||||||
|
return BodyType.FOOTNOTE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
161
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java
Normal file
161
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFFootnotes.java
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.xwpf.usermodel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
|
import org.apache.poi.POIXMLException;
|
||||||
|
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackagePart;
|
||||||
|
import org.apache.poi.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFootnotes;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.FootnotesDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks after the collection of Footnotes for a document
|
||||||
|
*
|
||||||
|
* @author Mike McEuen (mceuen@hp.com)
|
||||||
|
*/
|
||||||
|
public class XWPFFootnotes extends POIXMLDocumentPart {
|
||||||
|
private List<XWPFFootnote> listFootnote = new ArrayList<XWPFFootnote>();
|
||||||
|
private CTFootnotes ctFootnotes;
|
||||||
|
|
||||||
|
protected XWPFDocument document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct XWPFFootnotes from a package part
|
||||||
|
*
|
||||||
|
* @param part the package part holding the data of the footnotes,
|
||||||
|
* @param rel the package relationship of type "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes"
|
||||||
|
*/
|
||||||
|
public XWPFFootnotes(PackagePart part, PackageRelationship rel) throws IOException, OpenXML4JException{
|
||||||
|
super(part, rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct XWPFFootnotes from scratch for a new document.
|
||||||
|
*/
|
||||||
|
public XWPFFootnotes() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read document
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void onDocumentRead () throws IOException {
|
||||||
|
FootnotesDocument notesDoc;
|
||||||
|
try {
|
||||||
|
InputStream is = getPackagePart().getInputStream();
|
||||||
|
notesDoc = FootnotesDocument.Factory.parse(is);
|
||||||
|
ctFootnotes = notesDoc.getFootnotes();
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new POIXMLException();
|
||||||
|
}
|
||||||
|
|
||||||
|
//get any Footnote
|
||||||
|
for(CTFtnEdn note : ctFootnotes.getFootnoteList()) {
|
||||||
|
listFootnote.add(new XWPFFootnote(note, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void commit() throws IOException {
|
||||||
|
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
|
||||||
|
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTFootnotes.type.getName().getNamespaceURI(), "footnotes"));
|
||||||
|
Map<String,String> map = new HashMap<String,String>();
|
||||||
|
map.put("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "r");
|
||||||
|
map.put("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "w");
|
||||||
|
xmlOptions.setSaveSuggestedPrefixes(map);
|
||||||
|
PackagePart part = getPackagePart();
|
||||||
|
OutputStream out = part.getOutputStream();
|
||||||
|
ctFootnotes.save(out, xmlOptions);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<XWPFFootnote> getFootnotesList() {
|
||||||
|
return listFootnote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XWPFFootnote getFootnoteById(int id) {
|
||||||
|
for(XWPFFootnote note : listFootnote) {
|
||||||
|
if(note.getCTFtnEdn().getId().intValue() == id)
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ctFootnotes
|
||||||
|
* @param footnotes
|
||||||
|
*/
|
||||||
|
public void setFootnotes(CTFootnotes footnotes) {
|
||||||
|
ctFootnotes = footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add an XWPFFootnote to the document
|
||||||
|
* @param footnote
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void addFootnote(XWPFFootnote footnote){
|
||||||
|
listFootnote.add(footnote);
|
||||||
|
ctFootnotes.addNewFootnote().set(footnote.getCTFtnEdn());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add a footnote to the document
|
||||||
|
* @param footnote
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public XWPFFootnote addFootnote(CTFtnEdn note){
|
||||||
|
CTFtnEdn newNote = ctFootnotes.addNewFootnote();
|
||||||
|
newNote.set(note);
|
||||||
|
XWPFFootnote xNote = new XWPFFootnote(newNote, this);
|
||||||
|
listFootnote.add(xNote);
|
||||||
|
return xNote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setXWPFDocument(XWPFDocument doc) {
|
||||||
|
document = doc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.apache.poi.xwpf.usermodel.IBody#getPart()
|
||||||
|
*/
|
||||||
|
public XWPFDocument getXWPFDocument() {
|
||||||
|
if ( document != null) {
|
||||||
|
return document;
|
||||||
|
} else {
|
||||||
|
return (XWPFDocument)getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}//end class
|
||||||
|
|
@ -498,6 +498,10 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo
|
|||||||
return tableRow.getTableCell(cell);
|
return tableRow.getTableCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setXWPFDocument(XWPFDocument doc) {
|
||||||
|
document = doc;
|
||||||
|
}
|
||||||
|
|
||||||
public XWPFDocument getXWPFDocument() {
|
public XWPFDocument getXWPFDocument() {
|
||||||
if (document!=null) {
|
if (document!=null) {
|
||||||
return document;
|
return document;
|
||||||
|
@ -114,10 +114,10 @@ public final class XWPFRelation extends POIXMLRelation {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
public static final XWPFRelation FOOTNOTE = new XWPFRelation(
|
public static final XWPFRelation FOOTNOTE = new XWPFRelation(
|
||||||
null,
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml",
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
|
||||||
null,
|
"/word/footnotes.xml",
|
||||||
null
|
XWPFFootnotes.class
|
||||||
);
|
);
|
||||||
public static final XWPFRelation ENDNOTE = new XWPFRelation(
|
public static final XWPFRelation ENDNOTE = new XWPFRelation(
|
||||||
null,
|
null,
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.xwpf.usermodel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.lang.String;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.apache.poi.xwpf.XWPFTestDataSamples;
|
||||||
|
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFtnEdn;
|
||||||
|
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STFtnEdn;
|
||||||
|
|
||||||
|
public class TestXWPFFootnotes extends TestCase {
|
||||||
|
|
||||||
|
public void testAddFootnotesToDocument() throws IOException{
|
||||||
|
XWPFDocument docOut = new XWPFDocument();
|
||||||
|
|
||||||
|
BigInteger noteId = BigInteger.valueOf(1);
|
||||||
|
|
||||||
|
XWPFFootnotes footnotes = docOut.createFootnotes();
|
||||||
|
CTFtnEdn ctNote = CTFtnEdn.Factory.newInstance();
|
||||||
|
ctNote.setId(noteId);
|
||||||
|
ctNote.setType(STFtnEdn.NORMAL);
|
||||||
|
footnotes.addFootnote(ctNote);
|
||||||
|
|
||||||
|
XWPFDocument docIn = XWPFTestDataSamples.writeOutAndReadBack(docOut);
|
||||||
|
|
||||||
|
XWPFFootnote note = docIn.getFootnoteByID(noteId.intValue());
|
||||||
|
assertEquals(note.getCTFtnEdn().getType(), STFtnEdn.NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user