diff --git a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/v07/handlers/HyperlinkTagHandler.java b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/v07/handlers/HyperlinkTagHandler.java index 9323edc0f..e8cdae12e 100644 --- a/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/v07/handlers/HyperlinkTagHandler.java +++ b/fesod-sheet/src/main/java/org/apache/fesod/sheet/analysis/v07/handlers/HyperlinkTagHandler.java @@ -25,7 +25,6 @@ package org.apache.fesod.sheet.analysis.v07.handlers; -import java.util.Optional; import org.apache.fesod.common.util.StringUtils; import org.apache.fesod.sheet.constant.ExcelXmlConstants; import org.apache.fesod.sheet.context.xlsx.XlsxReadContext; @@ -53,28 +52,29 @@ public void startElement(XlsxReadContext xlsxReadContext, String name, Attribute if (StringUtils.isEmpty(ref)) { return; } - // Hyperlink has 2 case: - // case 1,In the 'location' tag + // External hyperlinks store the target in the r:id relationship. + // When present, location contains the URI fragment. String location = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_LOCATION); - if (location != null) { - CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, location, ref); - xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); - xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); - return; - } - // case 2, In the 'r:id' tag, Then go to 'PackageRelationshipCollection' to get inside String rId = attributes.getValue(ExcelXmlConstants.ATTRIBUTE_RID); PackageRelationshipCollection packageRelationshipCollection = xlsxReadContext.xlsxReadSheetHolder().getPackageRelationshipCollection(); - if (rId == null || packageRelationshipCollection == null) { + PackageRelationship relationship = rId == null || packageRelationshipCollection == null + ? null + : packageRelationshipCollection.getRelationshipByID(rId); + String address; + if (relationship != null) { + address = relationship.getTargetURI().toString(); + if (location != null) { + address += "#" + location; + } + } else if (location != null) { + // Internal hyperlinks store their destination directly in location. + address = location; + } else { return; } - Optional.ofNullable(packageRelationshipCollection.getRelationshipByID(rId)) - .map(PackageRelationship::getTargetURI) - .ifPresent(uri -> { - CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, uri.toString(), ref); - xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); - xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); - }); + CellExtra cellExtra = new CellExtra(CellExtraTypeEnum.HYPERLINK, address, ref); + xlsxReadContext.readSheetHolder().setCellExtra(cellExtra); + xlsxReadContext.analysisEventProcessor().extra(xlsxReadContext); } } diff --git a/fesod-sheet/src/test/java/org/apache/fesod/sheet/converter/ExtraDataTest.java b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converter/ExtraDataTest.java index 1c13ad43c..de440fd00 100644 --- a/fesod-sheet/src/test/java/org/apache/fesod/sheet/converter/ExtraDataTest.java +++ b/fesod-sheet/src/test/java/org/apache/fesod/sheet/converter/ExtraDataTest.java @@ -26,6 +26,8 @@ package org.apache.fesod.sheet.converter; import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import org.apache.fesod.sheet.FesodSheet; import org.apache.fesod.sheet.context.AnalysisContext; @@ -124,4 +126,29 @@ public void extra(CellExtra extra, AnalysisContext context) { .sheet() .doRead(); } + + @Test + void readHyperlinkWithUrlFragment() { + // A1 links to https://example.com/page#section, stored as r:id plus location="section" + File file = readFile("extra" + File.separator + "extraHyperlinkFragment.xlsx"); + List hyperlinks = new ArrayList<>(); + FesodSheet.read(file, new ReadListener() { + @Override + public void invoke(Object data, AnalysisContext context) {} + + @Override + public void doAfterAllAnalysed(AnalysisContext context) {} + + @Override + public void extra(CellExtra extra, AnalysisContext context) { + hyperlinks.add(extra.getText()); + } + }) + .extraRead(CellExtraTypeEnum.HYPERLINK) + .sheet() + .doRead(); + + Assertions.assertEquals( + Arrays.asList("https://example.com/page#section", "https://example.com/plain"), hyperlinks); + } } diff --git a/fesod-sheet/src/test/resources/extra/extraHyperlinkFragment.xlsx b/fesod-sheet/src/test/resources/extra/extraHyperlinkFragment.xlsx new file mode 100644 index 000000000..d5cb4a54d Binary files /dev/null and b/fesod-sheet/src/test/resources/extra/extraHyperlinkFragment.xlsx differ