mirror of
https://github.com/fumiama/go-docx.git
synced 2026-06-11 19:10:24 +08:00
初步添加shape
This commit is contained in:
8
empty.go
8
empty.go
@@ -31,9 +31,11 @@ func newEmptyA4File() *Docx {
|
|||||||
XMLName: xml.Name{
|
XMLName: xml.Name{
|
||||||
Space: "w",
|
Space: "w",
|
||||||
},
|
},
|
||||||
XMLW: XMLNS_W,
|
XMLW: XMLNS_W,
|
||||||
XMLR: XMLNS_R,
|
XMLR: XMLNS_R,
|
||||||
XMLWP: XMLNS_WP,
|
XMLWP: XMLNS_WP,
|
||||||
|
XMLWPS: XMLNS_WPS,
|
||||||
|
// XMLMC: XMLNS_MC,
|
||||||
// XMLWP14: XMLNS_WP14,
|
// XMLWP14: XMLNS_WP14,
|
||||||
Body: Body{
|
Body: Body{
|
||||||
Items: make([]interface{}, 0, 64),
|
Items: make([]interface{}, 0, 64),
|
||||||
|
|||||||
16
structdoc.go
16
structdoc.go
@@ -28,9 +28,11 @@ import (
|
|||||||
|
|
||||||
//nolint:revive,stylecheck
|
//nolint:revive,stylecheck
|
||||||
const (
|
const (
|
||||||
XMLNS_W = `http://schemas.openxmlformats.org/wordprocessingml/2006/main`
|
XMLNS_W = `http://schemas.openxmlformats.org/wordprocessingml/2006/main`
|
||||||
XMLNS_R = `http://schemas.openxmlformats.org/officeDocument/2006/relationships`
|
XMLNS_R = `http://schemas.openxmlformats.org/officeDocument/2006/relationships`
|
||||||
XMLNS_WP = `http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing`
|
XMLNS_WP = `http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing`
|
||||||
|
XMLNS_WPS = `http://schemas.microsoft.com/office/word/2010/wordprocessingShape`
|
||||||
|
// XMLNS_MC = `http://schemas.openxmlformats.org/markup-compatibility/2006`
|
||||||
// XMLNS_WP14 = `http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing`
|
// XMLNS_WP14 = `http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing`
|
||||||
|
|
||||||
XMLNS_PICTURE = `http://schemas.openxmlformats.org/drawingml/2006/picture`
|
XMLNS_PICTURE = `http://schemas.openxmlformats.org/drawingml/2006/picture`
|
||||||
@@ -95,9 +97,11 @@ func (b *Body) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
// Document <w:document>
|
// Document <w:document>
|
||||||
type Document struct {
|
type Document struct {
|
||||||
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main document"`
|
XMLName xml.Name `xml:"http://schemas.openxmlformats.org/wordprocessingml/2006/main document"`
|
||||||
XMLW string `xml:"xmlns:w,attr"` // cannot be unmarshalled in
|
XMLW string `xml:"xmlns:w,attr"` // cannot be unmarshalled in
|
||||||
XMLR string `xml:"xmlns:r,attr,omitempty"` // 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
|
XMLWP string `xml:"xmlns:wp,attr,omitempty"` // cannot be unmarshalled in
|
||||||
|
XMLWPS string `xml:"xmlns:wps,attr,omitempty"` // cannot be unmarshalled in
|
||||||
|
// XMLMC string `xml:"xmlns:mc,attr,omitempty"` // cannot be unmarshalled in
|
||||||
// XMLWP14 string `xml:"xmlns:wp14,attr,omitempty"` // cannot be unmarshalled in
|
// XMLWP14 string `xml:"xmlns:wp14,attr,omitempty"` // cannot be unmarshalled in
|
||||||
|
|
||||||
Body Body `xml:"w:body"`
|
Body Body `xml:"w:body"`
|
||||||
|
|||||||
@@ -741,10 +741,6 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case "prstGeom":
|
case "prstGeom":
|
||||||
err = d.DecodeElement(&p.PrstGeom, &tt)
|
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
p.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
p.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
||||||
default:
|
default:
|
||||||
err = d.Skip() // skip unsupported tags
|
err = d.Skip() // skip unsupported tags
|
||||||
|
|||||||
120
structrun.go
120
structrun.go
@@ -49,56 +49,92 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var child interface{}
|
|
||||||
|
|
||||||
if tt, ok := t.(xml.StartElement); ok {
|
if tt, ok := t.(xml.StartElement); ok {
|
||||||
switch tt.Name.Local {
|
child, err := r.parse(d, tt)
|
||||||
case "rPr":
|
if err != nil {
|
||||||
var value RunProperties
|
return err
|
||||||
err = d.DecodeElement(&value, &tt)
|
}
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
if child != nil {
|
||||||
return err
|
r.Children = append(r.Children, child)
|
||||||
}
|
|
||||||
r.RunProperties = &value
|
|
||||||
continue
|
|
||||||
case "instrText":
|
|
||||||
var value string
|
|
||||||
err = d.DecodeElement(&value, &tt)
|
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.InstrText = value
|
|
||||||
continue
|
|
||||||
case "t":
|
|
||||||
var value Text
|
|
||||||
err = d.DecodeElement(&value, &tt)
|
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
child = &value
|
|
||||||
case "drawing":
|
|
||||||
var value Drawing
|
|
||||||
err = d.DecodeElement(&value, &tt)
|
|
||||||
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
child = &value
|
|
||||||
case "tab":
|
|
||||||
child = &Tab{}
|
|
||||||
default:
|
|
||||||
err = d.Skip() // skip unsupported tags
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
r.Children = append(r.Children, child)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Run) parse(d *xml.Decoder, tt xml.StartElement) (child interface{}, err error) {
|
||||||
|
switch tt.Name.Local {
|
||||||
|
case "rPr":
|
||||||
|
var value RunProperties
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r.RunProperties = &value
|
||||||
|
return nil, nil
|
||||||
|
case "instrText":
|
||||||
|
var value string
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r.InstrText = value
|
||||||
|
return nil, nil
|
||||||
|
case "t":
|
||||||
|
var value Text
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
child = &value
|
||||||
|
case "drawing":
|
||||||
|
var value Drawing
|
||||||
|
err = d.DecodeElement(&value, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
child = &value
|
||||||
|
case "tab":
|
||||||
|
child = &Tab{}
|
||||||
|
case "AlternateContent":
|
||||||
|
altcont:
|
||||||
|
for {
|
||||||
|
tok, err1 := d.Token()
|
||||||
|
if err1 == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err1 != nil {
|
||||||
|
return nil, err1
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
break altcont
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if et, ok := tok.(xml.EndElement); ok {
|
||||||
|
if et.Name.Local == "AlternateContent" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RunProperties encapsulates visual properties of a run
|
// RunProperties encapsulates visual properties of a run
|
||||||
type RunProperties struct {
|
type RunProperties struct {
|
||||||
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
XMLName xml.Name `xml:"w:rPr,omitempty"`
|
||||||
|
|||||||
263
structshape.go
Normal file
263
structshape.go
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
package docx
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"io"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WPSWordprocessingShape is a container for a WordprocessingML DrawingML shape.
|
||||||
|
type WPSWordprocessingShape struct {
|
||||||
|
XMLName xml.Name `xml:"wps:wsp,omitempty"`
|
||||||
|
CNvCnPr *WPSCNvCnPr
|
||||||
|
SpPr *WPSSpPr
|
||||||
|
BodyPr *WPSBodyPr
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (w *WPSWordprocessingShape) 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 "cNvCnPr":
|
||||||
|
w.CNvCnPr = new(WPSCNvCnPr)
|
||||||
|
err = d.DecodeElement(w.CNvCnPr, &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 "bodyPr":
|
||||||
|
w.BodyPr = new(WPSBodyPr)
|
||||||
|
err = d.DecodeElement(w.BodyPr, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// WPSCNvCnPr represents the non-visual drawing properties of a connector.
|
||||||
|
type WPSCNvCnPr struct {
|
||||||
|
XMLName xml.Name `xml:"wps:cNvCnPr,omitempty"`
|
||||||
|
ConnShapeLocks *struct{} `xml:"a:cxnSpLocks,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (w *WPSCNvCnPr) 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 "cxnSpLocks":
|
||||||
|
w.ConnShapeLocks = &struct{}{}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
Ln *ALine
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (w *WPSSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "bwMode":
|
||||||
|
w.BWMode = 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 "xfrm":
|
||||||
|
err = d.DecodeElement(&w.Xfrm, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "prstGeom":
|
||||||
|
w.PrstGeom.Prst = getAtt(tt.Attr, "prst")
|
||||||
|
case "noFill":
|
||||||
|
w.NoFill = &struct{}{}
|
||||||
|
case "ln":
|
||||||
|
w.Ln = &ALine{}
|
||||||
|
err = d.DecodeElement(&w.Ln, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ALine represents a line element in a Word document.
|
||||||
|
type ALine struct {
|
||||||
|
XMLName xml.Name `xml:"a:ln,omitempty"`
|
||||||
|
W int64 `xml:"w,attr"`
|
||||||
|
|
||||||
|
SolidFill *ASolidFill
|
||||||
|
Round *struct{} `xml:"a:round,omitempty"`
|
||||||
|
HeadEnd *struct{} `xml:"a:headEnd,omitempty"`
|
||||||
|
TailEnd *struct{} `xml:"a:tailEnd,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (l *ALine) UnmarshalXML(d *xml.Decoder, start xml.StartElement) (err error) {
|
||||||
|
for _, attr := range start.Attr {
|
||||||
|
switch attr.Name.Local {
|
||||||
|
case "w":
|
||||||
|
l.W, err = strconv.ParseInt(attr.Value, 10, 64)
|
||||||
|
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 "solidFill":
|
||||||
|
l.SolidFill = new(ASolidFill)
|
||||||
|
err = d.DecodeElement(l.SolidFill, &tt)
|
||||||
|
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "round":
|
||||||
|
l.Round = &struct{}{}
|
||||||
|
case "headEnd":
|
||||||
|
l.HeadEnd = &struct{}{}
|
||||||
|
case "tailEnd":
|
||||||
|
l.TailEnd = &struct{}{}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported tags
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASolidFill represents a solid fill of a shape or chart element.
|
||||||
|
type ASolidFill struct {
|
||||||
|
XMLName xml.Name `xml:"a:solidFill,omitempty"`
|
||||||
|
SrgbClr *ASrgbClr
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalXML ...
|
||||||
|
func (s *ASolidFill) 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 "srgbClr":
|
||||||
|
s.SrgbClr = new(ASrgbClr)
|
||||||
|
for _, attr := range tt.Attr {
|
||||||
|
if attr.Name.Local == "val" {
|
||||||
|
s.SrgbClr.Val = attr.Value
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = d.Skip() // skip unsupported elements
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
err = d.Skip() // skip unsupported elements
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASrgbClr represents an sRGB color.
|
||||||
|
type ASrgbClr struct {
|
||||||
|
XMLName xml.Name `xml:"a:srgbClr,omitempty"`
|
||||||
|
Val string `xml:"val,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// WPSBodyPr represents the body properties for a WordprocessingML DrawingML shape.
|
||||||
|
type WPSBodyPr struct {
|
||||||
|
XMLName xml.Name `xml:"wps:bodyPr,omitempty"`
|
||||||
|
}
|
||||||
@@ -81,6 +81,8 @@ func (f *Docx) parseDocument(file *zip.File) error {
|
|||||||
f.Document.XMLW = XMLNS_W
|
f.Document.XMLW = XMLNS_W
|
||||||
f.Document.XMLR = XMLNS_R
|
f.Document.XMLR = XMLNS_R
|
||||||
f.Document.XMLWP = XMLNS_WP
|
f.Document.XMLWP = XMLNS_WP
|
||||||
|
// f.Document.XMLMC = XMLNS_MC
|
||||||
|
f.Document.XMLWPS = XMLNS_WPS
|
||||||
// f.Document.XMLWP14 = XMLNS_WP14
|
// f.Document.XMLWP14 = XMLNS_WP14
|
||||||
f.Document.XMLName.Space = XMLNS_W
|
f.Document.XMLName.Space = XMLNS_W
|
||||||
f.Document.XMLName.Local = "document"
|
f.Document.XMLName.Local = "document"
|
||||||
|
|||||||
Reference in New Issue
Block a user