From 64b3464cbf43cb4e2fdea1fcd8e780cb809f4cc9 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: Thu, 2 Mar 2023 18:07:53 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AE=8C=E5=96=84=20table=20?=
=?UTF-8?q?canvas?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apidrawing.go | 4 +-
apishape.go | 83 ++++++-
cmd/main/main.go | 15 +-
empty.go | 14 +-
id.go | 20 ++
structcanvas.go | 25 +-
structdrawing.go | 41 +++-
structeffects.go | 64 +++++-
structpara.go | 93 ++++++--
structrel_test.go | 12 +-
structrun.go | 35 ++-
structshape.go | 441 +++++++++++++++++++++++++++++++++++-
structshape_test.go | 38 +++-
structtable.go | 8 +-
xml/a4/[Content_Types].xml | 2 -
xml/a4/word/settings.xml | 56 -----
xml/a4/word/webSettings.xml | 11 -
17 files changed, 806 insertions(+), 156 deletions(-)
delete mode 100755 xml/a4/word/settings.xml
delete mode 100755 xml/a4/word/webSettings.xml
diff --git a/apidrawing.go b/apidrawing.go
index e20614e..90015ee 100644
--- a/apidrawing.go
+++ b/apidrawing.go
@@ -69,7 +69,7 @@ func (p *Paragraph) AddInlineDrawing(pic []byte) (*Run, error) {
XMLA: XMLNS_DRAWINGML_MAIN,
GraphicData: &AGraphicData{
URI: XMLNS_PICTURE,
- Pic: &PICPic{
+ Pic: &Picture{
XMLPIC: XMLNS_DRAWINGML_PICTURE,
NonVisualPicProperties: &PICNonVisualPicProperties{
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
@@ -179,7 +179,7 @@ func (p *Paragraph) AddAnchorDrawing(pic []byte) (*Run, error) {
XMLA: XMLNS_DRAWINGML_MAIN,
GraphicData: &AGraphicData{
URI: XMLNS_PICTURE,
- Pic: &PICPic{
+ Pic: &Picture{
XMLPIC: XMLNS_DRAWINGML_PICTURE,
NonVisualPicProperties: &PICNonVisualPicProperties{
NonVisualDrawingProperties: PICNonVisualDrawingProperties{
diff --git a/apishape.go b/apishape.go
index 9507111..2918aa3 100644
--- a/apishape.go
+++ b/apishape.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
import (
@@ -5,8 +25,63 @@ import (
"sync/atomic"
)
-// AddShape adds wsp named drawing to paragraph
-func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []interface{}) (*Run, error) {
+// AddInlineShape adds wsp named drawing to paragraph
+func (p *Paragraph) AddInlineShape(w, h int64, name, bwMode, prst string, ln *ALine) (*Run, error) {
+ idn := int(atomic.AddUintptr(&p.file.docID, 1))
+ id := strconv.Itoa(int(p.file.IncreaseID(name)))
+ d := &Drawing{
+ Inline: &WPInline{
+ Extent: &WPExtent{
+ CX: w,
+ CY: h,
+ },
+ EffectExtent: &WPEffectExtent{},
+ DocPr: &WPDocPr{
+ ID: idn,
+ Name: name + " " + id,
+ },
+ CNvGraphicFramePr: &WPCNvGraphicFramePr{},
+ Graphic: &AGraphic{
+ XMLA: XMLNS_DRAWINGML_MAIN,
+ GraphicData: &AGraphicData{
+ URI: XMLNS_WPS,
+ Shape: &WordprocessingShape{
+ CNvCnPr: &WPSCNvCnPr{
+ ConnShapeLocks: &struct{}{},
+ },
+ SpPr: &WPSSpPr{
+ BWMode: bwMode,
+
+ Xfrm: AXfrm{
+ Ext: AExt{
+ CX: w,
+ CY: h,
+ },
+ },
+ PrstGeom: APrstGeom{
+ Prst: prst,
+ },
+ NoFill: &struct{}{},
+ Line: ln,
+ },
+ BodyPr: &WPSBodyPr{},
+ },
+ },
+ },
+ },
+ }
+ c := make([]interface{}, 1, 64)
+ c[0] = d
+ run := &Run{
+ RunProperties: &RunProperties{},
+ Children: c,
+ }
+ p.Children = append(p.Children, run)
+ return run, nil
+}
+
+// AddAnchorShape adds wsp named drawing to paragraph
+func (p *Paragraph) AddAnchorShape(w, h int64, name, bwMode, prst string, ln *ALine) (*Run, error) {
idn := int(atomic.AddUintptr(&p.file.docID, 1))
id := strconv.Itoa(int(p.file.IncreaseID(name)))
d := &Drawing{
@@ -37,7 +112,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
XMLA: XMLNS_DRAWINGML_MAIN,
GraphicData: &AGraphicData{
URI: XMLNS_WPS,
- Shape: &WPSWordprocessingShape{
+ Shape: &WordprocessingShape{
CNvCnPr: &WPSCNvCnPr{
ConnShapeLocks: &struct{}{},
},
@@ -54,7 +129,7 @@ func (p *Paragraph) AddShape(w, h int64, name, bwMode, prst string, elems []inte
Prst: prst,
},
NoFill: &struct{}{},
- Elems: elems,
+ Line: ln,
},
BodyPr: &WPSBodyPr{},
},
diff --git a/cmd/main/main.go b/cmd/main/main.go
index cdf9402..d6a391d 100644
--- a/cmd/main/main.go
+++ b/cmd/main/main.go
@@ -125,7 +125,7 @@ func main() {
p := w.AddParagraph().Justification("center")
p.AddText("测试 AutoShape w:ln").Size("44")
- p.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
+ p.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
&docx.ALine{
W: 9525,
SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
@@ -133,7 +133,16 @@ func main() {
HeadEnd: &docx.AHeadEnd{},
TailEnd: &docx.ATailEnd{},
},
- })
+ )
+ p.AddInlineShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
+ &docx.ALine{
+ W: 9525,
+ SolidFill: &docx.ASolidFill{SrgbClr: &docx.ASrgbClr{Val: "000000"}},
+ Round: &struct{}{},
+ HeadEnd: &docx.AHeadEnd{},
+ TailEnd: &docx.ATailEnd{},
+ },
+ )
f, err := os.Create(*fileLocation)
if err != nil {
@@ -193,7 +202,7 @@ func main() {
if len(c.Paragraphs) > 0 && len(c.Paragraphs[0].Children) > 0 {
fmt.Printf("<%d> %v\t", y, &c.Paragraphs[0])
} else {
- fmt.Print("\t")
+ fmt.Printf("<%d> \t\t", y)
}
}
fmt.Print("\n")
diff --git a/empty.go b/empty.go
index 0d674c5..6f7451f 100644
--- a/empty.go
+++ b/empty.go
@@ -60,21 +60,11 @@ func newEmptyA4File() *Docx {
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
Target: "fontTable.xml",
},
- {
- ID: "rId4",
- Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings`,
- Target: "settings.xml",
- },
- {
- ID: "rId5",
- Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings`,
- Target: "webSettings.xml",
- },
},
},
media: make([]Media, 0, 64),
mediaNameIdx: make(map[string]int, 64),
- rID: 5,
+ rID: 3,
slowIDs: make(map[string]uintptr, 64),
template: "a4",
tmpfslst: []string{
@@ -83,9 +73,7 @@ func newEmptyA4File() *Docx {
"docProps/core.xml",
"word/theme/theme1.xml",
"word/fontTable.xml",
- "word/settings.xml",
"word/styles.xml",
- "word/webSettings.xml",
"[Content_Types].xml",
},
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024)),
diff --git a/id.go b/id.go
index 005e92a..fb0bd60 100644
--- a/id.go
+++ b/id.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
func (f *Docx) IncreaseID(name string) (n uintptr) {
diff --git a/structcanvas.go b/structcanvas.go
index ada991e..bd93cbf 100644
--- a/structcanvas.go
+++ b/structcanvas.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
import (
@@ -12,6 +32,8 @@ type WordprocessingCanvas struct {
Whole *WPCWhole
Items []interface{}
+
+ file *Docx
}
// UnmarshalXML ...
@@ -40,7 +62,8 @@ func (c *WordprocessingCanvas) UnmarshalXML(d *xml.Decoder, start xml.StartEleme
return err
}
case "wsp":
- var value WPSWordprocessingShape
+ var value WordprocessingShape
+ value.file = c.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
diff --git a/structdrawing.go b/structdrawing.go
index 87151d4..30ec665 100644
--- a/structdrawing.go
+++ b/structdrawing.go
@@ -44,6 +44,8 @@ type Drawing struct {
XMLName xml.Name `xml:"w:drawing,omitempty"`
Inline *WPInline
Anchor *WPAnchor
+
+ file *Docx
}
// UnmarshalXML ...
@@ -61,12 +63,14 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "inline":
r.Inline = new(WPInline)
+ r.Inline.file = r.file
err = d.DecodeElement(r.Inline, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
case "anchor":
r.Anchor = new(WPAnchor)
+ r.Anchor.file = r.file
err = d.DecodeElement(r.Anchor, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
@@ -105,6 +109,8 @@ type WPInline struct {
DocPr *WPDocPr
CNvGraphicFramePr *WPCNvGraphicFramePr
Graphic *AGraphic
+
+ file *Docx
}
// UnmarshalXML ...
@@ -191,6 +197,7 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
r.CNvGraphicFramePr = &value
case "graphic":
var value AGraphic
+ value.file = r.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
@@ -360,6 +367,8 @@ type AGraphic struct {
XMLName xml.Name `xml:"a:graphic,omitempty"`
XMLA string `xml:"xmlns:a,attr,omitempty"`
GraphicData *AGraphicData
+
+ file *Docx
}
// UnmarshalXML ...
@@ -385,6 +394,7 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "graphicData":
var value AGraphicData
+ value.file = a.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
@@ -407,8 +417,11 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
type AGraphicData struct {
XMLName xml.Name `xml:"a:graphicData,omitempty"`
URI string `xml:"uri,attr"`
- Pic *PICPic
- Shape *WPSWordprocessingShape
+ Pic *Picture
+ Shape *WordprocessingShape
+ Canvas *WordprocessingCanvas
+
+ file *Docx
}
// UnmarshalXML ...
@@ -425,7 +438,7 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
case "pic":
- var value PICPic
+ var value Picture
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
@@ -433,12 +446,21 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
value.XMLPIC = getAtt(tt.Attr, "pic")
a.Pic = &value
case "wsp":
- var value WPSWordprocessingShape
+ var value WordprocessingShape
+ value.file = a.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
a.Shape = &value
+ case "wpc":
+ var value WordprocessingCanvas
+ value.file = a.file
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ a.Canvas = &value
default:
err = d.Skip() // skip unsupported tags
if err != nil {
@@ -451,8 +473,8 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
return nil
}
-// PICPic represents a picture in a Word document.
-type PICPic struct {
+// Picture represents a picture in a Word document.
+type Picture struct {
XMLName xml.Name `xml:"pic:pic,omitempty"`
XMLPIC string `xml:"xmlns:pic,attr,omitempty"`
NonVisualPicProperties *PICNonVisualPicProperties
@@ -461,7 +483,7 @@ type PICPic struct {
}
// UnmarshalXML ...
-func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+func (p *Picture) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
@@ -649,7 +671,7 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
type ABlip struct {
XMLName xml.Name `xml:"a:blip,omitempty"`
Embed string `xml:"r:embed,attr"`
- Cstate string `xml:"cstate,attr"`
+ Cstate string `xml:"cstate,attr,omitempty"`
AlphaModFix *AAlphaModFix
}
@@ -934,6 +956,8 @@ type WPAnchor struct {
DocPr *WPDocPr
CNvGraphicFramePr *WPCNvGraphicFramePr
Graphic *AGraphic
+
+ file *Docx
}
// UnmarshalXML ...
@@ -1061,6 +1085,7 @@ func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
}
case "graphic":
r.Graphic = new(AGraphic)
+ r.Graphic.file = r.file
err = d.DecodeElement(&r.Graphic, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
diff --git a/structeffects.go b/structeffects.go
index abb5062..2dc0ad8 100644
--- a/structeffects.go
+++ b/structeffects.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
import "encoding/xml"
@@ -27,6 +47,12 @@ type Size struct {
Val string `xml:"w:val,attr"`
}
+// SizeCs contains the cs font size
+type SizeCs struct {
+ XMLName xml.Name `xml:"w:szCs,omitempty"`
+ Val string `xml:"w:val,attr"`
+}
+
// Bold ...
type Bold struct {
XMLName xml.Name `xml:"w:b,omitempty"`
@@ -52,7 +78,7 @@ type Highlight struct {
// Kern ...
type Kern struct {
XMLName xml.Name `xml:"w:kern,omitempty"`
- Val int64 `xml:"w:val,attr,omitempty"`
+ Val int64 `xml:"w:val,attr"`
}
// Justification contains the way of the horizonal alignment
@@ -68,6 +94,18 @@ type Justification struct {
Val string `xml:"w:val,attr"`
}
+// TextAlignment ...
+type TextAlignment struct {
+ XMLName xml.Name `xml:"w:textAlignment,omitempty"`
+ Val string `xml:"w:val,attr"`
+}
+
+// VertAlign ...
+type VertAlign struct {
+ XMLName xml.Name `xml:"w:vertAlign,omitempty"`
+ Val string `xml:"w:val,attr"`
+}
+
// Shade is an element that represents a shading pattern applied to a document element.
type Shade struct {
XMLName xml.Name `xml:"w:shd,omitempty"`
@@ -100,3 +138,27 @@ func (s *Shade) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
_, err := d.Token()
return err
}
+
+// AdjustRightInd ...
+type AdjustRightInd struct {
+ XMLName xml.Name `xml:"w:adjustRightInd,omitempty"`
+ Val int `xml:"w:val,attr"`
+}
+
+// SnapToGrid ...
+type SnapToGrid struct {
+ XMLName xml.Name `xml:"w:snapToGrid,omitempty"`
+ Val int `xml:"w:val,attr"`
+}
+
+// Kinsoku ...
+type Kinsoku struct {
+ XMLName xml.Name `xml:"w:kinsoku,omitempty"`
+ Val int `xml:"w:val,attr"`
+}
+
+// OverflowPunct ...
+type OverflowPunct struct {
+ XMLName xml.Name `xml:"w:overflowPunct,omitempty"`
+ Val int `xml:"w:val,attr"`
+}
diff --git a/structpara.go b/structpara.go
index d4aa430..9805f03 100644
--- a/structpara.go
+++ b/structpara.go
@@ -31,10 +31,18 @@ import (
// ParagraphProperties
type ParagraphProperties struct {
- XMLName xml.Name `xml:"w:pPr,omitempty"`
- Justification *Justification
- Shade *Shade
- Kern *Kern
+ XMLName xml.Name `xml:"w:pPr,omitempty"`
+ Justification *Justification
+ Shade *Shade
+ Kern *Kern
+ Style *Style
+ TextAlignment *TextAlignment
+ AdjustRightInd *AdjustRightInd
+ SnapToGrid *SnapToGrid
+ Kinsoku *Kinsoku
+ OverflowPunct *OverflowPunct
+
+ RunProperties *RunProperties
}
// UnmarshalXML ...
@@ -69,6 +77,61 @@ func (p *ParagraphProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
return err
}
p.Kern = &value
+ case "rPr":
+ var value RunProperties
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ p.RunProperties = &value
+ case "pStyle":
+ p.Style = &Style{Val: getAtt(tt.Attr, "val")}
+ case "textAlignment":
+ p.TextAlignment = &TextAlignment{Val: getAtt(tt.Attr, "val")}
+ case "adjustRightInd":
+ var value AdjustRightInd
+ v := getAtt(tt.Attr, "val")
+ if v == "" {
+ continue
+ }
+ value.Val, err = strconv.Atoi(v)
+ if err != nil {
+ return err
+ }
+ p.AdjustRightInd = &value
+ case "snapToGrid":
+ var value SnapToGrid
+ v := getAtt(tt.Attr, "val")
+ if v == "" {
+ continue
+ }
+ value.Val, err = strconv.Atoi(v)
+ if err != nil {
+ return err
+ }
+ p.SnapToGrid = &value
+ case "kinsoku":
+ var value Kinsoku
+ v := getAtt(tt.Attr, "val")
+ if v == "" {
+ continue
+ }
+ value.Val, err = strconv.Atoi(v)
+ if err != nil {
+ return err
+ }
+ p.Kinsoku = &value
+ case "overflowPunct":
+ var value OverflowPunct
+ v := getAtt(tt.Attr, "val")
+ if v == "" {
+ continue
+ }
+ value.Val, err = strconv.Atoi(v)
+ if err != nil {
+ return err
+ }
+ p.OverflowPunct = &value
default:
err = d.Skip() // skip unsupported tags
if err != nil {
@@ -177,27 +240,6 @@ func (p *Paragraph) String() string {
return sb.String()
}
-// MarshalXML ...
-func (p *Paragraph) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- err := e.EncodeToken(start)
- if err != nil {
- return err
- }
- if p.Properties != nil {
- err = e.Encode(p.Properties)
- if err != nil {
- return err
- }
- }
- for _, c := range p.Children {
- err = e.Encode(c)
- if err != nil {
- return err
- }
- }
- return e.EncodeToken(start.End())
-}
-
// UnmarshalXML ...
func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for _, attr := range start.Attr {
@@ -243,6 +285,7 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
elem = &value
case "r":
var value Run
+ value.file = p.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
diff --git a/structrel_test.go b/structrel_test.go
index dcc2716..b4c1d41 100644
--- a/structrel_test.go
+++ b/structrel_test.go
@@ -47,16 +47,6 @@ func TestRelationships(t *testing.T) {
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable`,
Target: "fontTable.xml",
},
- {
- ID: "rId4",
- Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings`,
- Target: "settings.xml",
- },
- {
- ID: "rId5",
- Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings`,
- Target: "webSettings.xml",
- },
},
}
f, err := os.Create("TestRelationships.xml")
@@ -69,7 +59,7 @@ func TestRelationships(t *testing.T) {
t.Fatal(err)
}
m := hex.EncodeToString(h.Sum(make([]byte, 0, 16)))
- if m != "c75af73ef6cc9536a193669c4a3605c3" {
+ if m != "62c753dc14365fce007fc4c7c3bd0c82" {
t.Fatal("real md5:", m)
}
}
diff --git a/structrun.go b/structrun.go
index bda46b7..095f835 100644
--- a/structrun.go
+++ b/structrun.go
@@ -31,16 +31,27 @@ import (
// a piece of text in bold, or a link
type Run struct {
XMLName xml.Name `xml:"w:r,omitempty"`
+ RsidRPr string `xml:"w:rsidRPr,attr,omitempty"`
RunProperties *RunProperties `xml:"w:rPr,omitempty"`
InstrText string `xml:"w:instrText,omitempty"`
Children []interface{}
+
+ file *Docx
}
// UnmarshalXML ...
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "rsidRPr":
+ r.RsidRPr = attr.Value
+ default:
+ // ignore other attributes
+ }
+ }
for {
t, err := d.Token()
if err == io.EOF {
@@ -91,6 +102,7 @@ func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err
child = &value
case "drawing":
var value Drawing
+ value.file = r.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return nil, err
@@ -112,8 +124,14 @@ func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err
if ttt, ok := tok.(xml.StartElement); ok && ttt.Name.Local == "Choice" {
for _, attr := range ttt.Attr {
if attr.Name.Local == "Requires" {
- if attr.Value == "wps" {
- child, err = r.parse(d, ttt)
+ if attr.Value == "wps" || attr.Value == "wpc" {
+ tok, err = d.Token() // go into choice
+ if err != nil {
+ return nil, err
+ }
+ if ttt, ok := tok.(xml.StartElement); ok {
+ child, err = r.parse(d, ttt)
+ }
break altcont
}
break
@@ -141,15 +159,18 @@ type RunProperties struct {
XMLName xml.Name `xml:"w:rPr,omitempty"`
Fonts *RunFonts
Bold *Bold
+ ICs *struct{} `xml:"w:iCs,omitempty"`
Italic *Italic
Underline *Underline
Highlight *Highlight
Color *Color
Size *Size
+ SizeCs *SizeCs
RunStyle *RunStyle
Style *Style
Shade *Shade
Kern *Kern
+ VertAlign *VertAlign
}
// UnmarshalXML ...
@@ -174,6 +195,8 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
r.Fonts = &value
case "b":
r.Bold = &Bold{}
+ case "iCs":
+ r.ICs = &struct{}{}
case "i":
r.Italic = &Italic{}
case "u":
@@ -192,6 +215,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
var value Size
value.Val = getAtt(tt.Attr, "val")
r.Size = &value
+ case "szCs":
+ var value SizeCs
+ value.Val = getAtt(tt.Attr, "val")
+ r.SizeCs = &value
case "rStyle":
var value RunStyle
value.Val = getAtt(tt.Attr, "val")
@@ -218,6 +245,10 @@ func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) err
return err
}
r.Kern = &value
+ case "vertAlign":
+ var value VertAlign
+ value.Val = getAtt(tt.Attr, "val")
+ r.VertAlign = &value
default:
err = d.Skip() // skip unsupported tags
if err != nil {
diff --git a/structshape.go b/structshape.go
index 46301ec..72329ae 100644
--- a/structshape.go
+++ b/structshape.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
import (
@@ -7,16 +27,21 @@ import (
"strings"
)
-// WPSWordprocessingShape is a container for a WordprocessingML DrawingML shape.
-type WPSWordprocessingShape struct {
+// WordprocessingShape is a container for a WordprocessingML DrawingML shape.
+type WordprocessingShape struct {
XMLName xml.Name `xml:"wps:wsp,omitempty"`
+ CNvPr *WPSCNvPr
CNvCnPr *WPSCNvCnPr
+ CNvSpPr *WPSCNvSpPr
SpPr *WPSSpPr
+ TextBox *WPSTextBox
BodyPr *WPSBodyPr
+
+ file *Docx
}
// UnmarshalXML ...
-func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+func (w *WordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
@@ -28,18 +53,38 @@ func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartEle
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
+ case "cNvPr":
+ w.CNvPr = new(WPSCNvPr)
+ err = d.DecodeElement(w.CNvPr, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
case "cNvCnPr":
w.CNvCnPr = new(WPSCNvCnPr)
err = d.DecodeElement(w.CNvCnPr, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
+ case "cNvSpPr":
+ w.CNvSpPr = new(WPSCNvSpPr)
+ err = d.DecodeElement(w.CNvSpPr, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
case "spPr":
w.SpPr = new(WPSSpPr)
err = d.DecodeElement(w.SpPr, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
+ case "txbx":
+ var value WPSTextBox
+ value.file = w.file
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ w.TextBox = &value
case "bodyPr":
w.BodyPr = new(WPSBodyPr)
err = d.DecodeElement(w.BodyPr, &tt)
@@ -57,6 +102,33 @@ func (w *WPSWordprocessingShape) UnmarshalXML(d *xml.Decoder, start xml.StartEle
return nil
}
+// WPSCNvPr is an element that represents the non-visual properties of a content control.
+type WPSCNvPr struct {
+ XMLName xml.Name `xml:"wps:cNvPr,omitempty"`
+ ID int `xml:"id,attr"`
+ Name string `xml:"name,attr"`
+}
+
+// UnmarshalXML ...
+func (r *WPSCNvPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "id":
+ r.ID, err = strconv.Atoi(attr.Value)
+ if err != nil {
+ return
+ }
+ case "name":
+ r.Name = attr.Value
+ default:
+ // ignore other attributes
+ }
+ }
+ // Consume the end element
+ _, err = d.Token()
+ return
+}
+
// WPSCNvCnPr represents the non-visual drawing properties of a connector.
type WPSCNvCnPr struct {
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
@@ -90,15 +162,76 @@ func (w *WPSCNvCnPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
return nil
}
+// WPSCNvSpPr represents the non-visual properties of a WordArt object.
+type WPSCNvSpPr struct {
+ XMLName xml.Name `xml:"wps:cNvSpPr,omitempty"`
+ TxBox int `xml:"txBox,attr,omitempty"`
+
+ SPLocks *ASPLocks
+}
+
+// UnmarshalXML ...
+func (w *WPSCNvSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "txBox":
+ w.TxBox, err = strconv.Atoi(attr.Value)
+ if err != nil {
+ return err
+ }
+ default:
+ // ignore other attributes
+ }
+ }
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ if tt, ok := t.(xml.StartElement); ok {
+ switch tt.Name.Local {
+ case "spLocks":
+ var value ASPLocks
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ w.SPLocks = &value
+ default:
+ err = d.Skip() // skip unsupported tags
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
+ return nil
+}
+
+// ASPLocks represents the locks applied to a shape.
+type ASPLocks struct {
+ XMLName xml.Name `xml:"a:spLocks,omitempty"`
+}
+
// WPSSpPr is a container element that represents the visual properties of a shape.
type WPSSpPr struct {
XMLName xml.Name `xml:"wps:spPr,omitempty"`
BWMode string `xml:"bwMode,attr"`
- Xfrm AXfrm
- PrstGeom APrstGeom
- NoFill *struct{} `xml:"a:noFill,omitempty"`
- Elems []interface{}
+ Xfrm AXfrm
+ PrstGeom APrstGeom
+ SolidFill *ASolidFill
+ BlipFill *ABlipFill
+ NoFill *struct{} `xml:"a:noFill,omitempty"`
+ Line *ALine
+
+ EffectList struct{} `xml:"a:effectLst"`
+ ExtList struct{} `xml:"a:extLst"`
}
// UnmarshalXML ...
@@ -129,6 +262,20 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
}
case "prstGeom":
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
+ case "solidFill":
+ var value ASolidFill
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ w.SolidFill = &value
+ case "blipFill":
+ var value ABlipFill
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ w.BlipFill = &value
case "noFill":
w.NoFill = &struct{}{}
case "ln":
@@ -137,7 +284,7 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
- w.Elems = append(w.Elems, &ln)
+ w.Line = &ln
default:
err = d.Skip() // skip unsupported tags
if err != nil {
@@ -150,14 +297,137 @@ func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return nil
}
+// ABlipFill represents a fill that contains a reference to an image.
+type ABlipFill struct {
+ XMLName xml.Name `xml:"a:blipFill,omitempty"`
+ DPI int `xml:"dpi,attr"`
+ RotWithShape int `xml:"rotWithShape,attr"`
+
+ Blip *ABlip
+ SrcRect *ASrcRect
+ Tile *ATile
+}
+
+// UnmarshalXML ...
+func (r *ABlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "dpi":
+ r.DPI, err = strconv.Atoi(attr.Value)
+ if err != nil {
+ return err
+ }
+ case "rotWithShape":
+ r.RotWithShape, err = strconv.Atoi(attr.Value)
+ if err != nil {
+ return err
+ }
+ default:
+ // ignore other attributes
+ }
+ }
+
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ if tt, ok := t.(xml.StartElement); ok {
+ switch tt.Name.Local {
+ case "blip":
+ var value ABlip
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ r.Blip = &value
+ case "srcRect":
+ r.SrcRect = new(ASrcRect)
+ case "tile":
+ var value ATile
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ r.Tile = &value
+ default:
+ err = d.Skip() // skip unsupported tags
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
+ return nil
+}
+
+// ASrcRect represents the source rectangle of a tiled image fill.
+type ASrcRect struct {
+ XMLName xml.Name `xml:"a:srcRect,omitempty"`
+}
+
+// ATile represents the tiling information of a fill or border
+type ATile struct {
+ XMLName xml.Name `xml:"a:tile,omitempty"`
+ TX int64 `xml:"tx,attr"`
+ TY int64 `xml:"ty,attr"`
+ SX int64 `xml:"sx,attr"`
+ SY int64 `xml:"sy,attr"`
+ Flip string `xml:"flip,attr"`
+ Algn string `xml:"algn,attr"`
+}
+
+// UnmarshalXML ...
+func (t *ATile) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "tx":
+ t.TX, err = strconv.ParseInt(attr.Value, 10, 64)
+ if err != nil {
+ return err
+ }
+ case "ty":
+ t.TY, err = strconv.ParseInt(attr.Value, 10, 64)
+ if err != nil {
+ return err
+ }
+ case "sx":
+ t.SX, err = strconv.ParseInt(attr.Value, 10, 64)
+ if err != nil {
+ return err
+ }
+ case "sy":
+ t.SY, err = strconv.ParseInt(attr.Value, 10, 64)
+ if err != nil {
+ return err
+ }
+ case "flip":
+ t.Flip = attr.Value
+ case "algn":
+ t.Algn = attr.Value
+ default:
+ // ignore other attributes
+ }
+ }
+ // Consume the end element
+ _, err = d.Token()
+ return err
+}
+
// ALine represents a line element in a Word document.
type ALine struct {
XMLName xml.Name `xml:"a:ln,omitempty"`
- W int64 `xml:"w,attr"`
+ W int64 `xml:"w,attr,omitempty"`
Cap string `xml:"cap,attr,omitempty"`
Compound string `xml:"cmpd,attr,omitempty"`
Align string `xml:"algn,attr,omitempty"`
+ NoFill *struct{} `xml:"a:noFill,omitempty"`
SolidFill *ASolidFill
PrstDash *APrstDash
Miter *AMiter
@@ -196,6 +466,8 @@ func (l *ALine) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error)
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
+ case "noFill":
+ l.NoFill = &struct{}{}
case "solidFill":
l.SolidFill = new(ASolidFill)
err = d.DecodeElement(l.SolidFill, &tt)
@@ -351,7 +623,156 @@ func (r *ATailEnd) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return err
}
+// WPSTextBox ...
+type WPSTextBox struct {
+ XMLName xml.Name `xml:"wps:txbx,omitempty"`
+ Content *WTextBoxContent
+
+ file *Docx
+}
+
+// UnmarshalXML ...
+func (b *WPSTextBox) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ if tt, ok := t.(xml.StartElement); ok {
+ switch tt.Name.Local {
+ case "txbxContent":
+ var value WTextBoxContent
+ value.file = b.file
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ b.Content = &value
+ default:
+ err = d.Skip() // skip unsupported tags
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
+ return nil
+}
+
+// WTextBoxContent ...
+type WTextBoxContent struct {
+ XMLName xml.Name `xml:"w:txbxContent,omitempty"`
+ Paragraphs []Paragraph `xml:"w:p,omitempty"`
+
+ file *Docx
+}
+
+// UnmarshalXML ...
+func (c *WTextBoxContent) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ if tt, ok := t.(xml.StartElement); ok {
+ switch tt.Name.Local {
+ case "p":
+ var value Paragraph
+ err = d.DecodeElement(&value, &tt)
+ if err != nil && !strings.HasPrefix(err.Error(), "expected") {
+ return err
+ }
+ if len(value.Children) > 0 {
+ value.file = c.file
+ c.Paragraphs = append(c.Paragraphs, value)
+ }
+ default:
+ err = d.Skip() // skip unsupported tags
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
+ return nil
+}
+
// WPSBodyPr represents the body properties for a WordprocessingML DrawingML shape.
type WPSBodyPr struct {
- XMLName xml.Name `xml:"wps:bodyPr,omitempty"`
+ XMLName xml.Name `xml:"wps:bodyPr,omitempty"`
+ Rot int `xml:"rot,attr,omitempty"`
+ Vert string `xml:"vert,attr,omitempty"`
+ Wrap string `xml:"wrap,attr,omitempty"`
+ LIns int64 `xml:"lIns,attr,omitempty"`
+ TIns int64 `xml:"tIns,attr,omitempty"`
+ RIns int64 `xml:"rIns,attr,omitempty"`
+ BIns int64 `xml:"bIns,attr,omitempty"`
+ Anchor string `xml:"anchor,attr,omitempty"`
+ AnchorCtr int `xml:"anchorCtr,attr,omitempty"`
+ Upright int `xml:"upright,attr,omitempty"`
+
+ NoAutofit *struct{} `xml:"a:noAutofit,omitempty"`
+}
+
+// UnmarshalXML ...
+func (r *WPSBodyPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
+ for _, attr := range start.Attr {
+ switch attr.Name.Local {
+ case "rot":
+ r.Rot, _ = strconv.Atoi(attr.Value)
+ case "vert":
+ r.Vert = attr.Value
+ case "wrap":
+ r.Wrap = attr.Value
+ case "lIns":
+ r.LIns, _ = strconv.ParseInt(attr.Value, 10, 64)
+ case "tIns":
+ r.TIns, _ = strconv.ParseInt(attr.Value, 10, 64)
+ case "rIns":
+ r.RIns, _ = strconv.ParseInt(attr.Value, 10, 64)
+ case "bIns":
+ r.BIns, _ = strconv.ParseInt(attr.Value, 10, 64)
+ case "anchor":
+ r.Anchor = attr.Value
+ case "anchorCtr":
+ r.AnchorCtr, _ = strconv.Atoi(attr.Value)
+ case "upright":
+ r.Upright, _ = strconv.Atoi(attr.Value)
+ default:
+ // ignore other attributes
+ }
+ }
+ for {
+ t, err := d.Token()
+ if err == io.EOF {
+ break
+ }
+ if err != nil {
+ return err
+ }
+
+ if tt, ok := t.(xml.StartElement); ok {
+ switch tt.Name.Local {
+ case "noAutofit":
+ r.NoAutofit = &struct{}{}
+ default:
+ err = d.Skip() // skip unsupported elements
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ }
+ }
+ return nil
}
diff --git a/structshape_test.go b/structshape_test.go
index 5f8eb7e..d70fad5 100644
--- a/structshape_test.go
+++ b/structshape_test.go
@@ -1,3 +1,23 @@
+/*
+ Copyright (c) 2020 gingfrederik
+ Copyright (c) 2021 Gonzalo Fernandez-Victorio
+ Copyright (c) 2021 Basement Crowd Ltd (https://www.basementcrowd.com)
+ Copyright (c) 2023 Fumiama Minamoto (源文雨)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+
package docx
import (
@@ -13,8 +33,8 @@ func TestShapeStructure(t *testing.T) {
// add new paragraph
para1 := w.AddParagraph()
// add text
- para1.AddText("test shape")
- para1.AddShape(808355, 238760, "AutoShape", "auto", "straightConnector1", []interface{}{
+ para1.AddText("test anchor shape")
+ para1.AddAnchorShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
&ALine{
W: 9525,
SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
@@ -22,7 +42,19 @@ func TestShapeStructure(t *testing.T) {
HeadEnd: &AHeadEnd{},
TailEnd: &ATailEnd{},
},
- })
+ )
+
+ para2 := w.AddParagraph()
+ para2.AddText("test inline shape")
+ para2.AddInlineShape(808355, 238760, "AutoShape", "auto", "straightConnector1",
+ &ALine{
+ W: 9525,
+ SolidFill: &ASolidFill{SrgbClr: &ASrgbClr{Val: "000000"}},
+ Round: &struct{}{},
+ HeadEnd: &AHeadEnd{},
+ TailEnd: &ATailEnd{},
+ },
+ )
f, err := os.Create("TestMarshalShapeStructure.xml")
if err != nil {
diff --git a/structtable.go b/structtable.go
index 7590c88..10e1b25 100644
--- a/structtable.go
+++ b/structtable.go
@@ -51,11 +51,11 @@ func (t *WTable) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt.Name.Local {
case "tr":
var value WTableRow
+ value.file = t.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
- value.file = t.file
t.TableRows = append(t.TableRows, &value)
case "tblPr":
t.TableProperties = new(WTableProperties)
@@ -421,11 +421,11 @@ func (w *WTableRow) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
}
case "tc":
var value WTableCell
+ value.file = w.file
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
- value.file = w.file
w.TableCells = append(w.TableCells, &value)
default:
err = d.Skip() // skip unsupported tags
@@ -504,7 +504,7 @@ func (t *WTableRowProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
// WTableRowHeight represents the height of a row within a table.
type WTableRowHeight struct {
XMLName xml.Name `xml:"w:trHeight,omitempty"`
- Rule string `xml:"w:hRule,omitempty"`
+ Rule string `xml:"w:hRule,attr,omitempty"`
Val int64 `xml:"w:val,attr"`
}
@@ -565,9 +565,9 @@ type WTableCellProperties struct {
TableCellWidth *WTableCellWidth
VMerge *WvMerge
GridSpan *WGridSpan
- VAlign *WVerticalAlignment
TableBorders *WTableBorders `xml:"w:tcBorders"`
Shade *Shade
+ VAlign *WVerticalAlignment
}
// UnmarshalXML ...
diff --git a/xml/a4/[Content_Types].xml b/xml/a4/[Content_Types].xml
index b3a964c..3ea9380 100644
--- a/xml/a4/[Content_Types].xml
+++ b/xml/a4/[Content_Types].xml
@@ -7,8 +7,6 @@
-
-
diff --git a/xml/a4/word/settings.xml b/xml/a4/word/settings.xml
deleted file mode 100755
index 599386d..0000000
--- a/xml/a4/word/settings.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/xml/a4/word/webSettings.xml b/xml/a4/word/webSettings.xml
deleted file mode 100755
index 6c0860b..0000000
--- a/xml/a4/word/webSettings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-