From 050781fdde57ff833d6a886f32b4109c8898ddc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sun, 23 Apr 2023 19:28:05 +0800 Subject: [PATCH] add api AppendFile --- structdoc.go | 52 ++++++++++++++++++++++++++++++++++++++++++---------- unpack.go | 22 +++++++++++++++++++--- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/structdoc.go b/structdoc.go index 5a27f0b..91cc0a5 100644 --- a/structdoc.go +++ b/structdoc.go @@ -284,23 +284,39 @@ newdoclop: return } +func (r *Run) copymedia(to *Docx) *Run { + nr := *r + nr.Children = make([]interface{}, 0, len(r.Children)) + nr.file = to + for _, rc := range r.Children { + if d, ok := rc.(*Drawing); ok { + nr.Children = append(nr.Children, d.copymedia(to)) + continue + } + nr.Children = append(nr.Children, rc) + } + return &nr +} + func (p *Paragraph) copymedia(to *Docx) (np Paragraph) { np = *p np.Children = make([]interface{}, 0, len(p.Children)) np.file = to for _, pc := range p.Children { if r, ok := pc.(*Run); ok { - nr := *r - nr.Children = make([]interface{}, 0, len(r.Children)) - nr.file = to - for _, rc := range r.Children { - if d, ok := rc.(*Drawing); ok { - nr.Children = append(nr.Children, d.copymedia(to)) - continue - } - nr.Children = append(nr.Children, rc) + np.Children = append(np.Children, r.copymedia(to)) + continue + } + if h, ok := pc.(*Hyperlink); ok { + tgt, err := p.file.ReferTarget(h.ID) + if err != nil { + continue } - np.Children = append(np.Children, &nr) + rid := to.addLinkRelation(tgt) + np.Children = append(np.Children, &Hyperlink{ + ID: rid, + Run: *h.Run.copymedia(to), + }) continue } np.Children = append(np.Children, pc) @@ -330,3 +346,19 @@ func (t *Table) copymedia(to *Docx) (nt Table) { } return } + +// AppendFile appends all contents in af to f +func (f *Docx) AppendFile(af *Docx) { + for _, item := range af.Document.Body.Items { + switch o := item.(type) { + case *Paragraph: + np := o.copymedia(f) + f.Document.Body.Items = append(f.Document.Body.Items, &np) + case *Table: + nt := o.copymedia(f) + f.Document.Body.Items = append(f.Document.Body.Items, &nt) + default: + f.Document.Body.Items = append(f.Document.Body.Items, o) + } + } +} diff --git a/unpack.go b/unpack.go index 97672ff..8b7f8a9 100644 --- a/unpack.go +++ b/unpack.go @@ -23,7 +23,9 @@ package docx import ( "archive/zip" "encoding/xml" + "errors" "io" + "strconv" "strings" ) @@ -108,9 +110,23 @@ func (f *Docx) parseDocRelation(file *zip.File) error { defer zf.Close() f.docRelation.Xmlns = XMLNS_R - //TODO: find last rID - f.rID = 100000 - return xml.NewDecoder(zf).Decode(&f.docRelation) + err = xml.NewDecoder(zf).Decode(&f.docRelation) + if err != nil { + return err + } + for _, r := range f.docRelation.Relationship { + if !strings.HasPrefix(r.ID, "rId") { + return errors.New("invalid rel ID: " + r.ID) + } + id, err := strconv.ParseUint(r.ID[3:], 10, 64) + if err != nil { + return err + } + if f.rID < uintptr(id) { + f.rID = uintptr(id) + } + } + return nil } // parseMedia add the media into Docx struct