From ddde81cf806a5534a01483b563651bd84cf7452d Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Sat, 13 Feb 2016 23:02:55 +0000 Subject: Read embedded blips in wp:inline --- .../java/org/zwobble/mammoth/documents/Image.java | 6 ++-- .../org/zwobble/mammoth/docx/BodyXmlReader.java | 39 ++++++++++++++++++++-- .../zwobble/mammoth/util/InputStreamSupplier.java | 9 +++++ .../org/zwobble/mammoth/xml/XmlElementList.java | 11 ++++++ 4 files changed, 58 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/zwobble/mammoth/util/InputStreamSupplier.java (limited to 'src/main/java/org') diff --git a/src/main/java/org/zwobble/mammoth/documents/Image.java b/src/main/java/org/zwobble/mammoth/documents/Image.java index 7435cbf..8022ea4 100644 --- a/src/main/java/org/zwobble/mammoth/documents/Image.java +++ b/src/main/java/org/zwobble/mammoth/documents/Image.java @@ -1,14 +1,12 @@ package org.zwobble.mammoth.documents; +import org.zwobble.mammoth.util.InputStreamSupplier; + import java.io.IOException; import java.io.InputStream; import java.util.Optional; public class Image implements DocumentElement { - @FunctionalInterface - public interface InputStreamSupplier { - InputStream open() throws IOException; - } private final Optional altText; private final Optional contentType; diff --git a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java b/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java index 4a0a169..4ac44d2 100644 --- a/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java +++ b/src/main/java/org/zwobble/mammoth/docx/BodyXmlReader.java @@ -3,9 +3,11 @@ package org.zwobble.mammoth.docx; import org.zwobble.mammoth.documents.*; import org.zwobble.mammoth.results.Result; import org.zwobble.mammoth.results.Warning; +import org.zwobble.mammoth.util.InputStreamSupplier; import org.zwobble.mammoth.util.MammothOptionals; import org.zwobble.mammoth.xml.XmlElement; import org.zwobble.mammoth.xml.XmlElementLike; +import org.zwobble.mammoth.xml.XmlElementList; import org.zwobble.mammoth.xml.XmlNode; import java.util.Optional; @@ -76,6 +78,9 @@ public class BodyXmlReader { case "v:imagedata": return readImagedata(element); + case "wp:inline": + return readInline(element); + case "w:ins": case "w:smartTag": case "w:drawing": @@ -245,13 +250,41 @@ public class BodyXmlReader { private ReadResult readImagedata(XmlElement element) { Optional title = element.getAttributeOrNone("o:title"); String relationshipId = element.getAttribute("r:id"); - Relationship relationship = relationships.findRelationshipById(relationshipId); - String imagePath = "word/" + trimLeft(relationship.getTarget(), '/'); + String imagePath = relationshipIdToDocxPath(relationshipId); + return readImage(imagePath, title, () -> file.getInputStream(imagePath)); + } + + private ReadResult readInline(XmlElement element) { + Optional altText = element.findChildOrEmpty("wp:docPr").getAttributeOrNone("descr"); + XmlElementList blips = element.findChildren("a:graphic") + .findChildren("a:graphicData") + .findChildren("pic:pic") + .findChildren("pic:blipFill") + .findChildren("a:blip"); + return readBlips(blips, altText); + } + + private ReadResult readBlips(XmlElementList blips, Optional altText) { + return ReadResult.concat(transform(blips, blip -> readBlip(blip, altText))); + } + + private ReadResult readBlip(XmlElement blip, Optional altText) { + String relationshipId = blip.getAttribute("r:embed"); + String imagePath = relationshipIdToDocxPath(relationshipId); + return readImage(imagePath, altText, () -> file.getInputStream(imagePath)); + } + + private ReadResult readImage(String imagePath, Optional altText, InputStreamSupplier open) { Optional contentType = contentTypes.findContentType(imagePath); - Image image = new Image(title, contentType, () -> file.getInputStream(imagePath)); + Image image = new Image(altText, contentType, open); return success(image); } + private String relationshipIdToDocxPath(String relationshipId) { + Relationship relationship = relationships.findRelationshipById(relationshipId); + return "word/" + trimLeft(relationship.getTarget(), '/'); + } + private Optional readVal(XmlElementLike element, String name) { return element.findChildOrEmpty(name).getAttributeOrNone("w:val"); } diff --git a/src/main/java/org/zwobble/mammoth/util/InputStreamSupplier.java b/src/main/java/org/zwobble/mammoth/util/InputStreamSupplier.java new file mode 100644 index 0000000..0f42389 --- /dev/null +++ b/src/main/java/org/zwobble/mammoth/util/InputStreamSupplier.java @@ -0,0 +1,9 @@ +package org.zwobble.mammoth.util; + +import java.io.IOException; +import java.io.InputStream; + +@FunctionalInterface +public interface InputStreamSupplier { + InputStream open() throws IOException; +} diff --git a/src/main/java/org/zwobble/mammoth/xml/XmlElementList.java b/src/main/java/org/zwobble/mammoth/xml/XmlElementList.java index 9e46314..b6a68ad 100644 --- a/src/main/java/org/zwobble/mammoth/xml/XmlElementList.java +++ b/src/main/java/org/zwobble/mammoth/xml/XmlElementList.java @@ -1,5 +1,8 @@ package org.zwobble.mammoth.xml; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + import java.util.Iterator; import java.util.List; @@ -14,4 +17,12 @@ public class XmlElementList implements Iterable { public Iterator iterator() { return elements.iterator(); } + + public XmlElementList findChildren(String name) { + Iterable children = Iterables.concat( + Iterables.transform( + elements, + element -> element.findChildren(name))); + return new XmlElementList(ImmutableList.copyOf(children)); + } } -- cgit v1.2.3