mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-05 07:40:24 +08:00
make lint happy
This commit is contained in:
10
apipara.go
10
apipara.go
@@ -2,14 +2,14 @@ package docxlib
|
||||
|
||||
// AddParagraph adds a new paragraph
|
||||
func (f *Docx) AddParagraph() *Paragraph {
|
||||
p := &Paragraph{
|
||||
f.Document.Body.mu.Lock()
|
||||
defer f.Document.Body.mu.Unlock()
|
||||
f.Document.Body.Paragraphs = append(f.Document.Body.Paragraphs, Paragraph{
|
||||
Children: make([]interface{}, 0, 64),
|
||||
file: f,
|
||||
}
|
||||
})
|
||||
|
||||
f.Document.Body.Paragraphs = append(f.Document.Body.Paragraphs, p)
|
||||
|
||||
return p
|
||||
return &f.Document.Body.Paragraphs[len(f.Document.Body.Paragraphs)-1]
|
||||
}
|
||||
|
||||
// Justification allows to set para's horizonal alignment
|
||||
|
||||
11
empty.go
11
empty.go
@@ -15,16 +15,13 @@ func newEmptyA4File() *Docx {
|
||||
XMLR: XMLNS_R,
|
||||
XMLWP: XMLNS_WP,
|
||||
// XMLWP14: XMLNS_WP14,
|
||||
Body: &Body{
|
||||
XMLName: xml.Name{
|
||||
Space: "w",
|
||||
},
|
||||
Paragraphs: make([]*Paragraph, 0, 64),
|
||||
Body: Body{
|
||||
Paragraphs: make([]Paragraph, 0, 64),
|
||||
},
|
||||
},
|
||||
DocRelation: Relationships{
|
||||
Xmlns: XMLNS_REL,
|
||||
Relationships: []*Relationship{
|
||||
Relationship: []Relationship{
|
||||
{
|
||||
ID: "rId1",
|
||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles`,
|
||||
@@ -69,6 +66,6 @@ func newEmptyA4File() *Docx {
|
||||
},
|
||||
buf: bytes.NewBuffer(make([]byte, 0, 1024*1024*4)),
|
||||
}
|
||||
docx.Document.file = docx
|
||||
docx.Document.Body.file = docx
|
||||
return docx
|
||||
}
|
||||
|
||||
12
link.go
12
link.go
@@ -17,14 +17,14 @@ var (
|
||||
//
|
||||
// this func is not thread-safe
|
||||
func (f *Docx) addLinkRelation(link string) string {
|
||||
rel := &Relationship{
|
||||
rel := Relationship{
|
||||
ID: "rId" + strconv.Itoa(int(atomic.AddUintptr(&f.rId, 1))),
|
||||
Type: REL_HYPERLINK,
|
||||
Target: link,
|
||||
TargetMode: REL_TARGETMODE,
|
||||
}
|
||||
|
||||
f.DocRelation.Relationships = append(f.DocRelation.Relationships, rel)
|
||||
f.DocRelation.Relationship = append(f.DocRelation.Relationship, rel)
|
||||
|
||||
return rel.ID
|
||||
}
|
||||
@@ -33,13 +33,13 @@ func (f *Docx) addLinkRelation(link string) string {
|
||||
//
|
||||
// this func is not thread-safe
|
||||
func (f *Docx) addImageRelation(m Media) string {
|
||||
rel := &Relationship{
|
||||
rel := Relationship{
|
||||
ID: "rId" + strconv.Itoa(int(atomic.AddUintptr(&f.rId, 1))),
|
||||
Type: REL_IMAGE,
|
||||
Target: "media/" + m.Name,
|
||||
}
|
||||
|
||||
f.DocRelation.Relationships = append(f.DocRelation.Relationships, rel)
|
||||
f.DocRelation.Relationship = append(f.DocRelation.Relationship, rel)
|
||||
|
||||
return rel.ID
|
||||
}
|
||||
@@ -48,7 +48,7 @@ func (f *Docx) addImageRelation(m Media) string {
|
||||
func (f *Docx) ReferTarget(id string) (string, error) {
|
||||
f.DocRelation.mu.RLock()
|
||||
defer f.DocRelation.mu.RUnlock()
|
||||
for _, a := range f.DocRelation.Relationships {
|
||||
for _, a := range f.DocRelation.Relationship {
|
||||
if a.ID == id {
|
||||
return a.Target, nil
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func (f *Docx) ReferTarget(id string) (string, error) {
|
||||
func (f *Docx) ReferID(target string) (string, error) {
|
||||
f.DocRelation.mu.RLock()
|
||||
defer f.DocRelation.mu.RUnlock()
|
||||
for _, a := range f.DocRelation.Relationships {
|
||||
for _, a := range f.DocRelation.Relationship {
|
||||
if a.Target == target {
|
||||
return a.ID, nil
|
||||
}
|
||||
|
||||
2
pack.go
2
pack.go
@@ -31,7 +31,7 @@ func (f *Docx) pack(zipWriter *zip.Writer) (err error) {
|
||||
}
|
||||
|
||||
files["word/_rels/document.xml.rels"] = marshaller{data: &f.DocRelation}
|
||||
files["word/document.xml"] = marshaller{data: f.Document}
|
||||
files["word/document.xml"] = marshaller{data: &f.Document}
|
||||
|
||||
for _, m := range f.media {
|
||||
files[m.String()] = bytes.NewReader(m.Data)
|
||||
|
||||
80
structdoc.go
80
structdoc.go
@@ -3,6 +3,8 @@ package docxlib
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -24,27 +26,13 @@ func getAtt(atts []xml.Attr, name string) string {
|
||||
}
|
||||
|
||||
type Body struct {
|
||||
XMLName xml.Name `xml:"w:body"`
|
||||
Paragraphs []*Paragraph `xml:"w:p,omitempty"`
|
||||
}
|
||||
|
||||
type Document struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main document"`
|
||||
XMLW string `xml:"xmlns:w,attr"` // cannot be unmarshalled in
|
||||
XMLR string `xml:"xmlns:r,attr,omitempty"` // cannot be unmarshalled in
|
||||
XMLWP string `xml:"xmlns:wp,attr,omitempty"` // cannot be unmarshalled in
|
||||
XMLWP14 string `xml:"xmlns:wp14,attr,omitempty"` // cannot be unmarshalled in
|
||||
Body *Body
|
||||
mu sync.Mutex
|
||||
Paragraphs []Paragraph `xml:"w:p,omitempty"`
|
||||
|
||||
file *Docx
|
||||
}
|
||||
|
||||
func (doc *Document) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
if doc.Body == nil {
|
||||
doc.Body = &Body{
|
||||
Paragraphs: make([]*Paragraph, 0, 64),
|
||||
}
|
||||
}
|
||||
func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err == io.EOF {
|
||||
@@ -56,19 +44,59 @@ func (doc *Document) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "body":
|
||||
case "p":
|
||||
if tt.Name.Local == "p" {
|
||||
var value Paragraph
|
||||
d.DecodeElement(&value, &tt)
|
||||
if len(value.Children) > 0 {
|
||||
value.file = doc.file
|
||||
doc.Body.Paragraphs = append(doc.Body.Paragraphs, &value)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
if len(value.Children) > 0 {
|
||||
value.file = b.file
|
||||
b.mu.Lock()
|
||||
b.Paragraphs = append(b.Paragraphs, value)
|
||||
b.mu.Unlock()
|
||||
}
|
||||
default:
|
||||
d.Skip()
|
||||
continue
|
||||
}
|
||||
err = d.Skip() // skip unsupported tags
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
type Document struct {
|
||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main document"`
|
||||
XMLW string `xml:"xmlns:w,attr"` // cannot be unmarshalled in
|
||||
XMLR string `xml:"xmlns:r,attr,omitempty"` // cannot be unmarshalled in
|
||||
XMLWP string `xml:"xmlns:wp,attr,omitempty"` // cannot be unmarshalled in
|
||||
// XMLWP14 string `xml:"xmlns:wp14,attr,omitempty"` // cannot be unmarshalled in
|
||||
|
||||
Body Body `xml:"w:body"`
|
||||
}
|
||||
|
||||
func (doc *Document) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
for {
|
||||
t, err := d.Token()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
if tt.Name.Local == "body" {
|
||||
err = d.DecodeElement(&doc.Body, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,9 +2,6 @@ package docxlib
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"hash/crc64"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -47,76 +44,3 @@ func TestUnmarshalPlainStructure(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInlineDrawingStructure(t *testing.T) {
|
||||
w := NewA4()
|
||||
// add new paragraph
|
||||
para1 := w.AddParagraph()
|
||||
// add text
|
||||
para1.AddText("直接粘贴 inline").AddTab()
|
||||
r, err := para1.AddAnchorDrawingFrom("testdata/fumiama.JPG")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000
|
||||
para2 := w.AddParagraph().Justification("center")
|
||||
para2.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
||||
para2.AddTab().AddTab().AppendTab().AppendTab()
|
||||
para2.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
||||
|
||||
para3 := w.AddParagraph()
|
||||
para3.AddInlineDrawingFrom("testdata/fumiamayoko.png")
|
||||
|
||||
f, err := os.Create("TestMarshalInlineDrawingStructure.xml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = marshaller{data: w.Document}.WriteTo(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w = NewA4()
|
||||
err = xml.NewDecoder(f).Decode(&w.Document)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f1, err := os.Create("TestUnmarshalInlineDrawingStructure.xml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f1.Close()
|
||||
_, err = marshaller{data: w.Document}.WriteTo(f1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f1.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := crc64.New(crc64.MakeTable(crc64.ECMA))
|
||||
_, err = io.Copy(h, f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
md51 := h.Sum64()
|
||||
h.Reset()
|
||||
_, err = io.Copy(h, f1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
md52 := h.Sum64()
|
||||
if md51 != md52 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
120
structdrawing.go
120
structdrawing.go
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -38,10 +39,16 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "inline":
|
||||
r.Inline = new(WPInline)
|
||||
d.DecodeElement(r.Inline, &tt)
|
||||
err = d.DecodeElement(r.Inline, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "anchor":
|
||||
r.Anchor = new(WPAnchor)
|
||||
d.DecodeElement(r.Anchor, &tt)
|
||||
err = d.DecodeElement(r.Anchor, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -138,14 +145,23 @@ func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
||||
}
|
||||
case "docPr":
|
||||
r.DocPr = new(WPDocPr)
|
||||
d.DecodeElement(r.DocPr, &tt)
|
||||
err = d.DecodeElement(r.DocPr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "cNvGraphicFramePr":
|
||||
var value WPCNvGraphicFramePr
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.CNvGraphicFramePr = &value
|
||||
case "graphic":
|
||||
var value AGraphic
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.Graphic = &value
|
||||
default:
|
||||
continue
|
||||
@@ -285,7 +301,10 @@ func (w *WPCNvGraphicFramePr) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
|
||||
switch tt.Name.Local {
|
||||
case "graphicFrameLocks":
|
||||
var value AGraphicFrameLocks
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
value.NoChangeAspect, err = strconv.Atoi(getAtt(tt.Attr, "noChangeAspect"))
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -336,7 +355,10 @@ func (a *AGraphic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "graphicData":
|
||||
var value AGraphicData
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
value.URI = getAtt(tt.Attr, "uri")
|
||||
a.GraphicData = &value
|
||||
default:
|
||||
@@ -370,7 +392,10 @@ func (a *AGraphicData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) erro
|
||||
switch tt.Name.Local {
|
||||
case "pic":
|
||||
var value PICPic
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
value.XMLPIC = getAtt(tt.Attr, "pic")
|
||||
a.Pic = &value
|
||||
default:
|
||||
@@ -406,15 +431,24 @@ func (p *PICPic) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "nvPicPr":
|
||||
var value PICNonVisualPicProperties
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
p.NonVisualPicProperties = &value
|
||||
case "blipFill":
|
||||
var value PICBlipFill
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
p.BlipFill = &value
|
||||
case "spPr":
|
||||
var value PICSpPr
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
p.SpPr = &value
|
||||
default:
|
||||
continue
|
||||
@@ -449,7 +483,10 @@ func (p *PICNonVisualPicProperties) UnmarshalXML(d *xml.Decoder, start xml.Start
|
||||
p.NonVisualDrawingProperties.ID = getAtt(tt.Attr, "id")
|
||||
p.NonVisualDrawingProperties.Name = getAtt(tt.Attr, "name")
|
||||
case "cNvPicPr":
|
||||
d.DecodeElement(&p.CNvPicPr, &tt)
|
||||
err = d.DecodeElement(&p.CNvPicPr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -529,9 +566,15 @@ func (p *PICBlipFill) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "blip":
|
||||
d.DecodeElement(&p.Blip, &tt)
|
||||
err = d.DecodeElement(&p.Blip, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "stretch":
|
||||
d.DecodeElement(&p.Stretch, &tt)
|
||||
err = d.DecodeElement(&p.Stretch, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -626,9 +669,15 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
case xml.StartElement:
|
||||
switch tt.Name.Local {
|
||||
case "xfrm":
|
||||
d.DecodeElement(&p.Xfrm, &tt)
|
||||
err = d.DecodeElement(&p.Xfrm, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "prstGeom":
|
||||
d.DecodeElement(&p.PrstGeom, &tt)
|
||||
err = d.DecodeElement(&p.PrstGeom, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
p.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
||||
default:
|
||||
continue
|
||||
@@ -881,17 +930,29 @@ func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
||||
case "positionH":
|
||||
r.PositionH = new(WPPositionH)
|
||||
// r.PositionH.RelativeFrom = getAtt(tt.Attr, "relativeFrom")
|
||||
d.DecodeElement(&r.PositionH, &tt)
|
||||
err = d.DecodeElement(&r.PositionH, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "positionV":
|
||||
r.PositionV = new(WPPositionV)
|
||||
// r.PositionV.RelativeFrom = getAtt(tt.Attr, "relativeFrom")
|
||||
d.DecodeElement(&r.PositionV, &tt)
|
||||
err = d.DecodeElement(&r.PositionV, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "extent":
|
||||
r.Extent = new(WPExtent)
|
||||
d.DecodeElement(&r.Extent, &tt)
|
||||
err = d.DecodeElement(&r.Extent, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "effectExtent":
|
||||
r.EffectExtent = new(WPEffectExtent)
|
||||
d.DecodeElement(&r.EffectExtent, &tt)
|
||||
err = d.DecodeElement(&r.EffectExtent, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "wrapNone":
|
||||
r.WrapNone = &struct{}{}
|
||||
case "wrapSquare":
|
||||
@@ -899,13 +960,22 @@ func (r *WPAnchor) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err err
|
||||
r.WrapSquare.WrapText = getAtt(tt.Attr, "wrapText")
|
||||
case "docPr":
|
||||
r.DocPr = new(WPDocPr)
|
||||
d.DecodeElement(r.DocPr, &tt)
|
||||
err = d.DecodeElement(r.DocPr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "cNvGraphicFramePr":
|
||||
r.CNvGraphicFramePr = new(WPCNvGraphicFramePr)
|
||||
d.DecodeElement(r.CNvGraphicFramePr, &tt)
|
||||
err = d.DecodeElement(r.CNvGraphicFramePr, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
case "graphic":
|
||||
r.Graphic = new(AGraphic)
|
||||
d.DecodeElement(&r.Graphic, &tt)
|
||||
err = d.DecodeElement(&r.Graphic, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
@@ -949,7 +1019,7 @@ func (r *WPPositionH) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
switch tt.Name.Local {
|
||||
case "posOffset":
|
||||
err = d.DecodeElement(&r.PosOffset, &tt)
|
||||
if err != nil {
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
@@ -988,7 +1058,7 @@ func (r *WPPositionV) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error
|
||||
switch tt.Name.Local {
|
||||
case "posOffset":
|
||||
err = d.DecodeElement(&r.PosOffset, &tt)
|
||||
if err != nil {
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
|
||||
82
structdrawing_test.go
Normal file
82
structdrawing_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package docxlib
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"hash/crc64"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDrawingStructure(t *testing.T) {
|
||||
w := NewA4()
|
||||
// add new paragraph
|
||||
para1 := w.AddParagraph()
|
||||
// add text
|
||||
para1.AddText("直接粘贴 inline").AddTab()
|
||||
r, err := para1.AddAnchorDrawingFrom("testdata/fumiama.JPG")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.BlipFill.Blip.AlphaModFix = &AAlphaModFix{Amount: 50000}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.NonVisualPicProperties.CNvPicPr.Locks = &APicLocks{NoChangeAspect: 1}
|
||||
r.Drawing.Anchor.Graphic.GraphicData.Pic.SpPr.Xfrm.Rot = 50000
|
||||
para2 := w.AddParagraph().Justification("center")
|
||||
para2.AddInlineDrawingFrom("testdata/fumiama.JPG")
|
||||
para2.AddTab().AddTab().AppendTab().AppendTab()
|
||||
para2.AddInlineDrawingFrom("testdata/fumiama2x.webp")
|
||||
|
||||
para3 := w.AddParagraph()
|
||||
para3.AddInlineDrawingFrom("testdata/fumiamayoko.png")
|
||||
|
||||
f, err := os.Create("TestMarshalInlineDrawingStructure.xml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = marshaller{data: &w.Document}.WriteTo(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w = NewA4()
|
||||
err = xml.NewDecoder(f).Decode(&w.Document)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f1, err := os.Create("TestUnmarshalInlineDrawingStructure.xml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer f1.Close()
|
||||
_, err = marshaller{data: &w.Document}.WriteTo(f1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = f1.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := crc64.New(crc64.MakeTable(crc64.ECMA))
|
||||
_, err = io.Copy(h, f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crc1 := h.Sum64()
|
||||
h.Reset()
|
||||
_, err = io.Copy(h, f1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
crc2 := h.Sum64()
|
||||
if crc1 != crc2 {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package docxlib
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Hyperlink element contains links
|
||||
@@ -25,9 +26,10 @@ func (r *Hyperlink) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt := t.(type) {
|
||||
case xml.StartElement:
|
||||
if tt.Name.Local == "r" {
|
||||
d.DecodeElement(&r.Run, &tt)
|
||||
} else {
|
||||
continue
|
||||
err = d.DecodeElement(&r.Run, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func (p *ParagraphProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElemen
|
||||
}
|
||||
|
||||
type Paragraph struct {
|
||||
XMLName xml.Name `xml:"w:p,omitempty"`
|
||||
// XMLName xml.Name `xml:"w:p,omitempty"`
|
||||
Properties *ParagraphProperties
|
||||
Children []interface{} // Children will generate an unnecessary tag <Children> ... </Children> and we skip it by a self-defined xml.Marshaler
|
||||
|
||||
@@ -106,7 +106,10 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "hyperlink":
|
||||
var value Hyperlink
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
id := getAtt(tt.Attr, "id")
|
||||
anchor := getAtt(tt.Attr, "anchor")
|
||||
if id != "" {
|
||||
@@ -118,15 +121,24 @@ func (p *Paragraph) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
elem = &value
|
||||
case "r":
|
||||
var value Run
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
elem = &value
|
||||
case "rPr":
|
||||
var value RunProperties
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
elem = &value
|
||||
case "pPr":
|
||||
var value ParagraphProperties
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
p.Properties = &value
|
||||
continue
|
||||
default:
|
||||
|
||||
17
structrel.go
17
structrel.go
@@ -1,7 +1,6 @@
|
||||
package docxlib
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -14,16 +13,14 @@ const (
|
||||
)
|
||||
|
||||
type Relationships struct {
|
||||
mu sync.RWMutex
|
||||
XMLName xml.Name `xml:"Relationships"`
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
Relationships []*Relationship `xml:"Relationship"`
|
||||
mu sync.RWMutex
|
||||
Xmlns string `xml:"xmlns,attr"`
|
||||
Relationship []Relationship
|
||||
}
|
||||
|
||||
type Relationship struct {
|
||||
XMLName xml.Name `xml:"Relationship"`
|
||||
ID string `xml:"Id,attr"`
|
||||
Type string `xml:"Type,attr"`
|
||||
Target string `xml:"Target,attr"`
|
||||
TargetMode string `xml:"TargetMode,attr,omitempty"`
|
||||
ID string `xml:"Id,attr"`
|
||||
Type string `xml:"Type,attr"`
|
||||
Target string `xml:"Target,attr"`
|
||||
TargetMode string `xml:"TargetMode,attr,omitempty"`
|
||||
}
|
||||
|
||||
55
structrel_test.go
Normal file
55
structrel_test.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package docxlib
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRelationships(t *testing.T) {
|
||||
rel := Relationships{
|
||||
Xmlns: XMLNS_REL,
|
||||
Relationship: []Relationship{
|
||||
{
|
||||
ID: "rId1",
|
||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles`,
|
||||
Target: "styles.xml",
|
||||
},
|
||||
{
|
||||
ID: "rId2",
|
||||
Type: `http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme`,
|
||||
Target: "theme/theme1.xml",
|
||||
},
|
||||
{
|
||||
ID: "rId3",
|
||||
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")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := md5.New()
|
||||
_, err = io.Copy(io.MultiWriter(f, h), marshaller{data: &rel})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m := hex.EncodeToString(h.Sum(make([]byte, 0, 16)))
|
||||
if m != "c75af73ef6cc9536a193669c4a3605c3" {
|
||||
t.Fatal("real md5:", m)
|
||||
}
|
||||
}
|
||||
25
structrun.go
25
structrun.go
@@ -3,6 +3,7 @@ package docxlib
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Run is part of a paragraph that has its own style. It could be
|
||||
@@ -36,19 +37,31 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||
switch tt.Name.Local {
|
||||
case "rPr":
|
||||
var value RunProperties
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.RunProperties = &value
|
||||
case "instrText":
|
||||
var value string
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.InstrText = value
|
||||
case "t":
|
||||
var value Text
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.Text = &value
|
||||
case "drawing":
|
||||
var value Drawing
|
||||
d.DecodeElement(&value, &tt)
|
||||
err = d.DecodeElement(&value, &tt)
|
||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||
return err
|
||||
}
|
||||
r.Drawing = &value
|
||||
case "tab":
|
||||
if r.InstrText == "" && r.Text == nil && r.Drawing == nil {
|
||||
@@ -159,6 +172,6 @@ type Size struct {
|
||||
// both:两端对齐。
|
||||
// distribute:分散对齐。
|
||||
type Justification struct {
|
||||
XMLName xml.Name `xml:"w:jc"`
|
||||
Val string `xml:"w:val,attr"`
|
||||
// XMLName xml.Name `xml:"w:jc"`
|
||||
Val string `xml:"w:val,attr"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user