diff --git a/README.md b/README.md index 87da82b..89141e3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Library for parsing and manipulating SVG files. ### Installation - go get github.com/JoshVarga/svgparser + go get svgparser ### Features diff --git a/example_test.go b/example_test.go index c8c5aff..4f74409 100644 --- a/example_test.go +++ b/example_test.go @@ -2,10 +2,9 @@ package svgparser_test import ( "fmt" + "github.com/sergesheff/svgparser" + "github.com/sergesheff/svgparser/utils" "strings" - - "github.com/JoshVarga/svgparser" - "github.com/JoshVarga/svgparser/utils" ) func ExampleParse() { diff --git a/find.go b/find.go index 62abd35..9be8f63 100644 --- a/find.go +++ b/find.go @@ -1,5 +1,7 @@ package svgparser +import "strings" + // FindID finds the first child with the specified ID. func (e *Element) FindID(id string) *Element { for _, child := range e.Children { @@ -24,3 +26,25 @@ func (e *Element) FindAll(name string) []*Element { } return elements } + +// FindByCharData finds all children with the given chardata. +func (e *Element) FindByCharData(text string) []*Element { + if e == nil { + return nil + } + + text = strings.ToLower(text) + + var elements []*Element + for _, child := range e.Children { + if child == nil { + continue + } + + if strings.Contains(strings.ToLower(child.Content), text) { + elements = append(elements, child) + } + elements = append(elements, child.FindByCharData(text)...) + } + return elements +} diff --git a/find_test.go b/find_test.go index 7754ea1..2844ff9 100644 --- a/find_test.go +++ b/find_test.go @@ -1,9 +1,8 @@ package svgparser_test import ( + "github.com/sergesheff/svgparser" "testing" - - "github.com/JoshVarga/svgparser" ) func testElement() *svgparser.Element { diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..61effbf --- /dev/null +++ b/go.mod @@ -0,0 +1,7 @@ +module github.com/sergesheff/svgparser + +go 1.20.0 + +require golang.org/x/net v0.26.0 + +require golang.org/x/text v0.16.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..1292c61 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= diff --git a/parser.go b/parser.go index cd9a398..f14c691 100644 --- a/parser.go +++ b/parser.go @@ -3,10 +3,10 @@ package svgparser import ( "bytes" "encoding/xml" + "golang.org/x/net/html/charset" "io" "io/ioutil" "strings" - "golang.org/x/net/html/charset" ) // ValidationError contains errors which have occured when parsing svg input. @@ -23,11 +23,12 @@ type Element struct { Name string Attributes map[string]string Children []*Element + Parent *Element Content string } // NewElement creates element from decoder token. -func NewElement(token xml.StartElement) *Element { +func NewElement(token xml.StartElement, parent *Element) *Element { element := &Element{} attributes := make(map[string]string) for _, attr := range token.Attr { @@ -35,6 +36,8 @@ func NewElement(token xml.StartElement) *Element { } element.Name = token.Name.Local element.Attributes = attributes + element.Parent = parent + return element } @@ -74,7 +77,7 @@ func DecodeFirst(decoder *xml.Decoder) (*Element, error) { switch element := token.(type) { case xml.StartElement: - return NewElement(element), nil + return NewElement(element, nil), nil } } return &Element{}, nil @@ -94,7 +97,7 @@ func (e *Element) Decode(decoder *xml.Decoder) error { switch element := token.(type) { case xml.StartElement: - nextElement := NewElement(element) + nextElement := NewElement(element, e) err := nextElement.Decode(decoder) if err != nil { return err @@ -134,3 +137,51 @@ func Parse(source io.Reader, validate bool) (*Element, error) { } return element, nil } + +func (el Element) MarshalXML(e *xml.Encoder, start xml.StartElement) error { + + openToken := xml.StartElement{ + Name: xml.Name{ + Local: el.Name, + }, + } + + if len(el.Attributes) > 0 { + openToken.Attr = []xml.Attr{} + + for key, value := range el.Attributes { + openToken.Attr = append(openToken.Attr, xml.Attr{ + Name: xml.Name{ + Local: key, + }, + Value: value, + }) + } + } + + if err := e.EncodeToken(openToken); err != nil { + return err + } + + if len(el.Content) > 0 { + if err := e.EncodeToken(xml.CharData(el.Content)); err != nil { + return err + } + } + + for _, c := range el.Children { + if c != nil { + if err := c.MarshalXML(e, openToken); err != nil { + return err + } + } + } + + closeToken := xml.EndElement{openToken.Name} + + if err := e.EncodeToken(closeToken); err != nil { + return err + } + + return e.Flush() +} diff --git a/parser_test.go b/parser_test.go index aacbb4e..c879ac5 100644 --- a/parser_test.go +++ b/parser_test.go @@ -3,7 +3,7 @@ package svgparser_test import ( "testing" - "github.com/JoshVarga/svgparser" + "github.com/sergesheff/svgparser" ) func TestParser(t *testing.T) { diff --git a/testutils_test.go b/testutils_test.go index aa8f26d..b70f39a 100644 --- a/testutils_test.go +++ b/testutils_test.go @@ -3,7 +3,7 @@ package svgparser_test import ( "strings" - "github.com/JoshVarga/svgparser" + "github.com/sergesheff/svgparser" ) func element(name string, attrs map[string]string) *svgparser.Element { diff --git a/utils/path_test.go b/utils/path_test.go index 4a884f6..dcd76c0 100644 --- a/utils/path_test.go +++ b/utils/path_test.go @@ -3,7 +3,7 @@ package utils_test import ( "testing" - "." + "github.com/sergesheff/svgparser/utils" ) func TestPathParser(t *testing.T) { diff --git a/utils/style_test.go b/utils/style_test.go index d9cac1d..3693a39 100644 --- a/utils/style_test.go +++ b/utils/style_test.go @@ -3,7 +3,7 @@ package utils_test import ( "testing" - "." + "github.com/sergesheff/svgparser/utils" ) func TestStyleParser(t *testing.T) {