Parcourir la source

Fixe issue generated file corrupted caused by incorrect default XML namespace attributes

xuri il y a 4 ans
Parent
commit
7e429c5b46
11 fichiers modifiés avec 40 ajouts et 21 suppressions
  1. 1 1
      README.md
  2. 1 1
      README_zh.md
  3. 1 1
      excelize_test.go
  4. 3 0
      lib.go
  5. 6 0
      lib_test.go
  6. 5 5
      stream.go
  7. 11 1
      stream_test.go
  8. 3 4
      styles.go
  9. 1 1
      table.go
  10. 1 0
      xmlDrawing.go
  11. 7 7
      xmlStyles.go

+ 1 - 1
README.md

@@ -204,7 +204,7 @@ func main() {
 
 ## Contributing
 
-Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change. XML is compliant with [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](http://www.ecma-international.org/publications/standards/Ecma-376.htm).
+Contributions are welcome! Open a pull request to fix a bug, or open an issue to discuss a new feature or change. XML is compliant with [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/).
 
 ## Licenses
 

+ 1 - 1
README_zh.md

@@ -204,7 +204,7 @@ func main() {
 
 ## 社区合作
 
-欢迎您为此项目贡献代码,提出建议或问题、修复 Bug 以及参与讨论对新功能的想法。 XML 符合标准: [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](http://www.ecma-international.org/publications/standards/Ecma-376.htm)。
+欢迎您为此项目贡献代码,提出建议或问题、修复 Bug 以及参与讨论对新功能的想法。 XML 符合标准: [part 1 of the 5th edition of the ECMA-376 Standard for Office Open XML](https://www.ecma-international.org/publications-and-standards/standards/ecma-376/)。
 
 ## 开源许可
 

+ 1 - 1
excelize_test.go

@@ -54,7 +54,7 @@ func TestOpenFile(t *testing.T) {
 
 	assert.NoError(t, f.SetCellStr("Sheet2", "C11", "Knowns"))
 	// Test max characters in a cell.
-	assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", 32769)))
+	assert.NoError(t, f.SetCellStr("Sheet2", "D11", strings.Repeat("c", TotalCellChars+2)))
 	f.NewSheet(":\\/?*[]Maximum 31 characters allowed in sheet title.")
 	// Test set worksheet name with illegal name.
 	f.SetSheetName("Maximum 31 characters allowed i", "[Rename]:\\/?* Maximum 31 characters allowed in sheet title.")

+ 3 - 0
lib.go

@@ -349,6 +349,9 @@ func genXMLNamespace(attr []xml.Attr) string {
 	var rootElement string
 	for _, v := range attr {
 		if lastSpace := getXMLNamespace(v.Name.Space, attr); lastSpace != "" {
+			if lastSpace == NameSpaceXML {
+				lastSpace = "xml"
+			}
 			rootElement += fmt.Sprintf("%s:%s=\"%s\" ", lastSpace, v.Name.Local, v.Value)
 			continue
 		}

+ 6 - 0
lib_test.go

@@ -228,3 +228,9 @@ func TestStack(t *testing.T) {
 	assert.Equal(t, s.Peek(), nil)
 	assert.Equal(t, s.Pop(), nil)
 }
+
+func TestGenXMLNamespace(t *testing.T) {
+	assert.Equal(t, genXMLNamespace([]xml.Attr{
+		{Name: xml.Name{Space: NameSpaceXML, Local: "space"}, Value: "preserve"},
+	}), `xml:space="preserve">`)
+}

+ 5 - 5
stream.go

@@ -40,8 +40,9 @@ type StreamWriter struct {
 // generate new worksheet with large amounts of data. Note that after set
 // rows, you must call the 'Flush' method to end the streaming writing
 // process and ensure that the order of line numbers is ascending, the common
-// API and stream API can't be work mixed to writing data on the worksheets.
-// For example, set data for worksheet of size 102400 rows x 50 columns with
+// API and stream API can't be work mixed to writing data on the worksheets,
+// you can't get cell value when in-memory chunks data over 16MB. For
+// example, set data for worksheet of size 102400 rows x 50 columns with
 // numbers and style:
 //
 //    file := excelize.NewFile()
@@ -111,7 +112,7 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
 // AddTable creates an Excel table for the StreamWriter using the given
 // coordinate area and format set. For example, create a table of A1:D5:
 //
-//    err := sw.AddTable("A1", "D5", ``)
+//    err := sw.AddTable("A1", "D5", "")
 //
 // Create a table of F2:H6 with format set:
 //
@@ -500,8 +501,7 @@ func (bw *bufferedWriter) Reader() (io.Reader, error) {
 // buffer has grown large enough. Any error will be returned.
 func (bw *bufferedWriter) Sync() (err error) {
 	// Try to use local storage
-	const chunk = 1 << 24
-	if bw.buf.Len() < chunk {
+	if bw.buf.Len() < StreamChunkSize {
 		return nil
 	}
 	if bw.tmp == nil {

+ 11 - 1
stream_test.go

@@ -40,7 +40,7 @@ func TestStreamWriter(t *testing.T) {
 
 	// Test max characters in a cell.
 	row := make([]interface{}, 1)
-	row[0] = strings.Repeat("c", 32769)
+	row[0] = strings.Repeat("c", TotalCellChars+2)
 	assert.NoError(t, streamWriter.SetRow("A1", row))
 
 	// Test leading and ending space(s) character characters in a cell.
@@ -100,6 +100,16 @@ func TestStreamWriter(t *testing.T) {
 	file.XLSX["xl/worksheets/sheet1.xml"] = MacintoshCyrillicCharset
 	_, err = file.NewStreamWriter("Sheet1")
 	assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8")
+
+	// Test read cell.
+	file = NewFile()
+	streamWriter, err = file.NewStreamWriter("Sheet1")
+	assert.NoError(t, err)
+	assert.NoError(t, streamWriter.SetRow("A1", []interface{}{Cell{StyleID: styleID, Value: "Data"}}))
+	assert.NoError(t, streamWriter.Flush())
+	cellValue, err := file.GetCellValue("Sheet1", "A1")
+	assert.NoError(t, err)
+	assert.Equal(t, "Data", cellValue)
 }
 
 func TestStreamTable(t *testing.T) {

+ 3 - 4
styles.go

@@ -2187,17 +2187,16 @@ func (f *File) newFont(style *Style) *xlsxFont {
 		Family: &attrValInt{Val: intPtr(2)},
 	}
 	if style.Font.Bold {
-		fnt.B = &style.Font.Bold
+		fnt.B = &attrValBool{Val: &style.Font.Bold}
 	}
 	if style.Font.Italic {
-		fnt.I = &style.Font.Italic
+		fnt.I = &attrValBool{Val: &style.Font.Italic}
 	}
 	if *fnt.Name.Val == "" {
 		*fnt.Name.Val = f.GetDefaultFont()
 	}
 	if style.Font.Strike {
-		strike := true
-		fnt.Strike = &strike
+		fnt.Strike = &attrValBool{Val: &style.Font.Strike}
 	}
 	val, ok := fontUnderlineType[style.Font.Underline]
 	if ok {

+ 1 - 1
table.go

@@ -35,7 +35,7 @@ func parseFormatTableSet(formatSet string) (*formatTable, error) {
 // name, coordinate area and format set. For example, create a table of A1:D5
 // on Sheet1:
 //
-//    err := f.AddTable("Sheet1", "A1", "D5", ``)
+//    err := f.AddTable("Sheet1", "A1", "D5", "")
 //
 // Create a table of F2:H6 on Sheet2 with format set:
 //

+ 1 - 0
xmlDrawing.go

@@ -91,6 +91,7 @@ const (
 
 // Excel specifications and limits
 const (
+	StreamChunkSize      = 1 << 24
 	MaxFontFamilyLength  = 31
 	MaxFontSize          = 409
 	MaxFileNameLength    = 207

+ 7 - 7
xmlStyles.go

@@ -83,13 +83,13 @@ type xlsxFonts struct {
 // xlsxFont directly maps the font element. This element defines the
 // properties for one of the fonts used in this workbook.
 type xlsxFont struct {
-	B        *bool          `xml:"b,omitempty"`
-	I        *bool          `xml:"i,omitempty"`
-	Strike   *bool          `xml:"strike,omitempty"`
-	Outline  *bool          `xml:"outline,omitempty"`
-	Shadow   *bool          `xml:"shadow,omitempty"`
-	Condense *bool          `xml:"condense,omitempty"`
-	Extend   *bool          `xml:"extend,omitempty"`
+	B        *attrValBool   `xml:"b,omitempty"`
+	I        *attrValBool   `xml:"i,omitempty"`
+	Strike   *attrValBool   `xml:"strike,omitempty"`
+	Outline  *attrValBool   `xml:"outline,omitempty"`
+	Shadow   *attrValBool   `xml:"shadow,omitempty"`
+	Condense *attrValBool   `xml:"condense,omitempty"`
+	Extend   *attrValBool   `xml:"extend,omitempty"`
 	U        *attrValString `xml:"u"`
 	Sz       *attrValFloat  `xml:"sz"`
 	Color    *xlsxColor     `xml:"color"`