1
0
mirror of https://github.com/fumiama/go-docx.git synced 2026-06-05 07:40:24 +08:00

初步添加shape

This commit is contained in:
源文雨
2023-02-26 22:26:38 +08:00
parent 1f52bf35fe
commit c8aae913f2
6 changed files with 358 additions and 55 deletions

View File

@@ -31,9 +31,11 @@ func newEmptyA4File() *Docx {
XMLName: xml.Name{
Space: "w",
},
XMLW: XMLNS_W,
XMLR: XMLNS_R,
XMLWP: XMLNS_WP,
XMLW: XMLNS_W,
XMLR: XMLNS_R,
XMLWP: XMLNS_WP,
XMLWPS: XMLNS_WPS,
// XMLMC: XMLNS_MC,
// XMLWP14: XMLNS_WP14,
Body: Body{
Items: make([]interface{}, 0, 64),

View File

@@ -28,9 +28,11 @@ import (
//nolint:revive,stylecheck
const (
XMLNS_W = `http://schemas.openxmlformats.org/wordprocessingml/2006/main`
XMLNS_R = `http://schemas.openxmlformats.org/officeDocument/2006/relationships`
XMLNS_WP = `http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing`
XMLNS_W = `http://schemas.openxmlformats.org/wordprocessingml/2006/main`
XMLNS_R = `http://schemas.openxmlformats.org/officeDocument/2006/relationships`
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_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>
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
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
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
Body Body `xml:"w:body"`

View File

@@ -741,10 +741,6 @@ func (p *PICSpPr) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return err
}
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")
default:
err = d.Skip() // skip unsupported tags

View File

@@ -49,56 +49,92 @@ func (r *Run) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
return err
}
var child interface{}
if tt, ok := t.(xml.StartElement); ok {
switch tt.Name.Local {
case "rPr":
var value RunProperties
err = d.DecodeElement(&value, &tt)
if err != nil && !strings.HasPrefix(err.Error(), "expected") {
return err
}
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
child, err := r.parse(d, tt)
if err != nil {
return err
}
if child != nil {
r.Children = append(r.Children, child)
}
r.Children = append(r.Children, child)
}
}
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
type RunProperties struct {
XMLName xml.Name `xml:"w:rPr,omitempty"`

263
structshape.go Normal file
View 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"`
}

View File

@@ -81,6 +81,8 @@ func (f *Docx) parseDocument(file *zip.File) error {
f.Document.XMLW = XMLNS_W
f.Document.XMLR = XMLNS_R
f.Document.XMLWP = XMLNS_WP
// f.Document.XMLMC = XMLNS_MC
f.Document.XMLWPS = XMLNS_WPS
// f.Document.XMLWP14 = XMLNS_WP14
f.Document.XMLName.Space = XMLNS_W
f.Document.XMLName.Local = "document"