Skip to content

Commit 34c4f96

Browse files
copy a modified method from a standard library
1 parent 547fe7a commit 34c4f96

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

cell.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -512,7 +512,7 @@ func trimCellValue(value string, escape bool) (v string, ns xml.Attr) {
512512
}
513513
if escape && value != "" {
514514
var buf bytes.Buffer
515-
_ = xml.EscapeText(&buf, []byte(value))
515+
_ = escapeText(&buf, []byte(value))
516516
value = buf.String()
517517
}
518518
if value != "" {

xml.go

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package excelize
2+
3+
// ---------------------------------------------------------
4+
// INFO: THIS FILE IS COPIED FROM THE STANDARD LIBRARY
5+
// REASON: to solve the problem with 'xml:space="preserve"' when value ends with '\n' and it replaces it with '&#xA';
6+
// ---------------------------------------------------------
7+
8+
import (
9+
"io"
10+
"unicode/utf8"
11+
)
12+
13+
var (
14+
escQuot = []byte(""") // shorter than """
15+
escApos = []byte("'") // shorter than "'"
16+
escAmp = []byte("&")
17+
escLT = []byte("<")
18+
escGT = []byte(">")
19+
escTab = []byte("	")
20+
escCR = []byte("
")
21+
escFFFD = []byte("\uFFFD") // Unicode replacement character
22+
)
23+
24+
// escapeText writes to w the properly escaped XML equivalent
25+
// of the plain text data s. If escapeNewline is true, newline
26+
// characters will be escaped.
27+
func escapeText(w io.Writer, s []byte) error {
28+
var esc []byte
29+
last := 0
30+
for i := 0; i < len(s); {
31+
r, width := utf8.DecodeRune(s[i:])
32+
i += width
33+
switch r {
34+
case '"':
35+
esc = escQuot
36+
case '\'':
37+
esc = escApos
38+
case '&':
39+
esc = escAmp
40+
case '<':
41+
esc = escLT
42+
case '>':
43+
esc = escGT
44+
case '\t':
45+
esc = escTab
46+
case '\r':
47+
esc = escCR
48+
default:
49+
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
50+
esc = escFFFD
51+
break
52+
}
53+
continue
54+
}
55+
if _, err := w.Write(s[last : i-width]); err != nil {
56+
return err
57+
}
58+
if _, err := w.Write(esc); err != nil {
59+
return err
60+
}
61+
last = i
62+
}
63+
_, err := w.Write(s[last:])
64+
return err
65+
}
66+
67+
// Decide whether the given rune is in the XML Character Range, per
68+
// the Char production of https://www.xml.com/axml/testaxml.htm,
69+
// Section 2.2 Characters.
70+
func isInCharacterRange(r rune) (inRange bool) {
71+
return r == 0x09 ||
72+
r == 0x0A ||
73+
r == 0x0D ||
74+
r >= 0x20 && r <= 0xD7FF ||
75+
r >= 0xE000 && r <= 0xFFFD ||
76+
r >= 0x10000 && r <= 0x10FFFF
77+
}

0 commit comments

Comments
 (0)