aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/docx/Numbering.java4
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/docx/NumberingXml.java36
-rw-r--r--src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java7
3 files changed, 43 insertions, 4 deletions
diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/Numbering.java b/src/main/java/org/zwobble/mammoth/internal/docx/Numbering.java
index 764bb87..1a39047 100644
--- a/src/main/java/org/zwobble/mammoth/internal/docx/Numbering.java
+++ b/src/main/java/org/zwobble/mammoth/internal/docx/Numbering.java
@@ -41,6 +41,10 @@ public class Numbering {
this.paragraphStyleId = paragraphStyleId;
}
+ public String levelIndex() {
+ return levelIndex;
+ }
+
public NumberingLevel toNumberingLevel() {
return new NumberingLevel(levelIndex, isOrdered);
}
diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/NumberingXml.java b/src/main/java/org/zwobble/mammoth/internal/docx/NumberingXml.java
index 5f811db..012d548 100644
--- a/src/main/java/org/zwobble/mammoth/internal/docx/NumberingXml.java
+++ b/src/main/java/org/zwobble/mammoth/internal/docx/NumberingXml.java
@@ -3,6 +3,7 @@ package org.zwobble.mammoth.internal.docx;
import org.zwobble.mammoth.internal.xml.XmlElement;
import org.zwobble.mammoth.internal.xml.XmlElementList;
+import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@@ -31,15 +32,42 @@ public class NumberingXml {
}
private static Map<String, Numbering.AbstractNumLevel> readAbstractNumLevels(XmlElement element) {
- return toMap(element.findChildren("w:lvl"), NumberingXml::readAbstractNumLevel);
+ Map<String, Numbering.AbstractNumLevel> levels = new HashMap<>();
+
+ // Some malformed documents define numbering levels without an index, and
+ // reference the numbering using a w:numPr element without a w:ilvl child.
+ // To handle such cases, we assume a level of 0 as a fallback.
+ Optional<Numbering.AbstractNumLevel> levelWithoutIndex = Optional.empty();
+
+ for (XmlElement levelElement : element.findChildren("w:lvl")) {
+ Map.Entry<Optional<String>, Numbering.AbstractNumLevel> entry =
+ readAbstractNumLevel(levelElement);
+
+ if (entry.getKey().isPresent()) {
+ levels.put(entry.getKey().get(), entry.getValue());
+ } else {
+ levelWithoutIndex = Optional.of(entry.getValue());
+ }
+ }
+
+ if (levelWithoutIndex.isPresent() && !levels.containsKey(levelWithoutIndex.get().levelIndex())) {
+ levels.put(levelWithoutIndex.get().levelIndex(), levelWithoutIndex.get());
+ }
+
+ return levels;
}
- private static Map.Entry<String, Numbering.AbstractNumLevel> readAbstractNumLevel(XmlElement element) {
- String levelIndex = element.getAttribute("w:ilvl");
+ private static Map.Entry<Optional<String>, Numbering.AbstractNumLevel> readAbstractNumLevel(XmlElement element) {
+ Optional<String> levelIndex = element.getAttributeOrNone("w:ilvl");
Optional<String> numFmt = element.findChildOrEmpty("w:numFmt").getAttributeOrNone("w:val");
boolean isOrdered = !numFmt.equals(Optional.of("bullet"));
Optional<String> paragraphStyleId = element.findChildOrEmpty("w:pStyle").getAttributeOrNone("w:val");
- return entry(levelIndex, new Numbering.AbstractNumLevel(levelIndex, isOrdered, paragraphStyleId));
+ Numbering.AbstractNumLevel abstractNumLevel = new Numbering.AbstractNumLevel(
+ levelIndex.orElse("0"),
+ isOrdered,
+ paragraphStyleId
+ );
+ return entry(levelIndex, abstractNumLevel);
}
private static Map<String, Numbering.Num> readNums(XmlElementList numElements) {
diff --git a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
index 649a47b..1f5aff4 100644
--- a/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
+++ b/src/main/java/org/zwobble/mammoth/internal/docx/StatefulBodyXmlReader.java
@@ -429,6 +429,13 @@ class StatefulBodyXmlReader {
}
}
+ // Some malformed documents define numbering levels without an index, and
+ // reference the numbering using a w:numPr element without a w:ilvl child.
+ // To handle such cases, we assume a level of 0 as a fallback.
+ if (numId.isPresent()) {
+ return numbering.findLevel(numId.get(), "0");
+ }
+
return Optional.empty();
}