diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 7e764b2c6..73abd537d 100644 --- a/src/documentation/content/xdocs/status.xml +++ b/src/documentation/content/xdocs/status.xml @@ -33,8 +33,9 @@ - 45556 - Fixed ExtractorFactory to support .xltx and .dotx files + 47517 - Fixed ExtractorFactory to support .xltx and .dotx files 45556 - Support for extraction of footnotes from docx files + 45555 - Support for extraction of endnotes from docx files 47520 - Initial support for custom XML mappings in XSSF 47460 - Fixed NPE when retrieving core properties from a newly created workbook 47498 - Fixed HyperlinkRecord to properly handle URL monikers diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java index 2e86e79c7..dc08bdcce 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java @@ -53,6 +53,7 @@ public class XWPFDocument extends POIXMLDocument { protected List paragraphs; protected List tables; protected Map footnotes; + protected Map endnotes; /** Handles the joy of different headers/footers for different pages */ private XWPFHeaderFooterPolicy headerFooterPolicy; @@ -81,6 +82,7 @@ public class XWPFDocument extends POIXMLDocument { paragraphs = new ArrayList(); tables= new ArrayList(); footnotes = new HashMap(); + endnotes = new HashMap(); try { DocumentDocument doc = DocumentDocument.Factory.parse(getPackagePart().getInputStream()); @@ -143,6 +145,12 @@ public class XWPFDocument extends POIXMLDocument { for(CTFtnEdn ctFtnEdn : footnotesDocument.getFootnotes().getFootnoteArray()) { footnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn)); } + } else if (relation.equals(XWPFRelation.ENDNOTE.getRelation())){ + EndnotesDocument endnotesDocument = EndnotesDocument.Factory.parse(p.getPackagePart().getInputStream()); + + for(CTFtnEdn ctFtnEdn : endnotesDocument.getEndnotes().getEndnoteArray()) { + endnotes.put(ctFtnEdn.getId().intValue(), new XWPFFootnote(this, ctFtnEdn)); + } } } } @@ -218,6 +226,10 @@ public class XWPFDocument extends POIXMLDocument { return footnotes.get(id); } + public XWPFFootnote getEndnoteByID(int id) { + return endnotes.get(id); + } + public Collection getFootnotes() { return footnotes == null ? new ArrayList() : footnotes.values(); } diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java index 1ddda9d4f..81a4add75 100644 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFParagraph.java @@ -93,7 +93,10 @@ public class XWPFParagraph { if (o instanceof CTFtnEdnRef) { CTFtnEdnRef ftn = (CTFtnEdnRef) o; footnoteText.append("[").append(ftn.getId()).append(": "); - XWPFFootnote footnote = document.getFootnoteByID(ftn.getId().intValue()); + XWPFFootnote footnote = + ftn.getDomNode().getLocalName().equals("footnoteReference") ? + document.getFootnoteByID(ftn.getId().intValue()) : + document.getEndnoteByID(ftn.getId().intValue()); boolean first = true; for (XWPFParagraph p : footnote.getParagraphs()) { diff --git a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java index c1b91bb07..d28915e35 100755 --- a/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java +++ b/src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFRelation.java @@ -112,6 +112,12 @@ public final class XWPFRelation extends POIXMLRelation { null, null ); + public static final XWPFRelation ENDNOTE = new XWPFRelation( + null, + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes", + null, + null + ); private XWPFRelation(String type, String rel, String defaultName, Class cls) { diff --git a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java index 1527e562b..e923c40fc 100644 --- a/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java +++ b/src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java @@ -185,7 +185,15 @@ public class TestXWPFWordExtractor extends TestCase { assertTrue("Unable to find expected word in text\n" + text, text.contains("test phrase")); } - //TODO use the same logic as in HSSFTestDataSamples + public void testEndnotes() throws Exception { + XWPFDocument doc = open("endnotes.docx"); + XWPFWordExtractor extractor = new XWPFWordExtractor(doc); + + assertTrue(extractor.getText().contains("XXX")); + } + + + //TODO use the same logic for opening test files as in HSSFTestDataSamples private XWPFDocument open(String sampleFileName) throws IOException { File file = new File( System.getProperty("HWPF.testdata.path"), sampleFileName); diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/data/endnotes.docx b/src/scratchpad/testcases/org/apache/poi/hwpf/data/endnotes.docx new file mode 100755 index 000000000..a5db3492c Binary files /dev/null and b/src/scratchpad/testcases/org/apache/poi/hwpf/data/endnotes.docx differ