diff --git a/ooxml/XWPF/Usermodel/XWPFDocument.cs b/ooxml/XWPF/Usermodel/XWPFDocument.cs index 48d6794df..e5102d8bf 100644 --- a/ooxml/XWPF/Usermodel/XWPFDocument.cs +++ b/ooxml/XWPF/Usermodel/XWPFDocument.cs @@ -27,6 +27,7 @@ namespace NPOI.XWPF.UserModel using System.Xml.Serialization; using System.Diagnostics; using NPOI.OOXML.XWPF.Util; + using System.Linq; /** *

High(ish) level class for working with .docx files.

@@ -217,6 +218,11 @@ private void InitHyperlinks() { throw new POIXMLException(e); } + hyperlinks.AddRange(footers.SelectMany(footer => footer.GetHyperlinks())); + if (footnotes != null) + { + hyperlinks.AddRange(footnotes.GetHyperlinks()); + } } private void InitFootnotes() diff --git a/ooxml/XWPF/Usermodel/XWPFFooter.cs b/ooxml/XWPF/Usermodel/XWPFFooter.cs index 6e69e27e4..934a1ab27 100644 --- a/ooxml/XWPF/Usermodel/XWPFFooter.cs +++ b/ooxml/XWPF/Usermodel/XWPFFooter.cs @@ -22,12 +22,14 @@ namespace NPOI.XWPF.UserModel using System.IO; using System.Xml; using System.Xml.Serialization; + using System.Collections.Generic; /** * Sketch of XWPF footer class */ public class XWPFFooter : XWPFHeaderFooter { + protected List hyperlinks = new List(); public XWPFFooter() //: base() { @@ -68,6 +70,7 @@ public XWPFFooter(XWPFDocument doc, CT_HdrFtr hdrFtr) tables.Add(t); } } + } public XWPFFooter(POIXMLDocumentPart parent, PackagePart part) @@ -112,7 +115,8 @@ internal override void OnDocumentRead() { base.OnDocumentRead(); FtrDocument ftrDocument = null; - try { + try + { XmlDocument xmldoc = ConvertStreamToXml(GetPackagePart().GetInputStream()); ftrDocument = FtrDocument.Parse(xmldoc, NamespaceManager); headerFooter = ftrDocument.Ftr; @@ -138,9 +142,48 @@ internal override void OnDocumentRead() bodyElements.Add(c); } } - } catch (Exception e) { + } + catch (Exception e) + { throw new POIXMLException(e); } + InitHyperlinks(); + } + + private void InitHyperlinks() + { + try + { + IEnumerator relIter = + GetPackagePart().GetRelationshipsByType(XWPFRelation.HYPERLINK.Relation).GetEnumerator(); + while (relIter.MoveNext()) + { + PackageRelationship rel = relIter.Current; + hyperlinks.Add(new XWPFHyperlink(rel.Id, rel.TargetUri.OriginalString)); + } + } + catch (InvalidDataException e) + { + throw new POIXMLException(e); + } + } + + public List GetHyperlinks() + { + return hyperlinks; + } + + public XWPFHyperlink GetHyperlinkByID(string id) + { + IEnumerator iter = hyperlinks.GetEnumerator(); + while (iter.MoveNext()) + { + XWPFHyperlink link = iter.Current; + if (link.Id.Equals(id)) + return link; + } + + return null; } /** diff --git a/ooxml/XWPF/Usermodel/XWPFFootnotes.cs b/ooxml/XWPF/Usermodel/XWPFFootnotes.cs index 4aba717ab..b4fcc3237 100644 --- a/ooxml/XWPF/Usermodel/XWPFFootnotes.cs +++ b/ooxml/XWPF/Usermodel/XWPFFootnotes.cs @@ -35,6 +35,7 @@ public class XWPFFootnotes : POIXMLDocumentPart { private List listFootnote = new List(); private CT_Footnotes ctFootnotes; + private List hyperlinks = new List(); protected XWPFDocument document; @@ -96,8 +97,26 @@ internal override void OnDocumentRead() listFootnote.Add(new XWPFFootnote(note, this)); } } + InitHyperlinks(); } + private void InitHyperlinks() + { + try + { + IEnumerator relIter = + GetPackagePart().GetRelationshipsByType(XWPFRelation.HYPERLINK.Relation).GetEnumerator(); + while (relIter.MoveNext()) + { + PackageRelationship rel = relIter.Current; + hyperlinks.Add(new XWPFHyperlink(rel.Id, rel.TargetUri.OriginalString)); + } + } + catch (InvalidDataException e) + { + throw new POIXMLException(e); + } + } protected internal override void Commit() { @@ -220,6 +239,23 @@ public XWPFDocument GetXWPFDocument() } } + public XWPFHyperlink GetHyperlinkByID(String id) + { + IEnumerator iter = hyperlinks.GetEnumerator(); + while (iter.MoveNext()) + { + XWPFHyperlink link = iter.Current; + if (link.Id.Equals(id)) + return link; + } + + return null; + } + + public List GetHyperlinks() + { + return hyperlinks; + } }//end class diff --git a/testcases/ooxml/XWPF/Model/TestXWPFDecorators.cs b/testcases/ooxml/XWPF/Model/TestXWPFDecorators.cs index ab7c94136..8f060c5e7 100644 --- a/testcases/ooxml/XWPF/Model/TestXWPFDecorators.cs +++ b/testcases/ooxml/XWPF/Model/TestXWPFDecorators.cs @@ -20,6 +20,7 @@ namespace TestCases.XWPF.Model using NPOI.XWPF.Model; using NPOI.XWPF.UserModel; using NUnit.Framework; + using System.Linq; /** * Tests for the various XWPF decorators @@ -30,12 +31,17 @@ public class TestXWPFDecorators private XWPFDocument simple; private XWPFDocument hyperlink; private XWPFDocument comments; + private XWPFDocument footerhyperlink; + private XWPFDocument footnotehyperlink; + [SetUp] public void SetUp() { simple = XWPFTestDataSamples.OpenSampleDocument("SampleDoc.docx"); hyperlink = XWPFTestDataSamples.OpenSampleDocument("TestDocument.docx"); comments = XWPFTestDataSamples.OpenSampleDocument("WordWithAttachments.docx"); + footerhyperlink = XWPFTestDataSamples.OpenSampleDocument("TestHyperlinkInFooterDocument.docx"); + footnotehyperlink = XWPFTestDataSamples.OpenSampleDocument("TestHyperlinkInFootnotes.docx"); } [Test] @@ -66,6 +72,50 @@ public void TestHyperlink() Assert.AreEqual("http://poi.apache.org/", link.GetHyperlink(hyperlink).URL); } + [Test] + public void TestHyperlinkInFooter() + { + Assert.AreEqual(1, footerhyperlink.Paragraphs.Count); + + // Simple text + XWPFParagraph paragraph = footerhyperlink.Paragraphs[(0)]; + Assert.AreEqual("This is a test document.", paragraph.ParagraphText); + Assert.AreEqual(2, paragraph.Runs.Count); + + Assert.AreEqual(3, footerhyperlink.FooterList.Count); + + Assert.AreEqual(1, footerhyperlink.GetHyperlinks().Length); + + XWPFHyperlinkRun run = (XWPFHyperlinkRun)((XWPFParagraph)footerhyperlink.FooterList[2].BodyElements[0]).Runs[1]; + Assert.AreEqual("http://poi.apache.org/", run.GetHyperlink(footerhyperlink).URL); + + Assert.AreEqual(1, footerhyperlink.FooterList[2].GetHyperlinks().Count); + + XWPFHyperlink link = footerhyperlink.GetHyperlinks().First(); + Assert.AreEqual("http://poi.apache.org/", link.URL); + } + + [Test] + public void TestHyperlinkInFootnotes() + { + Assert.AreEqual(1, footerhyperlink.Paragraphs.Count); + + // Simple text + XWPFParagraph paragraph = footnotehyperlink.Paragraphs[(0)]; + Assert.AreEqual("This is a test document.[footnoteRef:1]", paragraph.ParagraphText); + Assert.AreEqual(3, paragraph.Runs.Count); + + Assert.AreEqual(3, footnotehyperlink.GetFootnotes().Count); + + Assert.AreEqual(1, footnotehyperlink.GetHyperlinks().Length); + + XWPFHyperlinkRun run = (XWPFHyperlinkRun)footnotehyperlink.GetFootnotes()[2].Paragraphs[0].Runs[3]; + Assert.AreEqual("http://poi.apache.org/", run.GetHyperlink(footerhyperlink).URL); + + XWPFHyperlink link = footnotehyperlink.GetHyperlinks().First(); + Assert.AreEqual("http://poi.apache.org/", link.URL); + } + [Test] public void TestComments() { diff --git a/testcases/test-data/document/TestHyperlinkInFooterDocument.docx b/testcases/test-data/document/TestHyperlinkInFooterDocument.docx new file mode 100644 index 000000000..070c068ad Binary files /dev/null and b/testcases/test-data/document/TestHyperlinkInFooterDocument.docx differ diff --git a/testcases/test-data/document/TestHyperlinkInFootnotes.docx b/testcases/test-data/document/TestHyperlinkInFootnotes.docx new file mode 100644 index 000000000..fc8d2ddbf Binary files /dev/null and b/testcases/test-data/document/TestHyperlinkInFootnotes.docx differ