From 83e12cc4e5242904366a51f642596acbc9f9dd56 Mon Sep 17 00:00:00 2001 From: xuri Date: Fri, 11 Jun 2021 22:48:37 +0800 Subject: [PATCH] support escaped string literal basic string and use GitHub Action instead of TravisCI - Note that: travis-ci.org will shutdown on June 15th, 2021, and I don't have enough permission to migrate this project to travis-ci.com currently --- .travis.yml | 25 ------------------------ README.md | 6 +++++- README_zh.md | 6 +++++- chart.go | 4 ++++ lib.go | 46 +++++++++++++++++++++++++++++++++++++++++++++ lib_test.go | 19 +++++++++++++++++++ xmlSharedStrings.go | 4 ++-- 7 files changed, 81 insertions(+), 29 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 34ce8ee..0000000 --- a/.travis.yml +++ /dev/null @@ -1,25 +0,0 @@ -language: go - -install: - - go get -d -t -v ./... && go build -v ./... - -go: - - 1.15.x - - 1.16.x - -os: - - linux - - osx - - windows - -env: - jobs: - - GOARCH=amd64 - - GOARCH=386 - -script: - - env GO111MODULE=on go vet ./... - - env GO111MODULE=on go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/README.md b/README.md index 5beea06..972d013 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Excelize logo

- Build Status + Build Status Code Coverage Go Report Card go.dev @@ -86,6 +86,10 @@ func main() { fmt.Println(cell) // Get all the rows in the Sheet1. rows, err := f.GetRows("Sheet1") + if err != nil { + fmt.Println(err) + return + } for _, row := range rows { for _, colCell := range row { fmt.Print(colCell, "\t") diff --git a/README_zh.md b/README_zh.md index b8c0201..4e1f56f 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,7 +1,7 @@

Excelize logo

- Build Status + Build Status Code Coverage Go Report Card go.dev @@ -86,6 +86,10 @@ func main() { fmt.Println(cell) // 获取 Sheet1 上所有单元格 rows, err := f.GetRows("Sheet1") + if err != nil { + fmt.Println(err) + return + } for _, row := range rows { for _, colCell := range row { fmt.Print(colCell, "\t") diff --git a/chart.go b/chart.go index 23ea776..9bc4b20 100644 --- a/chart.go +++ b/chart.go @@ -739,6 +739,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // Set the primary horizontal and vertical axis options by x_axis and y_axis. The properties of x_axis that can be set are: // +// none // major_grid_lines // minor_grid_lines // tick_label_skip @@ -748,6 +749,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // // The properties of y_axis that can be set are: // +// none // major_grid_lines // minor_grid_lines // major_unit @@ -755,6 +757,8 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) { // maximum // minimum // +// none: Disable axes. +// // major_grid_lines: Specifies major gridlines. // // minor_grid_lines: Specifies minor gridlines. diff --git a/lib.go b/lib.go index 99083b1..e221d17 100644 --- a/lib.go +++ b/lib.go @@ -18,6 +18,7 @@ import ( "encoding/xml" "fmt" "io" + "regexp" "strconv" "strings" ) @@ -454,6 +455,51 @@ func isNumeric(s string) (bool, int) { return true, p } +// bstrUnmarshal parses the binary basic string, this will trim escaped string +// literal which not permitted in an XML 1.0 document. The basic string +// variant type can store any valid Unicode character. Unicode characters +// that cannot be directly represented in XML as defined by the XML 1.0 +// specification, shall be escaped using the Unicode numerical character +// representation escape character format _xHHHH_, where H represents a +// hexadecimal character in the character's value. For example: The Unicode +// character 8 is not permitted in an XML 1.0 document, so it shall be +// escaped as _x0008_. To store the literal form of an escape sequence, the +// initial underscore shall itself be escaped (i.e. stored as _x005F_). For +// example: The string literal _x0008_ would be stored as _x005F_x0008_. +func bstrUnmarshal(s string) (result string) { + m := regexp.MustCompile(`_x[a-zA-Z0-9]{4}_`) + escapeExp := regexp.MustCompile(`x[a-zA-Z0-9]{4}_`) + matches := m.FindAllStringSubmatchIndex(s, -1) + var cursor int + for _, match := range matches { + result += s[cursor:match[0]] + if s[match[0]:match[1]] == "_x005F_" { + if len(s) > match[1]+6 && !escapeExp.MatchString(s[match[1]:match[1]+6]) { + result += s[match[0]:match[1]] + cursor = match[1] + continue + } + if len(s) > match[1]+5 && s[match[1]:match[1]+5] == "x005F" { + result += "_" + cursor = match[1] + continue + } + if escapeExp.MatchString(s[match[0]:match[1]]) { + result += "_" + cursor = match[1] + continue + } + } + if escapeExp.MatchString(s[match[0]:match[1]]) { + cursor = match[1] + } + } + if cursor < len(s) { + result += s[cursor:] + } + return result +} + // Stack defined an abstract data type that serves as a collection of elements. type Stack struct { list *list.List diff --git a/lib_test.go b/lib_test.go index eb0a289..bd28c7e 100644 --- a/lib_test.go +++ b/lib_test.go @@ -234,3 +234,22 @@ func TestGenXMLNamespace(t *testing.T) { {Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve"}, }), `xml:space="preserve">`) } + +func TestBstrUnmarshal(t *testing.T) { + bstrs := map[string]string{ + "*": "*", + "*_x0008_": "*", + "_x0008_*": "*", + "*_x0008_*": "**", + "*_x005F__x0008_*": "*_x005F_*", + "*_x005F_x0001_*": "*_x0001_*", + "*_x005F_x005F_x005F_x0006_*": "*_x005F_x0006_*", + "_x005F__x0008_******": "_x005F_******", + "******_x005F__x0008_": "******_x005F_", + "******_x005F__x0008_******": "******_x005F_******", + "*_x005F_x005F__x0008_*": "*_x005F_*", + } + for bstr, expected := range bstrs { + assert.Equal(t, expected, bstrUnmarshal(bstr)) + } +} diff --git a/xmlSharedStrings.go b/xmlSharedStrings.go index 7cb23fd..816c931 100644 --- a/xmlSharedStrings.go +++ b/xmlSharedStrings.go @@ -53,10 +53,10 @@ func (x xlsxSI) String() string { rows.WriteString(s.T.Val) } } - return rows.String() + return bstrUnmarshal(rows.String()) } if x.T != nil { - return x.T.Val + return bstrUnmarshal(x.T.Val) } return "" }