From 92f5bf236020aae397dbdb0af40b1c28c0b82960 Mon Sep 17 00:00:00 2001 From: Yegor Kozlov Date: Sat, 18 Jul 2009 09:28:38 +0000 Subject: [PATCH] Support for extraction of endnotes from docx files git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@795329 13f79535-47bb-0310-9956-ffa450edef68 --- src/documentation/content/xdocs/status.xml | 3 ++- .../apache/poi/xwpf/usermodel/XWPFDocument.java | 12 ++++++++++++ .../poi/xwpf/usermodel/XWPFParagraph.java | 5 ++++- .../apache/poi/xwpf/usermodel/XWPFRelation.java | 6 ++++++ .../xwpf/extractor/TestXWPFWordExtractor.java | 10 +++++++++- .../org/apache/poi/hwpf/data/endnotes.docx | Bin 0 -> 13553 bytes 6 files changed, 33 insertions(+), 3 deletions(-) create mode 100755 src/scratchpad/testcases/org/apache/poi/hwpf/data/endnotes.docx diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml index 7e764b2c68..73abd537df 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 2e86e79c7d..dc08bdcce7 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 1ddda9d4fc..81a4add75e 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 c1b91bb07a..d28915e357 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 1527e562b7..e923c40fcb 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 0000000000000000000000000000000000000000..a5db3492c3f16398daff0065fdfd7b87cd9a5727 GIT binary patch literal 13553 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