Author: nick
Date: Thu Sep 22 11:06:41 2011
New Revision: 1174056
URL: http://svn.apache.org/viewvc?rev=1174056&view=rev
Log:
TIKA-727 Improve the HSLF PPT parser by using HSLF usermodel classes to
generate more specific XHTML events
Modified:
tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
Modified:
tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
URL:
http://svn.apache.org/viewvc/tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java?rev=1174056&r1=1174055&r2=1174056&view=diff
==============================================================================
---
tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
(original)
+++
tika/trunk/tika-parsers/src/main/java/org/apache/tika/parser/microsoft/HSLFExtractor.java
Thu Sep 22 11:06:41 2011
@@ -17,11 +17,19 @@
package org.apache.tika.parser.microsoft;
import java.io.IOException;
-import java.util.List;
+import java.util.HashSet;
-import org.apache.poi.hslf.extractor.PowerPointExtractor;
+import org.apache.poi.hslf.HSLFSlideShow;
+import org.apache.poi.hslf.model.Comment;
+import org.apache.poi.hslf.model.HeadersFooters;
+import org.apache.poi.hslf.model.MasterSheet;
+import org.apache.poi.hslf.model.Notes;
import org.apache.poi.hslf.model.OLEShape;
+import org.apache.poi.hslf.model.Shape;
+import org.apache.poi.hslf.model.Slide;
+import org.apache.poi.hslf.model.TextRun;
import org.apache.poi.hslf.usermodel.ObjectData;
+import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.tika.exception.TikaException;
import org.apache.tika.io.TikaInputStream;
@@ -30,40 +38,161 @@ import org.apache.tika.sax.XHTMLContentH
import org.xml.sax.SAXException;
public class HSLFExtractor extends AbstractPOIFSExtractor {
- public HSLFExtractor(ParseContext context) {
- super(context);
- }
-
- protected void parse(
- NPOIFSFileSystem filesystem, XHTMLContentHandler xhtml)
- throws IOException, SAXException, TikaException {
- PowerPointExtractor powerPointExtractor =
- new PowerPointExtractor(filesystem);
- powerPointExtractor.setSlidesByDefault(true);
- powerPointExtractor.setNotesByDefault(true);
- powerPointExtractor.setCommentsByDefault(true);
- powerPointExtractor.setMasterByDefault(true);
-
- xhtml.element("p", powerPointExtractor.getText());
-
- List<OLEShape> shapeList = powerPointExtractor.getOLEShapes();
- for (OLEShape shape : shapeList) {
- ObjectData data = shape.getObjectData();
- if(data != null) {
- TikaInputStream stream =
- TikaInputStream.get(data.getData());
- try {
- String mediaType = null;
- if ("Excel.Chart.8".equals(shape.getProgID())) {
+ public HSLFExtractor(ParseContext context) {
+ super(context);
+ }
+
+ protected void parse(
+ NPOIFSFileSystem filesystem, XHTMLContentHandler xhtml)
+ throws IOException, SAXException, TikaException {
+ HSLFSlideShow ss = new HSLFSlideShow(filesystem.getRoot());
+ SlideShow _show = new SlideShow(ss);
+ Slide[] _slides = _show.getSlides();
+
+ xhtml.startElement("div", "style", "slideShow");
+
+ /* Iterate over slides and extract text */
+ for( Slide slide : _slides ) {
+ xhtml.startElement("div", "class", "slide");
+
+ // Slide header, if present
+ HeadersFooters hf = slide.getHeadersFooters();
+ if (hf != null && hf.isHeaderVisible() && hf.getHeaderText() != null)
{
+ xhtml.startElement("p", "class", "slide-header");
+
+ xhtml.characters( hf.getHeaderText() );
+
+ xhtml.endElement("p");
+ }
+
+ // Slide master, if present
+ MasterSheet master = slide.getMasterSheet();
+ if(master != null) {
+ xhtml.startElement("p", "class", "slide-master-content");
+ textRunsToText(xhtml, master.getTextRuns() );
+ xhtml.endElement("p");
+ }
+
+ // Slide text
+ {
+ xhtml.startElement("p", "class", "slide-content");
+
+ textRunsToText(xhtml, slide.getTextRuns() );
+
+ xhtml.endElement("p");
+ }
+
+ // Slide footer, if present
+ if (hf != null && hf.isFooterVisible() && hf.getFooterText() != null)
{
+ xhtml.startElement("p", "class", "slide-footer");
+
+ xhtml.characters( hf.getFooterText() );
+
+ xhtml.endElement("p");
+ }
+
+ // Comments, if present
+ for( Comment comment : slide.getComments() ) {
+ xhtml.startElement("p", "class", "slide-comment");
+ xhtml.startElement("b");
+ xhtml.characters( comment.getAuthor() );
+ xhtml.endElement("b");
+ xhtml.characters( " - ");
+ xhtml.characters( comment.getText() );
+ xhtml.endElement("p");
+ }
+
+ // Now any embedded resources
+ handleSlideEmbeddedResources(slide, xhtml);
+
+ // TODO Find the Notes for this slide and extract inline
+
+ // Slide complete
+ xhtml.endElement("div");
+ }
+
+ // All slides done
+ xhtml.endElement("div");
+
+ /* notes */
+ xhtml.startElement("div", "class", "slideNotes");
+ HashSet<Integer> seenNotes = new HashSet<Integer>();
+ HeadersFooters hf = _show.getNotesHeadersFooters();
+
+ for (Slide slide : _slides) {
+ Notes notes = slide.getNotesSheet();
+ if (notes == null) {
+ continue;
+ }
+ Integer id = Integer.valueOf(notes._getSheetNumber());
+ if (seenNotes.contains(id)) {
+ continue;
+ }
+ seenNotes.add(id);
+
+ // Repeat the Notes header, if set
+ if (hf != null && hf.isHeaderVisible() && hf.getHeaderText() != null)
{
+ xhtml.startElement("p", "class", "slide-note-header");
+ xhtml.characters( hf.getFooterText() );
+ xhtml.endElement("p");
+ }
+
+ // Notes text
+ textRunsToText(xhtml, notes.getTextRuns());
+
+ // Repeat the notes footer, if set
+ if (hf != null && hf.isFooterVisible() && hf.getFooterText() != null)
{
+ xhtml.startElement("p", "class", "slide-note-footer");
+ xhtml.characters( hf.getFooterText() );
+ xhtml.endElement("p");
+ }
+ }
+
+ xhtml.endElement("div");
+ }
+
+ private void textRunsToText(XHTMLContentHandler xhtml, TextRun[] runs)
throws SAXException {
+ if (runs==null) {
+ return;
+ }
+
+ for (TextRun run : runs) {
+ if (run != null) {
+ xhtml.characters( run.getText() );
+ xhtml.startElement("br");
+ xhtml.endElement("br");
+ }
+ }
+ }
+
+ private void handleSlideEmbeddedResources(Slide slide, XHTMLContentHandler
xhtml)
+ throws TikaException, SAXException, IOException {
+ for( Shape shape : slide.getShapes() ) {
+ if( shape instanceof OLEShape ) {
+ OLEShape oleShape = (OLEShape)shape;
+
+ try {
+ ObjectData data = oleShape.getObjectData();
+
+ if(data != null) {
+ TikaInputStream stream =
+ TikaInputStream.get(data.getData());
+ try {
+ String mediaType = null;
+ if ("Excel.Chart.8".equals(oleShape.getProgID())) {
mediaType = "application/vnd.ms-excel";
- }
- handleEmbeddedResource(
- stream, Integer.toString(shape.getObjectID()),
- mediaType, xhtml, false);
- } finally {
- stream.close();
- }
+ }
+ handleEmbeddedResource(
+ stream, Integer.toString(oleShape.getObjectID()),
+ mediaType, xhtml, false);
+ } finally {
+ stream.close();
+ }
+ }
+ } catch( NullPointerException e ) {
+ /* getObjectData throws NPE some times. */
}
- }
- }
+ }
+ }
+ }
}