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