1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
|
// Copyright 2016 Charles Banning. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
package mxj
import (
"bytes"
)
var xmlEscapeChars bool
// XMLEscapeChars(true) forces escaping invalid characters in attribute and element values.
// NOTE: this is brute force with NO interrogation of '&' being escaped already; if it is
// then '&' will be re-escaped as '&'.
//
/*
The values are:
" "
' '
< <
> >
& &
*/
//
// Note: if XMLEscapeCharsDecoder(true) has been called - or the default, 'false,' value
// has been toggled to 'true' - then XMLEscapeChars(true) is ignored. If XMLEscapeChars(true)
// has already been called before XMLEscapeCharsDecoder(true), XMLEscapeChars(false) is called
// to turn escape encoding on mv.Xml, etc., to prevent double escaping ampersands, '&'.
func XMLEscapeChars(b ...bool) {
var bb bool
if len(b) == 0 {
bb = !xmlEscapeChars
} else {
bb = b[0]
}
if bb == true && xmlEscapeCharsDecoder == false {
xmlEscapeChars = true
} else {
xmlEscapeChars = false
}
}
// Scan for '&' first, since 's' may contain "&" that is parsed to "&amp;"
// - or "<" that is parsed to "&lt;".
var escapechars = [][2][]byte{
{[]byte(`&`), []byte(`&`)},
{[]byte(`<`), []byte(`<`)},
{[]byte(`>`), []byte(`>`)},
{[]byte(`"`), []byte(`"`)},
{[]byte(`'`), []byte(`'`)},
}
func escapeChars(s string) string {
if len(s) == 0 {
return s
}
b := []byte(s)
for _, v := range escapechars {
n := bytes.Count(b, v[0])
if n == 0 {
continue
}
b = bytes.Replace(b, v[0], v[1], n)
}
return string(b)
}
// per issue #84, escape CharData values from xml.Decoder
var xmlEscapeCharsDecoder bool
// XMLEscapeCharsDecoder(b ...bool) escapes XML characters in xml.CharData values
// returned by Decoder.Token. Thus, the internal Map values will contain escaped
// values, and you do not need to set XMLEscapeChars for proper encoding.
//
// By default, the Map values have the non-escaped values returned by Decoder.Token.
// XMLEscapeCharsDecoder(true) - or, XMLEscapeCharsDecoder() - will toggle escape
// encoding 'on.'
//
// Note: if XMLEscapeCharDecoder(true) is call then XMLEscapeChars(false) is
// called to prevent re-escaping the values on encoding using mv.Xml, etc.
func XMLEscapeCharsDecoder(b ...bool) {
if len(b) == 0 {
xmlEscapeCharsDecoder = !xmlEscapeCharsDecoder
} else {
xmlEscapeCharsDecoder = b[0]
}
if xmlEscapeCharsDecoder == true && xmlEscapeChars == true {
xmlEscapeChars = false
}
}
|