You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tika.apache.org by ta...@apache.org on 2016/04/07 21:36:47 UTC
[04/10] tika git commit: TIKA-1936 whitespace clean up
http://git-wip-us.apache.org/repos/asf/tika/blob/d8231f48/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java
----------------------------------------------------------------------
diff --git a/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java b/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java
index 6117690..5006d0b 100644
--- a/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java
+++ b/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XSSFExcelExtractorDecorator.java
@@ -1,396 +1,396 @@
-/*
- * 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.tika.parser.microsoft.ooxml;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-
-import org.apache.poi.hssf.extractor.ExcelExtractor;
-import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
-import org.apache.poi.openxml4j.opc.OPCPackage;
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.openxml4j.opc.PackagePartName;
-import org.apache.poi.openxml4j.opc.PackageRelationship;
-import org.apache.poi.openxml4j.opc.PackagingURIHelper;
-import org.apache.poi.openxml4j.opc.TargetMode;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.usermodel.HeaderFooter;
-import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
-import org.apache.poi.xssf.eventusermodel.XSSFReader;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
-import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
-import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
-import org.apache.poi.xssf.model.CommentsTable;
-import org.apache.poi.xssf.model.StylesTable;
-import org.apache.poi.xssf.usermodel.XSSFComment;
-import org.apache.poi.xssf.usermodel.XSSFRelation;
-import org.apache.poi.xssf.usermodel.XSSFShape;
-import org.apache.poi.xssf.usermodel.XSSFSimpleShape;
-import org.apache.poi.xssf.usermodel.helpers.HeaderFooterHelper;
-import org.apache.tika.exception.TikaException;
-import org.apache.tika.metadata.Metadata;
-import org.apache.tika.metadata.TikaMetadataKeys;
-import org.apache.tika.parser.ParseContext;
-import org.apache.tika.sax.XHTMLContentHandler;
-import org.apache.xmlbeans.XmlException;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-
-public class XSSFExcelExtractorDecorator extends AbstractOOXMLExtractor {
- /**
- * Allows access to headers/footers from raw xml strings
- */
- private static HeaderFooterHelper hfHelper = new HeaderFooterHelper();
- private final XSSFEventBasedExcelExtractor extractor;
- private final DataFormatter formatter;
- private final List<PackagePart> sheetParts = new ArrayList<PackagePart>();
- private Metadata metadata;
-
- public XSSFExcelExtractorDecorator(
- ParseContext context, XSSFEventBasedExcelExtractor extractor, Locale locale) {
- super(context, extractor);
-
- this.extractor = extractor;
- extractor.setFormulasNotResults(false);
- extractor.setLocale(locale);
-
- if (locale == null) {
- formatter = new DataFormatter();
- } else {
- formatter = new DataFormatter(locale);
- }
- }
-
- @Override
- public void getXHTML(
- ContentHandler handler, Metadata metadata, ParseContext context)
- throws SAXException, XmlException, IOException, TikaException {
-
- this.metadata = metadata;
- metadata.set(TikaMetadataKeys.PROTECTED, "false");
-
- super.getXHTML(handler, metadata, context);
- }
-
- /**
- * @see org.apache.poi.xssf.extractor.XSSFExcelExtractor#getText()
- */
- @Override
- protected void buildXHTML(XHTMLContentHandler xhtml) throws SAXException,
- XmlException, IOException {
- OPCPackage container = extractor.getPackage();
-
- ReadOnlySharedStringsTable strings;
- XSSFReader.SheetIterator iter;
- XSSFReader xssfReader;
- StylesTable styles;
- try {
- xssfReader = new XSSFReader(container);
- styles = xssfReader.getStylesTable();
- iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
- strings = new ReadOnlySharedStringsTable(container);
- } catch (InvalidFormatException e) {
- throw new XmlException(e);
- } catch (OpenXML4JException oe) {
- throw new XmlException(oe);
- }
-
- while (iter.hasNext()) {
- InputStream stream = iter.next();
- sheetParts.add(iter.getSheetPart());
-
- SheetTextAsHTML sheetExtractor = new SheetTextAsHTML(xhtml);
- CommentsTable comments = iter.getSheetComments();
-
- // Start, and output the sheet name
- xhtml.startElement("div");
- xhtml.element("h1", iter.getSheetName());
-
- // Extract the main sheet contents
- xhtml.startElement("table");
- xhtml.startElement("tbody");
-
- processSheet(sheetExtractor, comments, styles, strings, stream);
-
- xhtml.endElement("tbody");
- xhtml.endElement("table");
-
- // Output any headers and footers
- // (Need to process the sheet to get them, so we can't
- // do the headers before the contents)
- for (String header : sheetExtractor.headers) {
- extractHeaderFooter(header, xhtml);
- }
- for (String footer : sheetExtractor.footers) {
- extractHeaderFooter(footer, xhtml);
- }
- processShapes(iter.getShapes(), xhtml);
- // All done with this sheet
- xhtml.endElement("div");
- }
- }
-
- private void extractHeaderFooter(String hf, XHTMLContentHandler xhtml)
- throws SAXException {
- String content = ExcelExtractor._extractHeaderFooter(
- new HeaderFooterFromString(hf));
- if (content.length() > 0) {
- xhtml.element("p", content);
- }
- }
-
- private void processShapes(List<XSSFShape> shapes, XHTMLContentHandler xhtml) throws SAXException {
- if (shapes == null) {
- return;
- }
- for (XSSFShape shape : shapes) {
- if (shape instanceof XSSFSimpleShape) {
- String sText = ((XSSFSimpleShape) shape).getText();
- if (sText != null && sText.length() > 0) {
- xhtml.element("p", sText);
- }
- }
- }
- }
-
- public void processSheet(
- SheetContentsHandler sheetContentsExtractor,
- CommentsTable comments,
- StylesTable styles,
- ReadOnlySharedStringsTable strings,
- InputStream sheetInputStream)
- throws IOException, SAXException {
- InputSource sheetSource = new InputSource(sheetInputStream);
- SAXParserFactory saxFactory = SAXParserFactory.newInstance();
- saxFactory.setNamespaceAware(true);
- try {
- SAXParser saxParser = saxFactory.newSAXParser();
- XMLReader sheetParser = saxParser.getXMLReader();
- XSSFSheetInterestingPartsCapturer handler =
- new XSSFSheetInterestingPartsCapturer(new XSSFSheetXMLHandler(
- styles, comments, strings, sheetContentsExtractor, formatter, false));
- sheetParser.setContentHandler(handler);
- sheetParser.parse(sheetSource);
- sheetInputStream.close();
-
- if (handler.hasProtection) {
- metadata.set(TikaMetadataKeys.PROTECTED, "true");
- }
- } catch (ParserConfigurationException e) {
- throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
- }
- }
-
- /**
- * In Excel files, sheets have things embedded in them,
- * and sheet drawings which have the images
- */
- @Override
- protected List<PackagePart> getMainDocumentParts() throws TikaException {
- List<PackagePart> parts = new ArrayList<PackagePart>();
- for (PackagePart part : sheetParts) {
- // Add the sheet
- parts.add(part);
-
- // If it has drawings, return those too
- try {
- for (PackageRelationship rel : part.getRelationshipsByType(XSSFRelation.DRAWINGS.getRelation())) {
- if (rel.getTargetMode() == TargetMode.INTERNAL) {
- PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
- parts.add(rel.getPackage().getPart(relName));
- }
- }
- for (PackageRelationship rel : part.getRelationshipsByType(XSSFRelation.VML_DRAWINGS.getRelation())) {
- if (rel.getTargetMode() == TargetMode.INTERNAL) {
- PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
- parts.add(rel.getPackage().getPart(relName));
- }
- }
- } catch (InvalidFormatException e) {
- throw new TikaException("Broken OOXML file", e);
- }
- }
-
- return parts;
- }
-
- /**
- * Turns formatted sheet events into HTML
- */
- protected static class SheetTextAsHTML implements SheetContentsHandler {
- private XHTMLContentHandler xhtml;
- private List<String> headers;
- private List<String> footers;
-
- protected SheetTextAsHTML(XHTMLContentHandler xhtml) {
- this.xhtml = xhtml;
- headers = new ArrayList<String>();
- footers = new ArrayList<String>();
- }
-
- public void startRow(int rowNum) {
- try {
- xhtml.startElement("tr");
- } catch (SAXException e) {
- }
- }
-
- public void endRow(int rowNum) {
- try {
- xhtml.endElement("tr");
- } catch (SAXException e) {
- }
- }
-
- public void cell(String cellRef, String formattedValue, XSSFComment comment) {
- try {
- xhtml.startElement("td");
-
- // Main cell contents
- if (formattedValue != null) {
- xhtml.characters(formattedValue);
- }
-
- // Comments
- if (comment != null) {
- xhtml.startElement("br");
- xhtml.endElement("br");
- xhtml.characters(comment.getAuthor());
- xhtml.characters(": ");
- xhtml.characters(comment.getString().getString());
- }
-
- xhtml.endElement("td");
- } catch (SAXException e) {
- }
- }
-
- public void headerFooter(String text, boolean isHeader, String tagName) {
- if (isHeader) {
- headers.add(text);
- } else {
- footers.add(text);
- }
- }
- }
-
- protected static class HeaderFooterFromString implements HeaderFooter {
- private String text;
-
- protected HeaderFooterFromString(String text) {
- this.text = text;
- }
-
- public String getCenter() {
- return hfHelper.getCenterSection(text);
- }
-
- public void setCenter(String paramString) {
- }
-
- public String getLeft() {
- return hfHelper.getLeftSection(text);
- }
-
- public void setLeft(String paramString) {
- }
-
- public String getRight() {
- return hfHelper.getRightSection(text);
- }
-
- public void setRight(String paramString) {
- }
- }
-
- /**
- * Captures information on interesting tags, whilst
- * delegating the main work to the formatting handler
- */
- protected static class XSSFSheetInterestingPartsCapturer implements ContentHandler {
- private ContentHandler delegate;
- private boolean hasProtection = false;
-
- protected XSSFSheetInterestingPartsCapturer(ContentHandler delegate) {
- this.delegate = delegate;
- }
-
- public void startElement(String uri, String localName, String qName,
- Attributes atts) throws SAXException {
- if ("sheetProtection".equals(qName)) {
- hasProtection = true;
- }
- delegate.startElement(uri, localName, qName, atts);
- }
-
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- delegate.characters(ch, start, length);
- }
-
- public void endDocument() throws SAXException {
- delegate.endDocument();
- }
-
- public void endElement(String uri, String localName, String qName)
- throws SAXException {
- delegate.endElement(uri, localName, qName);
- }
-
- public void endPrefixMapping(String prefix) throws SAXException {
- delegate.endPrefixMapping(prefix);
- }
-
- public void ignorableWhitespace(char[] ch, int start, int length)
- throws SAXException {
- delegate.ignorableWhitespace(ch, start, length);
- }
-
- public void processingInstruction(String target, String data)
- throws SAXException {
- delegate.processingInstruction(target, data);
- }
-
- public void setDocumentLocator(Locator locator) {
- delegate.setDocumentLocator(locator);
- }
-
- public void skippedEntity(String name) throws SAXException {
- delegate.skippedEntity(name);
- }
-
- public void startDocument() throws SAXException {
- delegate.startDocument();
- }
-
- public void startPrefixMapping(String prefix, String uri)
- throws SAXException {
- delegate.startPrefixMapping(prefix, uri);
- }
- }
-}
+/*
+ * 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.tika.parser.microsoft.ooxml;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.poi.hssf.extractor.ExcelExtractor;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
+import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
+import org.apache.poi.openxml4j.opc.OPCPackage;
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+import org.apache.poi.openxml4j.opc.PackagingURIHelper;
+import org.apache.poi.openxml4j.opc.TargetMode;
+import org.apache.poi.ss.usermodel.DataFormatter;
+import org.apache.poi.ss.usermodel.HeaderFooter;
+import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
+import org.apache.poi.xssf.eventusermodel.XSSFReader;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
+import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
+import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
+import org.apache.poi.xssf.model.CommentsTable;
+import org.apache.poi.xssf.model.StylesTable;
+import org.apache.poi.xssf.usermodel.XSSFComment;
+import org.apache.poi.xssf.usermodel.XSSFRelation;
+import org.apache.poi.xssf.usermodel.XSSFShape;
+import org.apache.poi.xssf.usermodel.XSSFSimpleShape;
+import org.apache.poi.xssf.usermodel.helpers.HeaderFooterHelper;
+import org.apache.tika.exception.TikaException;
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.TikaMetadataKeys;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.XHTMLContentHandler;
+import org.apache.xmlbeans.XmlException;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
+public class XSSFExcelExtractorDecorator extends AbstractOOXMLExtractor {
+ /**
+ * Allows access to headers/footers from raw xml strings
+ */
+ private static HeaderFooterHelper hfHelper = new HeaderFooterHelper();
+ private final XSSFEventBasedExcelExtractor extractor;
+ private final DataFormatter formatter;
+ private final List<PackagePart> sheetParts = new ArrayList<PackagePart>();
+ private Metadata metadata;
+
+ public XSSFExcelExtractorDecorator(
+ ParseContext context, XSSFEventBasedExcelExtractor extractor, Locale locale) {
+ super(context, extractor);
+
+ this.extractor = extractor;
+ extractor.setFormulasNotResults(false);
+ extractor.setLocale(locale);
+
+ if (locale == null) {
+ formatter = new DataFormatter();
+ } else {
+ formatter = new DataFormatter(locale);
+ }
+ }
+
+ @Override
+ public void getXHTML(
+ ContentHandler handler, Metadata metadata, ParseContext context)
+ throws SAXException, XmlException, IOException, TikaException {
+
+ this.metadata = metadata;
+ metadata.set(TikaMetadataKeys.PROTECTED, "false");
+
+ super.getXHTML(handler, metadata, context);
+ }
+
+ /**
+ * @see org.apache.poi.xssf.extractor.XSSFExcelExtractor#getText()
+ */
+ @Override
+ protected void buildXHTML(XHTMLContentHandler xhtml) throws SAXException,
+ XmlException, IOException {
+ OPCPackage container = extractor.getPackage();
+
+ ReadOnlySharedStringsTable strings;
+ XSSFReader.SheetIterator iter;
+ XSSFReader xssfReader;
+ StylesTable styles;
+ try {
+ xssfReader = new XSSFReader(container);
+ styles = xssfReader.getStylesTable();
+ iter = (XSSFReader.SheetIterator) xssfReader.getSheetsData();
+ strings = new ReadOnlySharedStringsTable(container);
+ } catch (InvalidFormatException e) {
+ throw new XmlException(e);
+ } catch (OpenXML4JException oe) {
+ throw new XmlException(oe);
+ }
+
+ while (iter.hasNext()) {
+ InputStream stream = iter.next();
+ sheetParts.add(iter.getSheetPart());
+
+ SheetTextAsHTML sheetExtractor = new SheetTextAsHTML(xhtml);
+ CommentsTable comments = iter.getSheetComments();
+
+ // Start, and output the sheet name
+ xhtml.startElement("div");
+ xhtml.element("h1", iter.getSheetName());
+
+ // Extract the main sheet contents
+ xhtml.startElement("table");
+ xhtml.startElement("tbody");
+
+ processSheet(sheetExtractor, comments, styles, strings, stream);
+
+ xhtml.endElement("tbody");
+ xhtml.endElement("table");
+
+ // Output any headers and footers
+ // (Need to process the sheet to get them, so we can't
+ // do the headers before the contents)
+ for (String header : sheetExtractor.headers) {
+ extractHeaderFooter(header, xhtml);
+ }
+ for (String footer : sheetExtractor.footers) {
+ extractHeaderFooter(footer, xhtml);
+ }
+ processShapes(iter.getShapes(), xhtml);
+ // All done with this sheet
+ xhtml.endElement("div");
+ }
+ }
+
+ private void extractHeaderFooter(String hf, XHTMLContentHandler xhtml)
+ throws SAXException {
+ String content = ExcelExtractor._extractHeaderFooter(
+ new HeaderFooterFromString(hf));
+ if (content.length() > 0) {
+ xhtml.element("p", content);
+ }
+ }
+
+ private void processShapes(List<XSSFShape> shapes, XHTMLContentHandler xhtml) throws SAXException {
+ if (shapes == null) {
+ return;
+ }
+ for (XSSFShape shape : shapes) {
+ if (shape instanceof XSSFSimpleShape) {
+ String sText = ((XSSFSimpleShape) shape).getText();
+ if (sText != null && sText.length() > 0) {
+ xhtml.element("p", sText);
+ }
+ }
+ }
+ }
+
+ public void processSheet(
+ SheetContentsHandler sheetContentsExtractor,
+ CommentsTable comments,
+ StylesTable styles,
+ ReadOnlySharedStringsTable strings,
+ InputStream sheetInputStream)
+ throws IOException, SAXException {
+ InputSource sheetSource = new InputSource(sheetInputStream);
+ SAXParserFactory saxFactory = SAXParserFactory.newInstance();
+ saxFactory.setNamespaceAware(true);
+ try {
+ SAXParser saxParser = saxFactory.newSAXParser();
+ XMLReader sheetParser = saxParser.getXMLReader();
+ XSSFSheetInterestingPartsCapturer handler =
+ new XSSFSheetInterestingPartsCapturer(new XSSFSheetXMLHandler(
+ styles, comments, strings, sheetContentsExtractor, formatter, false));
+ sheetParser.setContentHandler(handler);
+ sheetParser.parse(sheetSource);
+ sheetInputStream.close();
+
+ if (handler.hasProtection) {
+ metadata.set(TikaMetadataKeys.PROTECTED, "true");
+ }
+ } catch (ParserConfigurationException e) {
+ throw new RuntimeException("SAX parser appears to be broken - " + e.getMessage());
+ }
+ }
+
+ /**
+ * In Excel files, sheets have things embedded in them,
+ * and sheet drawings which have the images
+ */
+ @Override
+ protected List<PackagePart> getMainDocumentParts() throws TikaException {
+ List<PackagePart> parts = new ArrayList<PackagePart>();
+ for (PackagePart part : sheetParts) {
+ // Add the sheet
+ parts.add(part);
+
+ // If it has drawings, return those too
+ try {
+ for (PackageRelationship rel : part.getRelationshipsByType(XSSFRelation.DRAWINGS.getRelation())) {
+ if (rel.getTargetMode() == TargetMode.INTERNAL) {
+ PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
+ parts.add(rel.getPackage().getPart(relName));
+ }
+ }
+ for (PackageRelationship rel : part.getRelationshipsByType(XSSFRelation.VML_DRAWINGS.getRelation())) {
+ if (rel.getTargetMode() == TargetMode.INTERNAL) {
+ PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
+ parts.add(rel.getPackage().getPart(relName));
+ }
+ }
+ } catch (InvalidFormatException e) {
+ throw new TikaException("Broken OOXML file", e);
+ }
+ }
+
+ return parts;
+ }
+
+ /**
+ * Turns formatted sheet events into HTML
+ */
+ protected static class SheetTextAsHTML implements SheetContentsHandler {
+ private XHTMLContentHandler xhtml;
+ private List<String> headers;
+ private List<String> footers;
+
+ protected SheetTextAsHTML(XHTMLContentHandler xhtml) {
+ this.xhtml = xhtml;
+ headers = new ArrayList<String>();
+ footers = new ArrayList<String>();
+ }
+
+ public void startRow(int rowNum) {
+ try {
+ xhtml.startElement("tr");
+ } catch (SAXException e) {
+ }
+ }
+
+ public void endRow(int rowNum) {
+ try {
+ xhtml.endElement("tr");
+ } catch (SAXException e) {
+ }
+ }
+
+ public void cell(String cellRef, String formattedValue, XSSFComment comment) {
+ try {
+ xhtml.startElement("td");
+
+ // Main cell contents
+ if (formattedValue != null) {
+ xhtml.characters(formattedValue);
+ }
+
+ // Comments
+ if (comment != null) {
+ xhtml.startElement("br");
+ xhtml.endElement("br");
+ xhtml.characters(comment.getAuthor());
+ xhtml.characters(": ");
+ xhtml.characters(comment.getString().getString());
+ }
+
+ xhtml.endElement("td");
+ } catch (SAXException e) {
+ }
+ }
+
+ public void headerFooter(String text, boolean isHeader, String tagName) {
+ if (isHeader) {
+ headers.add(text);
+ } else {
+ footers.add(text);
+ }
+ }
+ }
+
+ protected static class HeaderFooterFromString implements HeaderFooter {
+ private String text;
+
+ protected HeaderFooterFromString(String text) {
+ this.text = text;
+ }
+
+ public String getCenter() {
+ return hfHelper.getCenterSection(text);
+ }
+
+ public void setCenter(String paramString) {
+ }
+
+ public String getLeft() {
+ return hfHelper.getLeftSection(text);
+ }
+
+ public void setLeft(String paramString) {
+ }
+
+ public String getRight() {
+ return hfHelper.getRightSection(text);
+ }
+
+ public void setRight(String paramString) {
+ }
+ }
+
+ /**
+ * Captures information on interesting tags, whilst
+ * delegating the main work to the formatting handler
+ */
+ protected static class XSSFSheetInterestingPartsCapturer implements ContentHandler {
+ private ContentHandler delegate;
+ private boolean hasProtection = false;
+
+ protected XSSFSheetInterestingPartsCapturer(ContentHandler delegate) {
+ this.delegate = delegate;
+ }
+
+ public void startElement(String uri, String localName, String qName,
+ Attributes atts) throws SAXException {
+ if ("sheetProtection".equals(qName)) {
+ hasProtection = true;
+ }
+ delegate.startElement(uri, localName, qName, atts);
+ }
+
+ public void characters(char[] ch, int start, int length)
+ throws SAXException {
+ delegate.characters(ch, start, length);
+ }
+
+ public void endDocument() throws SAXException {
+ delegate.endDocument();
+ }
+
+ public void endElement(String uri, String localName, String qName)
+ throws SAXException {
+ delegate.endElement(uri, localName, qName);
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ delegate.endPrefixMapping(prefix);
+ }
+
+ public void ignorableWhitespace(char[] ch, int start, int length)
+ throws SAXException {
+ delegate.ignorableWhitespace(ch, start, length);
+ }
+
+ public void processingInstruction(String target, String data)
+ throws SAXException {
+ delegate.processingInstruction(target, data);
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ delegate.setDocumentLocator(locator);
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ delegate.skippedEntity(name);
+ }
+
+ public void startDocument() throws SAXException {
+ delegate.startDocument();
+ }
+
+ public void startPrefixMapping(String prefix, String uri)
+ throws SAXException {
+ delegate.startPrefixMapping(prefix, uri);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tika/blob/d8231f48/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XWPFWordExtractorDecorator.java
----------------------------------------------------------------------
diff --git a/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XWPFWordExtractorDecorator.java b/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XWPFWordExtractorDecorator.java
index 284d21f..6caf803 100644
--- a/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XWPFWordExtractorDecorator.java
+++ b/tika-parser-modules/tika-parser-office-module/src/main/java/org/apache/tika/parser/microsoft/ooxml/XWPFWordExtractorDecorator.java
@@ -1,459 +1,459 @@
-/*
- * 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.tika.parser.microsoft.ooxml;
-
-import javax.xml.namespace.QName;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
-import org.apache.poi.xwpf.model.XWPFCommentsDecorator;
-import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
-import org.apache.poi.xwpf.usermodel.BodyType;
-import org.apache.poi.xwpf.usermodel.IBody;
-import org.apache.poi.xwpf.usermodel.IBodyElement;
-import org.apache.poi.xwpf.usermodel.ICell;
-import org.apache.poi.xwpf.usermodel.IRunElement;
-import org.apache.poi.xwpf.usermodel.ISDTContent;
-import org.apache.poi.xwpf.usermodel.XWPFDocument;
-import org.apache.poi.xwpf.usermodel.XWPFHeaderFooter;
-import org.apache.poi.xwpf.usermodel.XWPFHyperlink;
-import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
-import org.apache.poi.xwpf.usermodel.XWPFParagraph;
-import org.apache.poi.xwpf.usermodel.XWPFPicture;
-import org.apache.poi.xwpf.usermodel.XWPFPictureData;
-import org.apache.poi.xwpf.usermodel.XWPFRun;
-import org.apache.poi.xwpf.usermodel.XWPFSDT;
-import org.apache.poi.xwpf.usermodel.XWPFSDTCell;
-import org.apache.poi.xwpf.usermodel.XWPFStyle;
-import org.apache.poi.xwpf.usermodel.XWPFStyles;
-import org.apache.poi.xwpf.usermodel.XWPFTable;
-import org.apache.poi.xwpf.usermodel.XWPFTableCell;
-import org.apache.poi.xwpf.usermodel.XWPFTableRow;
-import org.apache.tika.parser.ParseContext;
-import org.apache.tika.parser.microsoft.WordExtractor;
-import org.apache.tika.parser.microsoft.WordExtractor.TagAndStyle;
-import org.apache.tika.sax.XHTMLContentHandler;
-import org.apache.xmlbeans.XmlCursor;
-import org.apache.xmlbeans.XmlException;
-import org.apache.xmlbeans.XmlObject;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTObject;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
-import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.AttributesImpl;
-
-public class XWPFWordExtractorDecorator extends AbstractOOXMLExtractor {
-
- // could be improved by using the real delimiter in xchFollow [MS-DOC], v20140721, 2.4.6.3, Part 3, Step 3
- private static final String LIST_DELIMITER = " ";
-
-
- private XWPFDocument document;
- private XWPFStyles styles;
-
- public XWPFWordExtractorDecorator(ParseContext context, XWPFWordExtractor extractor) {
- super(context, extractor);
-
- document = (XWPFDocument) extractor.getDocument();
- styles = document.getStyles();
- }
-
- /**
- * @see org.apache.poi.xwpf.extractor.XWPFWordExtractor#getText()
- */
- @Override
- protected void buildXHTML(XHTMLContentHandler xhtml)
- throws SAXException, XmlException, IOException {
- XWPFHeaderFooterPolicy hfPolicy = document.getHeaderFooterPolicy();
- XWPFListManager listManager = new XWPFListManager(document);
- // headers
- if (hfPolicy != null) {
- extractHeaders(xhtml, hfPolicy, listManager);
- }
-
- // process text in the order that it occurs in
- extractIBodyText(document, listManager, xhtml);
-
- // then all document tables
- if (hfPolicy != null) {
- extractFooters(xhtml, hfPolicy, listManager);
- }
- }
-
- private void extractIBodyText(IBody bodyElement, XWPFListManager listManager,
- XHTMLContentHandler xhtml)
- throws SAXException, XmlException, IOException {
- for (IBodyElement element : bodyElement.getBodyElements()) {
- if (element instanceof XWPFParagraph) {
- XWPFParagraph paragraph = (XWPFParagraph) element;
- extractParagraph(paragraph, listManager, xhtml);
- }
- if (element instanceof XWPFTable) {
- XWPFTable table = (XWPFTable) element;
- extractTable(table, listManager, xhtml);
- }
- if (element instanceof XWPFSDT) {
- extractSDT((XWPFSDT) element, xhtml);
- }
-
- }
- }
-
- private void extractSDT(XWPFSDT element, XHTMLContentHandler xhtml) throws SAXException,
- XmlException, IOException {
- ISDTContent content = element.getContent();
- String tag = "p";
- xhtml.startElement(tag);
- xhtml.characters(content.getText());
- xhtml.endElement(tag);
- }
-
- private void extractParagraph(XWPFParagraph paragraph, XWPFListManager listManager,
- XHTMLContentHandler xhtml)
- throws SAXException, XmlException, IOException {
- // If this paragraph is actually a whole new section, then
- // it could have its own headers and footers
- // Check and handle if so
- XWPFHeaderFooterPolicy headerFooterPolicy = null;
- if (paragraph.getCTP().getPPr() != null) {
- CTSectPr ctSectPr = paragraph.getCTP().getPPr().getSectPr();
- if (ctSectPr != null) {
- headerFooterPolicy =
- new XWPFHeaderFooterPolicy(document, ctSectPr);
- extractHeaders(xhtml, headerFooterPolicy, listManager);
- }
- }
-
- // Is this a paragraph, or a heading?
- String tag = "p";
- String styleClass = null;
- if (paragraph.getStyleID() != null) {
- XWPFStyle style = styles.getStyle(
- paragraph.getStyleID()
- );
-
- if (style != null && style.getName() != null) {
- TagAndStyle tas = WordExtractor.buildParagraphTagAndStyle(
- style.getName(), paragraph.getPartType() == BodyType.TABLECELL
- );
- tag = tas.getTag();
- styleClass = tas.getStyleClass();
- }
- }
-
- if (styleClass == null) {
- xhtml.startElement(tag);
- } else {
- xhtml.startElement(tag, "class", styleClass);
- }
-
- writeParagraphNumber(paragraph, listManager, xhtml);
- // Output placeholder for any embedded docs:
-
- // TODO: replace w/ XPath/XQuery:
- for (XWPFRun run : paragraph.getRuns()) {
- XmlCursor c = run.getCTR().newCursor();
- c.selectPath("./*");
- while (c.toNextSelection()) {
- XmlObject o = c.getObject();
- if (o instanceof CTObject) {
- XmlCursor c2 = o.newCursor();
- c2.selectPath("./*");
- while (c2.toNextSelection()) {
- XmlObject o2 = c2.getObject();
-
- XmlObject embedAtt = o2.selectAttribute(new QName("Type"));
- if (embedAtt != null && embedAtt.getDomNode().getNodeValue().equals("Embed")) {
- // Type is "Embed"
- XmlObject relIDAtt = o2.selectAttribute(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id"));
- if (relIDAtt != null) {
- String relID = relIDAtt.getDomNode().getNodeValue();
- AttributesImpl attributes = new AttributesImpl();
- attributes.addAttribute("", "class", "class", "CDATA", "embedded");
- attributes.addAttribute("", "id", "id", "CDATA", relID);
- xhtml.startElement("div", attributes);
- xhtml.endElement("div");
- }
- }
- }
- c2.dispose();
- }
- }
-
- c.dispose();
- }
-
- // Attach bookmarks for the paragraph
- // (In future, we might put them in the right place, for now
- // we just put them in the correct paragraph)
- for (int i = 0; i < paragraph.getCTP().sizeOfBookmarkStartArray(); i++) {
- CTBookmark bookmark = paragraph.getCTP().getBookmarkStartArray(i);
- xhtml.startElement("a", "name", bookmark.getName());
- xhtml.endElement("a");
- }
-
- TmpFormatting fmtg = new TmpFormatting(false, false);
-
- // Do the iruns
- for (IRunElement run : paragraph.getIRuns()) {
- if (run instanceof XWPFSDT) {
- fmtg = closeStyleTags(xhtml, fmtg);
- processSDTRun((XWPFSDT) run, xhtml);
- //for now, we're ignoring formatting in sdt
- //if you hit an sdt reset to false
- fmtg.setBold(false);
- fmtg.setItalic(false);
- } else {
- fmtg = processRun((XWPFRun) run, paragraph, xhtml, fmtg);
- }
- }
- closeStyleTags(xhtml, fmtg);
-
-
- // Now do any comments for the paragraph
- XWPFCommentsDecorator comments = new XWPFCommentsDecorator(paragraph, null);
- String commentText = comments.getCommentText();
- if (commentText != null && commentText.length() > 0) {
- xhtml.characters(commentText);
- }
-
- String footnameText = paragraph.getFootnoteText();
- if (footnameText != null && footnameText.length() > 0) {
- xhtml.characters(footnameText + "\n");
- }
-
- // Also extract any paragraphs embedded in text boxes:
- for (XmlObject embeddedParagraph : paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent/w:p")) {
- extractParagraph(new XWPFParagraph(CTP.Factory.parse(embeddedParagraph.xmlText()), paragraph.getBody()), listManager, xhtml);
- }
-
- // Finish this paragraph
- xhtml.endElement(tag);
-
- if (headerFooterPolicy != null) {
- extractFooters(xhtml, headerFooterPolicy, listManager);
- }
- }
-
- private void writeParagraphNumber(XWPFParagraph paragraph,
- XWPFListManager listManager,
- XHTMLContentHandler xhtml) throws SAXException {
- if (paragraph.getNumIlvl() == null) {
- return;
- }
- String number = listManager.getFormattedNumber(paragraph);
- if (number != null) {
- xhtml.characters(number);
- }
-
- }
-
- private TmpFormatting closeStyleTags(XHTMLContentHandler xhtml,
- TmpFormatting fmtg) throws SAXException {
- // Close any still open style tags
- if (fmtg.isItalic()) {
- xhtml.endElement("i");
- fmtg.setItalic(false);
- }
- if (fmtg.isBold()) {
- xhtml.endElement("b");
- fmtg.setBold(false);
- }
- return fmtg;
- }
-
- private TmpFormatting processRun(XWPFRun run, XWPFParagraph paragraph,
- XHTMLContentHandler xhtml, TmpFormatting tfmtg)
- throws SAXException, XmlException, IOException {
- // True if we are currently in the named style tag:
- if (run.isBold() != tfmtg.isBold()) {
- if (tfmtg.isItalic()) {
- xhtml.endElement("i");
- tfmtg.setItalic(false);
- }
- if (run.isBold()) {
- xhtml.startElement("b");
- } else {
- xhtml.endElement("b");
- }
- tfmtg.setBold(run.isBold());
- }
-
- if (run.isItalic() != tfmtg.isItalic()) {
- if (run.isItalic()) {
- xhtml.startElement("i");
- } else {
- xhtml.endElement("i");
- }
- tfmtg.setItalic(run.isItalic());
- }
-
- boolean addedHREF = false;
- if (run instanceof XWPFHyperlinkRun) {
- XWPFHyperlinkRun linkRun = (XWPFHyperlinkRun) run;
- XWPFHyperlink link = linkRun.getHyperlink(document);
- if (link != null && link.getURL() != null) {
- xhtml.startElement("a", "href", link.getURL());
- addedHREF = true;
- } else if (linkRun.getAnchor() != null && linkRun.getAnchor().length() > 0) {
- xhtml.startElement("a", "href", "#" + linkRun.getAnchor());
- addedHREF = true;
- }
- }
-
- xhtml.characters(run.toString());
-
- // If we have any pictures, output them
- for (XWPFPicture picture : run.getEmbeddedPictures()) {
- if (paragraph.getDocument() != null) {
- XWPFPictureData data = picture.getPictureData();
- if (data != null) {
- AttributesImpl attr = new AttributesImpl();
-
- attr.addAttribute("", "src", "src", "CDATA", "embedded:" + data.getFileName());
- attr.addAttribute("", "alt", "alt", "CDATA", picture.getDescription());
-
- xhtml.startElement("img", attr);
- xhtml.endElement("img");
- }
- }
- }
-
- if (addedHREF) {
- xhtml.endElement("a");
- }
-
- return tfmtg;
- }
-
- private void processSDTRun(XWPFSDT run, XHTMLContentHandler xhtml)
- throws SAXException, XmlException, IOException {
- xhtml.characters(run.getContent().getText());
- }
-
- private void extractTable(XWPFTable table, XWPFListManager listManager,
- XHTMLContentHandler xhtml)
- throws SAXException, XmlException, IOException {
- xhtml.startElement("table");
- xhtml.startElement("tbody");
- for (XWPFTableRow row : table.getRows()) {
- xhtml.startElement("tr");
- for (ICell cell : row.getTableICells()) {
- xhtml.startElement("td");
- if (cell instanceof XWPFTableCell) {
- extractIBodyText((XWPFTableCell) cell, listManager, xhtml);
- } else if (cell instanceof XWPFSDTCell) {
- xhtml.characters(((XWPFSDTCell) cell).getContent().getText());
- }
- xhtml.endElement("td");
- }
- xhtml.endElement("tr");
- }
- xhtml.endElement("tbody");
- xhtml.endElement("table");
- }
-
- private void extractFooters(
- XHTMLContentHandler xhtml, XWPFHeaderFooterPolicy hfPolicy,
- XWPFListManager listManager)
- throws SAXException, XmlException, IOException {
- // footers
- if (hfPolicy.getFirstPageFooter() != null) {
- extractHeaderText(xhtml, hfPolicy.getFirstPageFooter(), listManager);
- }
- if (hfPolicy.getEvenPageFooter() != null) {
- extractHeaderText(xhtml, hfPolicy.getEvenPageFooter(), listManager);
- }
- if (hfPolicy.getDefaultFooter() != null) {
- extractHeaderText(xhtml, hfPolicy.getDefaultFooter(), listManager);
- }
- }
-
- private void extractHeaders(
- XHTMLContentHandler xhtml, XWPFHeaderFooterPolicy hfPolicy, XWPFListManager listManager)
- throws SAXException, XmlException, IOException {
- if (hfPolicy == null) return;
-
- if (hfPolicy.getFirstPageHeader() != null) {
- extractHeaderText(xhtml, hfPolicy.getFirstPageHeader(), listManager);
- }
-
- if (hfPolicy.getEvenPageHeader() != null) {
- extractHeaderText(xhtml, hfPolicy.getEvenPageHeader(), listManager);
- }
-
- if (hfPolicy.getDefaultHeader() != null) {
- extractHeaderText(xhtml, hfPolicy.getDefaultHeader(), listManager);
- }
- }
-
- private void extractHeaderText(XHTMLContentHandler xhtml, XWPFHeaderFooter header, XWPFListManager listManager) throws SAXException, XmlException, IOException {
-
- for (IBodyElement e : header.getBodyElements()) {
- if (e instanceof XWPFParagraph) {
- extractParagraph((XWPFParagraph) e, listManager, xhtml);
- } else if (e instanceof XWPFTable) {
- extractTable((XWPFTable) e, listManager, xhtml);
- } else if (e instanceof XWPFSDT) {
- extractSDT((XWPFSDT) e, xhtml);
- }
- }
- }
-
- /**
- * Word documents are simple, they only have the one
- * main part
- */
- @Override
- protected List<PackagePart> getMainDocumentParts() {
- List<PackagePart> parts = new ArrayList<PackagePart>();
- parts.add(document.getPackagePart());
- return parts;
- }
-
- private class TmpFormatting {
- private boolean bold = false;
- private boolean italic = false;
-
- private TmpFormatting(boolean bold, boolean italic) {
- this.bold = bold;
- this.italic = italic;
- }
-
- public boolean isBold() {
- return bold;
- }
-
- public void setBold(boolean bold) {
- this.bold = bold;
- }
-
- public boolean isItalic() {
- return italic;
- }
-
- public void setItalic(boolean italic) {
- this.italic = italic;
- }
-
- }
-
-}
+/*
+ * 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.tika.parser.microsoft.ooxml;
+
+import javax.xml.namespace.QName;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.poi.openxml4j.opc.PackagePart;
+import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
+import org.apache.poi.xwpf.model.XWPFCommentsDecorator;
+import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
+import org.apache.poi.xwpf.usermodel.BodyType;
+import org.apache.poi.xwpf.usermodel.IBody;
+import org.apache.poi.xwpf.usermodel.IBodyElement;
+import org.apache.poi.xwpf.usermodel.ICell;
+import org.apache.poi.xwpf.usermodel.IRunElement;
+import org.apache.poi.xwpf.usermodel.ISDTContent;
+import org.apache.poi.xwpf.usermodel.XWPFDocument;
+import org.apache.poi.xwpf.usermodel.XWPFHeaderFooter;
+import org.apache.poi.xwpf.usermodel.XWPFHyperlink;
+import org.apache.poi.xwpf.usermodel.XWPFHyperlinkRun;
+import org.apache.poi.xwpf.usermodel.XWPFParagraph;
+import org.apache.poi.xwpf.usermodel.XWPFPicture;
+import org.apache.poi.xwpf.usermodel.XWPFPictureData;
+import org.apache.poi.xwpf.usermodel.XWPFRun;
+import org.apache.poi.xwpf.usermodel.XWPFSDT;
+import org.apache.poi.xwpf.usermodel.XWPFSDTCell;
+import org.apache.poi.xwpf.usermodel.XWPFStyle;
+import org.apache.poi.xwpf.usermodel.XWPFStyles;
+import org.apache.poi.xwpf.usermodel.XWPFTable;
+import org.apache.poi.xwpf.usermodel.XWPFTableCell;
+import org.apache.poi.xwpf.usermodel.XWPFTableRow;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.parser.microsoft.WordExtractor;
+import org.apache.tika.parser.microsoft.WordExtractor.TagAndStyle;
+import org.apache.tika.sax.XHTMLContentHandler;
+import org.apache.xmlbeans.XmlCursor;
+import org.apache.xmlbeans.XmlException;
+import org.apache.xmlbeans.XmlObject;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTObject;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;
+import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSectPr;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+public class XWPFWordExtractorDecorator extends AbstractOOXMLExtractor {
+
+ // could be improved by using the real delimiter in xchFollow [MS-DOC], v20140721, 2.4.6.3, Part 3, Step 3
+ private static final String LIST_DELIMITER = " ";
+
+
+ private XWPFDocument document;
+ private XWPFStyles styles;
+
+ public XWPFWordExtractorDecorator(ParseContext context, XWPFWordExtractor extractor) {
+ super(context, extractor);
+
+ document = (XWPFDocument) extractor.getDocument();
+ styles = document.getStyles();
+ }
+
+ /**
+ * @see org.apache.poi.xwpf.extractor.XWPFWordExtractor#getText()
+ */
+ @Override
+ protected void buildXHTML(XHTMLContentHandler xhtml)
+ throws SAXException, XmlException, IOException {
+ XWPFHeaderFooterPolicy hfPolicy = document.getHeaderFooterPolicy();
+ XWPFListManager listManager = new XWPFListManager(document);
+ // headers
+ if (hfPolicy != null) {
+ extractHeaders(xhtml, hfPolicy, listManager);
+ }
+
+ // process text in the order that it occurs in
+ extractIBodyText(document, listManager, xhtml);
+
+ // then all document tables
+ if (hfPolicy != null) {
+ extractFooters(xhtml, hfPolicy, listManager);
+ }
+ }
+
+ private void extractIBodyText(IBody bodyElement, XWPFListManager listManager,
+ XHTMLContentHandler xhtml)
+ throws SAXException, XmlException, IOException {
+ for (IBodyElement element : bodyElement.getBodyElements()) {
+ if (element instanceof XWPFParagraph) {
+ XWPFParagraph paragraph = (XWPFParagraph) element;
+ extractParagraph(paragraph, listManager, xhtml);
+ }
+ if (element instanceof XWPFTable) {
+ XWPFTable table = (XWPFTable) element;
+ extractTable(table, listManager, xhtml);
+ }
+ if (element instanceof XWPFSDT) {
+ extractSDT((XWPFSDT) element, xhtml);
+ }
+
+ }
+ }
+
+ private void extractSDT(XWPFSDT element, XHTMLContentHandler xhtml) throws SAXException,
+ XmlException, IOException {
+ ISDTContent content = element.getContent();
+ String tag = "p";
+ xhtml.startElement(tag);
+ xhtml.characters(content.getText());
+ xhtml.endElement(tag);
+ }
+
+ private void extractParagraph(XWPFParagraph paragraph, XWPFListManager listManager,
+ XHTMLContentHandler xhtml)
+ throws SAXException, XmlException, IOException {
+ // If this paragraph is actually a whole new section, then
+ // it could have its own headers and footers
+ // Check and handle if so
+ XWPFHeaderFooterPolicy headerFooterPolicy = null;
+ if (paragraph.getCTP().getPPr() != null) {
+ CTSectPr ctSectPr = paragraph.getCTP().getPPr().getSectPr();
+ if (ctSectPr != null) {
+ headerFooterPolicy =
+ new XWPFHeaderFooterPolicy(document, ctSectPr);
+ extractHeaders(xhtml, headerFooterPolicy, listManager);
+ }
+ }
+
+ // Is this a paragraph, or a heading?
+ String tag = "p";
+ String styleClass = null;
+ if (paragraph.getStyleID() != null) {
+ XWPFStyle style = styles.getStyle(
+ paragraph.getStyleID()
+ );
+
+ if (style != null && style.getName() != null) {
+ TagAndStyle tas = WordExtractor.buildParagraphTagAndStyle(
+ style.getName(), paragraph.getPartType() == BodyType.TABLECELL
+ );
+ tag = tas.getTag();
+ styleClass = tas.getStyleClass();
+ }
+ }
+
+ if (styleClass == null) {
+ xhtml.startElement(tag);
+ } else {
+ xhtml.startElement(tag, "class", styleClass);
+ }
+
+ writeParagraphNumber(paragraph, listManager, xhtml);
+ // Output placeholder for any embedded docs:
+
+ // TODO: replace w/ XPath/XQuery:
+ for (XWPFRun run : paragraph.getRuns()) {
+ XmlCursor c = run.getCTR().newCursor();
+ c.selectPath("./*");
+ while (c.toNextSelection()) {
+ XmlObject o = c.getObject();
+ if (o instanceof CTObject) {
+ XmlCursor c2 = o.newCursor();
+ c2.selectPath("./*");
+ while (c2.toNextSelection()) {
+ XmlObject o2 = c2.getObject();
+
+ XmlObject embedAtt = o2.selectAttribute(new QName("Type"));
+ if (embedAtt != null && embedAtt.getDomNode().getNodeValue().equals("Embed")) {
+ // Type is "Embed"
+ XmlObject relIDAtt = o2.selectAttribute(new QName("http://schemas.openxmlformats.org/officeDocument/2006/relationships", "id"));
+ if (relIDAtt != null) {
+ String relID = relIDAtt.getDomNode().getNodeValue();
+ AttributesImpl attributes = new AttributesImpl();
+ attributes.addAttribute("", "class", "class", "CDATA", "embedded");
+ attributes.addAttribute("", "id", "id", "CDATA", relID);
+ xhtml.startElement("div", attributes);
+ xhtml.endElement("div");
+ }
+ }
+ }
+ c2.dispose();
+ }
+ }
+
+ c.dispose();
+ }
+
+ // Attach bookmarks for the paragraph
+ // (In future, we might put them in the right place, for now
+ // we just put them in the correct paragraph)
+ for (int i = 0; i < paragraph.getCTP().sizeOfBookmarkStartArray(); i++) {
+ CTBookmark bookmark = paragraph.getCTP().getBookmarkStartArray(i);
+ xhtml.startElement("a", "name", bookmark.getName());
+ xhtml.endElement("a");
+ }
+
+ TmpFormatting fmtg = new TmpFormatting(false, false);
+
+ // Do the iruns
+ for (IRunElement run : paragraph.getIRuns()) {
+ if (run instanceof XWPFSDT) {
+ fmtg = closeStyleTags(xhtml, fmtg);
+ processSDTRun((XWPFSDT) run, xhtml);
+ //for now, we're ignoring formatting in sdt
+ //if you hit an sdt reset to false
+ fmtg.setBold(false);
+ fmtg.setItalic(false);
+ } else {
+ fmtg = processRun((XWPFRun) run, paragraph, xhtml, fmtg);
+ }
+ }
+ closeStyleTags(xhtml, fmtg);
+
+
+ // Now do any comments for the paragraph
+ XWPFCommentsDecorator comments = new XWPFCommentsDecorator(paragraph, null);
+ String commentText = comments.getCommentText();
+ if (commentText != null && commentText.length() > 0) {
+ xhtml.characters(commentText);
+ }
+
+ String footnameText = paragraph.getFootnoteText();
+ if (footnameText != null && footnameText.length() > 0) {
+ xhtml.characters(footnameText + "\n");
+ }
+
+ // Also extract any paragraphs embedded in text boxes:
+ for (XmlObject embeddedParagraph : paragraph.getCTP().selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent/w:p")) {
+ extractParagraph(new XWPFParagraph(CTP.Factory.parse(embeddedParagraph.xmlText()), paragraph.getBody()), listManager, xhtml);
+ }
+
+ // Finish this paragraph
+ xhtml.endElement(tag);
+
+ if (headerFooterPolicy != null) {
+ extractFooters(xhtml, headerFooterPolicy, listManager);
+ }
+ }
+
+ private void writeParagraphNumber(XWPFParagraph paragraph,
+ XWPFListManager listManager,
+ XHTMLContentHandler xhtml) throws SAXException {
+ if (paragraph.getNumIlvl() == null) {
+ return;
+ }
+ String number = listManager.getFormattedNumber(paragraph);
+ if (number != null) {
+ xhtml.characters(number);
+ }
+
+ }
+
+ private TmpFormatting closeStyleTags(XHTMLContentHandler xhtml,
+ TmpFormatting fmtg) throws SAXException {
+ // Close any still open style tags
+ if (fmtg.isItalic()) {
+ xhtml.endElement("i");
+ fmtg.setItalic(false);
+ }
+ if (fmtg.isBold()) {
+ xhtml.endElement("b");
+ fmtg.setBold(false);
+ }
+ return fmtg;
+ }
+
+ private TmpFormatting processRun(XWPFRun run, XWPFParagraph paragraph,
+ XHTMLContentHandler xhtml, TmpFormatting tfmtg)
+ throws SAXException, XmlException, IOException {
+ // True if we are currently in the named style tag:
+ if (run.isBold() != tfmtg.isBold()) {
+ if (tfmtg.isItalic()) {
+ xhtml.endElement("i");
+ tfmtg.setItalic(false);
+ }
+ if (run.isBold()) {
+ xhtml.startElement("b");
+ } else {
+ xhtml.endElement("b");
+ }
+ tfmtg.setBold(run.isBold());
+ }
+
+ if (run.isItalic() != tfmtg.isItalic()) {
+ if (run.isItalic()) {
+ xhtml.startElement("i");
+ } else {
+ xhtml.endElement("i");
+ }
+ tfmtg.setItalic(run.isItalic());
+ }
+
+ boolean addedHREF = false;
+ if (run instanceof XWPFHyperlinkRun) {
+ XWPFHyperlinkRun linkRun = (XWPFHyperlinkRun) run;
+ XWPFHyperlink link = linkRun.getHyperlink(document);
+ if (link != null && link.getURL() != null) {
+ xhtml.startElement("a", "href", link.getURL());
+ addedHREF = true;
+ } else if (linkRun.getAnchor() != null && linkRun.getAnchor().length() > 0) {
+ xhtml.startElement("a", "href", "#" + linkRun.getAnchor());
+ addedHREF = true;
+ }
+ }
+
+ xhtml.characters(run.toString());
+
+ // If we have any pictures, output them
+ for (XWPFPicture picture : run.getEmbeddedPictures()) {
+ if (paragraph.getDocument() != null) {
+ XWPFPictureData data = picture.getPictureData();
+ if (data != null) {
+ AttributesImpl attr = new AttributesImpl();
+
+ attr.addAttribute("", "src", "src", "CDATA", "embedded:" + data.getFileName());
+ attr.addAttribute("", "alt", "alt", "CDATA", picture.getDescription());
+
+ xhtml.startElement("img", attr);
+ xhtml.endElement("img");
+ }
+ }
+ }
+
+ if (addedHREF) {
+ xhtml.endElement("a");
+ }
+
+ return tfmtg;
+ }
+
+ private void processSDTRun(XWPFSDT run, XHTMLContentHandler xhtml)
+ throws SAXException, XmlException, IOException {
+ xhtml.characters(run.getContent().getText());
+ }
+
+ private void extractTable(XWPFTable table, XWPFListManager listManager,
+ XHTMLContentHandler xhtml)
+ throws SAXException, XmlException, IOException {
+ xhtml.startElement("table");
+ xhtml.startElement("tbody");
+ for (XWPFTableRow row : table.getRows()) {
+ xhtml.startElement("tr");
+ for (ICell cell : row.getTableICells()) {
+ xhtml.startElement("td");
+ if (cell instanceof XWPFTableCell) {
+ extractIBodyText((XWPFTableCell) cell, listManager, xhtml);
+ } else if (cell instanceof XWPFSDTCell) {
+ xhtml.characters(((XWPFSDTCell) cell).getContent().getText());
+ }
+ xhtml.endElement("td");
+ }
+ xhtml.endElement("tr");
+ }
+ xhtml.endElement("tbody");
+ xhtml.endElement("table");
+ }
+
+ private void extractFooters(
+ XHTMLContentHandler xhtml, XWPFHeaderFooterPolicy hfPolicy,
+ XWPFListManager listManager)
+ throws SAXException, XmlException, IOException {
+ // footers
+ if (hfPolicy.getFirstPageFooter() != null) {
+ extractHeaderText(xhtml, hfPolicy.getFirstPageFooter(), listManager);
+ }
+ if (hfPolicy.getEvenPageFooter() != null) {
+ extractHeaderText(xhtml, hfPolicy.getEvenPageFooter(), listManager);
+ }
+ if (hfPolicy.getDefaultFooter() != null) {
+ extractHeaderText(xhtml, hfPolicy.getDefaultFooter(), listManager);
+ }
+ }
+
+ private void extractHeaders(
+ XHTMLContentHandler xhtml, XWPFHeaderFooterPolicy hfPolicy, XWPFListManager listManager)
+ throws SAXException, XmlException, IOException {
+ if (hfPolicy == null) return;
+
+ if (hfPolicy.getFirstPageHeader() != null) {
+ extractHeaderText(xhtml, hfPolicy.getFirstPageHeader(), listManager);
+ }
+
+ if (hfPolicy.getEvenPageHeader() != null) {
+ extractHeaderText(xhtml, hfPolicy.getEvenPageHeader(), listManager);
+ }
+
+ if (hfPolicy.getDefaultHeader() != null) {
+ extractHeaderText(xhtml, hfPolicy.getDefaultHeader(), listManager);
+ }
+ }
+
+ private void extractHeaderText(XHTMLContentHandler xhtml, XWPFHeaderFooter header, XWPFListManager listManager) throws SAXException, XmlException, IOException {
+
+ for (IBodyElement e : header.getBodyElements()) {
+ if (e instanceof XWPFParagraph) {
+ extractParagraph((XWPFParagraph) e, listManager, xhtml);
+ } else if (e instanceof XWPFTable) {
+ extractTable((XWPFTable) e, listManager, xhtml);
+ } else if (e instanceof XWPFSDT) {
+ extractSDT((XWPFSDT) e, xhtml);
+ }
+ }
+ }
+
+ /**
+ * Word documents are simple, they only have the one
+ * main part
+ */
+ @Override
+ protected List<PackagePart> getMainDocumentParts() {
+ List<PackagePart> parts = new ArrayList<PackagePart>();
+ parts.add(document.getPackagePart());
+ return parts;
+ }
+
+ private class TmpFormatting {
+ private boolean bold = false;
+ private boolean italic = false;
+
+ private TmpFormatting(boolean bold, boolean italic) {
+ this.bold = bold;
+ this.italic = italic;
+ }
+
+ public boolean isBold() {
+ return bold;
+ }
+
+ public void setBold(boolean bold) {
+ this.bold = bold;
+ }
+
+ public boolean isItalic() {
+ return italic;
+ }
+
+ public void setItalic(boolean italic) {
+ this.italic = italic;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/tika/blob/d8231f48/tika-parser-modules/tika-parser-office-module/src/test/java/org/apache/tika/parser/microsoft/WriteProtectedParserTest.java
----------------------------------------------------------------------
diff --git a/tika-parser-modules/tika-parser-office-module/src/test/java/org/apache/tika/parser/microsoft/WriteProtectedParserTest.java b/tika-parser-modules/tika-parser-office-module/src/test/java/org/apache/tika/parser/microsoft/WriteProtectedParserTest.java
index 931ecd0..aeca99b 100644
--- a/tika-parser-modules/tika-parser-office-module/src/test/java/org/apache/tika/parser/microsoft/WriteProtectedParserTest.java
+++ b/tika-parser-modules/tika-parser-office-module/src/test/java/org/apache/tika/parser/microsoft/WriteProtectedParserTest.java
@@ -1,42 +1,42 @@
-/*
- * 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.tika.parser.microsoft;
-
-import static org.apache.tika.TikaTest.assertContains;
-
-import java.io.InputStream;
-
-import org.apache.tika.metadata.Metadata;
-import org.apache.tika.parser.ParseContext;
-import org.apache.tika.sax.BodyContentHandler;
-import org.junit.Test;
-import org.xml.sax.ContentHandler;
-
-public class WriteProtectedParserTest {
-
- @Test
- public void testWriteProtected() throws Exception {
- InputStream input = ExcelParserTest.class.getResourceAsStream(
- "/test-documents/protect.xlsx");
-
- Metadata metadata = new Metadata();
- ContentHandler handler = new BodyContentHandler();
- new OfficeParser().parse(input, handler, metadata, new ParseContext());
- String content = handler.toString();
- assertContains("Office", content);
- }
-}
+/*
+ * 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.tika.parser.microsoft;
+
+import static org.apache.tika.TikaTest.assertContains;
+
+import java.io.InputStream;
+
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.ParseContext;
+import org.apache.tika.sax.BodyContentHandler;
+import org.junit.Test;
+import org.xml.sax.ContentHandler;
+
+public class WriteProtectedParserTest {
+
+ @Test
+ public void testWriteProtected() throws Exception {
+ InputStream input = ExcelParserTest.class.getResourceAsStream(
+ "/test-documents/protect.xlsx");
+
+ Metadata metadata = new Metadata();
+ ContentHandler handler = new BodyContentHandler();
+ new OfficeParser().parse(input, handler, metadata, new ParseContext());
+ String content = handler.toString();
+ assertContains("Office", content);
+ }
+}