1
0
mirror of https://github.com/fumiama/go-docx.git synced 2026-06-21 19:13:37 +08:00

fix: unmarshal RunProperties

This commit is contained in:
源文雨
2023-02-10 13:52:11 +08:00
parent 9aae5582ad
commit 9a504d59dc
10 changed files with 233 additions and 158 deletions

View File

@@ -10,9 +10,9 @@ func (r *Run) Color(color string) *Run {
} }
// Size allows to set run size // Size allows to set run size
func (r *Run) Size(size int) *Run { func (r *Run) Size(size string) *Run {
r.RunProperties.Size = &Size{ r.RunProperties.Size = &Size{
Val: size * 2, Val: size,
} }
return r return r

View File

@@ -23,10 +23,10 @@ func main() {
// add text // add text
para1.AddText("test") para1.AddText("test")
para1.AddText("test font size").Size(22) para1.AddText("test font size").Size("44")
para1.AddText("test color").Color("808080") para1.AddText("test color").Color("808080")
para2 := w.AddParagraph() para2 := w.AddParagraph()
para2.AddText("test font size and color").Size(22).Color("ff0000") para2.AddText("test font size and color").Size("44").Color("ff0000")
nextPara := w.AddParagraph() nextPara := w.AddParagraph()
nextPara.AddLink("google", `http://google.com`) nextPara.AddLink("google", `http://google.com`)
@@ -83,5 +83,17 @@ func main() {
} }
fmt.Print("End of paragraph\n\n") fmt.Print("End of paragraph\n\n")
} }
f, err = os.Create("tmp.docx")
if err != nil {
panic(err)
}
_, err = doc.WriteTo(f)
if err != nil {
panic(err)
}
err = f.Close()
if err != nil {
panic(err)
}
fmt.Println("End of main") fmt.Println("End of main")
} }

View File

@@ -8,6 +8,15 @@ const (
XMLNS_WP = `http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing` XMLNS_WP = `http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing`
) )
func getAtt(atts []xml.Attr, name string) string {
for _, at := range atts {
if at.Name.Local == name {
return at.Value
}
}
return ""
}
type Body struct { type Body struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main body"` XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main body"`
Paragraphs []*Paragraph `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main p"` Paragraphs []*Paragraph `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main p"`

View File

@@ -2,6 +2,7 @@ package docxlib
import ( import (
"encoding/xml" "encoding/xml"
"io"
"os" "os"
"testing" "testing"
) )
@@ -570,9 +571,9 @@ func TestMarshalDrawingStructure(t *testing.T) {
para1.AddText("直接粘贴 inline") para1.AddText("直接粘贴 inline")
para2 := w.AddParagraph() para2 := w.AddParagraph()
para2.AddText("test font size and color").Size(22).Color("ff0000") para2.AddText("test font size and color").Size("44").Color("ff0000")
para2.AddText("test font size and color").Size(22).Color("ff0000") para2.AddText("test font size and color").Size("44").Color("ff0000")
para2.AddText("test font size and color").Size(22).Color("ff0000") para2.AddText("test font size and color").Size("44").Color("ff0000")
nextPara := w.AddParagraph() nextPara := w.AddParagraph()
nextPara.AddLink("google", `http://google.com`) nextPara.AddLink("google", `http://google.com`)
@@ -581,9 +582,28 @@ func TestMarshalDrawingStructure(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer f.Close()
_, err = marshaller{data: w.Document}.WriteTo(f) _, err = marshaller{data: w.Document}.WriteTo(f)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, err = f.Seek(0, io.SeekStart)
if err != nil {
t.Fatal(err)
}
w = New()
err = xml.NewDecoder(f).Decode(&w.Document)
if err != nil {
t.Fatal(err)
}
f1, err := os.Create("test1.xml")
if err != nil {
t.Fatal(err)
}
defer f1.Close()
_, err = marshaller{data: w.Document}.WriteTo(f1)
if err != nil {
t.Fatal(err)
}
t.Fail() t.Fail()
} }

70
structdrawing.go Normal file
View File

@@ -0,0 +1,70 @@
package docxlib
import (
"encoding/xml"
"io"
)
// Drawing element contains photos
type Drawing struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main drawing,omitempty"`
Inline *WPInline
}
func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "inline":
r.Inline = new(WPInline)
r.Inline.DistT = getAtt(tt.Attr, "distT")
r.Inline.DistB = getAtt(tt.Attr, "distB")
r.Inline.DistL = getAtt(tt.Attr, "distL")
r.Inline.DistR = getAtt(tt.Attr, "distR")
d.DecodeElement(r.Inline, &start)
default:
continue
}
}
}
return nil
}
// WPInline wp:inline
type WPInline struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing inline,omitempty"`
DistT string `xml:"distT,attr"`
DistB string `xml:"distB,attr"`
DistL string `xml:"distL,attr"`
DistR string `xml:"distR,attr"`
}
func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "inline":
default:
continue
}
}
}
return nil
}

34
structlink.go Normal file
View File

@@ -0,0 +1,34 @@
package docxlib
import (
"encoding/xml"
"io"
)
// Hyperlink element contains links
type Hyperlink struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main hyperlink,omitempty"`
ID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr"`
Run Run
}
func (r *Hyperlink) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.StartElement:
if tt.Name.Local == "r" {
d.DecodeElement(&r.Run, &start)
} else {
continue
}
}
}
return nil
}

View File

@@ -19,69 +19,6 @@ type Run struct {
Drawing *Drawing Drawing *Drawing
} }
// Text object contains the actual text
type Text struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main t"`
XMLSpace string `xml:"xml:space,attr,omitempty"`
Text string `xml:",chardata"`
}
// Hyperlink element contains links
type Hyperlink struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main hyperlink,omitempty"`
ID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr"`
Run Run
}
// Drawing element contains photos
type Drawing struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main drawing,omitempty"`
Inline *WPInline
}
// WPInline wp:inline
type WPInline struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing inline,omitempty"`
DistT string `xml:"distT,attr"`
DistB string `xml:"distB,attr"`
DistL string `xml:"distL,attr"`
DistR string `xml:"distR,attr"`
}
// RunProperties encapsulates visual properties of a run
type RunProperties struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rPr,omitempty"`
Color *Color `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main color,omitempty"`
Size *Size `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main sz,omitempty"`
RunStyle *RunStyle `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rStyle,omitempty"`
Style *Style `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main pStyle,omitempty"`
}
// RunStyle contains styling for a run
type RunStyle struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rStyle,omitempty"`
Val string `xml:"w:val,attr"`
}
// Style contains styling for a paragraph
type Style struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main pStyle,omitempty"`
Val string `xml:"w:val,attr"`
}
// Color contains the sound of music. :D
// I'm kidding. It contains the color
type Color struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main color"`
Val string `xml:"w:val,attr"`
}
// Size contains the font size
type Size struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main sz"`
Val int `xml:"w:val,attr"`
}
func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error { func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for { for {
t, err := d.Token() t, err := d.Token()
@@ -118,43 +55,17 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return nil return nil
} }
func (r *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) { // RunProperties encapsulates visual properties of a run
case xml.CharData: type RunProperties struct {
r.Text = string(tt) // implicitly copy XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rPr,omitempty"`
} Color *Color `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main color,omitempty"`
Size *Size `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main sz,omitempty"`
} RunStyle *RunStyle `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rStyle,omitempty"`
Style *Style `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main pStyle,omitempty"`
return nil
} }
func (r *Hyperlink) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) { func (r *RunProperties) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
case xml.StartElement:
if tt.Name.Local == "r" {
d.DecodeElement(&r.Run, &start)
} else {
continue
}
}
}
return nil
}
func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for { for {
t, err := d.Token() t, err := d.Token()
if err == io.EOF { if err == io.EOF {
@@ -164,65 +75,54 @@ func (r *Drawing) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
switch tt := t.(type) { switch tt := t.(type) {
case xml.StartElement: case xml.StartElement:
switch tt.Name.Local { switch tt.Name.Local {
case "inline": case "color":
r.Inline = new(WPInline) var value Color
r.Inline.DistT = getAtt(tt.Attr, "distT") value.Val = getAtt(tt.Attr, "val")
r.Inline.DistB = getAtt(tt.Attr, "distB") r.Color = &value
r.Inline.DistL = getAtt(tt.Attr, "distL") case "sz":
r.Inline.DistR = getAtt(tt.Attr, "distR") var value Size
d.DecodeElement(r.Inline, &start) value.Val = getAtt(tt.Attr, "val")
r.Size = &value
case "rStyle":
var value RunStyle
value.Val = getAtt(tt.Attr, "val")
r.RunStyle = &value
case "pStyle":
var value Style
value.Val = getAtt(tt.Attr, "val")
r.Style = &value
default: default:
continue continue
} }
} }
} }
return nil
}
func (r *WPInline) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "inline":
default:
continue
}
}
}
return nil
}
func (r *RunStyle) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.StartElement:
r.Val = getAtt(tt.Attr, "val")
}
}
return nil return nil
} }
func getAtt(atts []xml.Attr, name string) string { // RunStyle contains styling for a run
for _, at := range atts { type RunStyle struct {
if at.Name.Local == name { XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main rStyle,omitempty"`
return at.Value Val string `xml:"w:val,attr"`
} }
}
return "" // Style contains styling for a paragraph
type Style struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main pStyle,omitempty"`
Val string `xml:"w:val,attr"`
}
// Color contains the sound of music. :D
// I'm kidding. It contains the color
type Color struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main color"`
Val string `xml:"w:val,attr"`
}
// Size contains the font size
type Size struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main sz"`
Val string `xml:"w:val,attr"`
} }

30
structtext.go Normal file
View File

@@ -0,0 +1,30 @@
package docxlib
import (
"encoding/xml"
"io"
)
// Text object contains the actual text
type Text struct {
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main t"`
XMLSpace string `xml:"xml:space,attr,omitempty"`
Text string `xml:",chardata"`
}
func (r *Text) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
for {
t, err := d.Token()
if err == io.EOF {
break
}
switch tt := t.(type) {
case xml.CharData:
r.Text = string(tt) // implicitly copy
}
}
return nil
}

View File

@@ -1,16 +1,16 @@
package docxlib package docxlib
// This contains internal functions needed to unpack (read) a zip file
import ( import (
"archive/zip" "archive/zip"
"bytes" "bytes"
"encoding/xml" "encoding/xml"
) )
// This receives a zip file (word documents are a zip with multiple xml inside) // unpack receives a zip file (word documents are a zip with multiple xml inside)
// and parses the files that are relevant for us: // and parses the files that are relevant for us:
// 1.-Document //
// 2.-Relationships // 1. Document
// 2. Relationships
func unpack(zipReader *zip.Reader) (docx *Docx, err error) { func unpack(zipReader *zip.Reader) (docx *Docx, err error) {
docx = new(Docx) docx = new(Docx)
for _, f := range zipReader.File { for _, f := range zipReader.File {