162 lines
3.6 KiB
Go
Executable File
162 lines
3.6 KiB
Go
Executable File
package xml2json
|
|
|
|
import (
|
|
"strings"
|
|
)
|
|
|
|
type (
|
|
// an plugin is added to an encoder or/and to an decoder to allow custom functionality at runtime
|
|
plugin interface {
|
|
AddToEncoder(*Encoder) *Encoder
|
|
AddToDecoder(*Decoder) *Decoder
|
|
}
|
|
// a type converter overides the default string sanitization for encoding json
|
|
encoderTypeConverter interface {
|
|
Convert(string) string
|
|
}
|
|
// customTypeConverter converts strings to JSON types using a best guess approach, only parses the JSON types given
|
|
// when initialized via WithTypeConverter
|
|
customTypeConverter struct {
|
|
parseTypes []JSType
|
|
}
|
|
|
|
attrPrefixer string
|
|
contentPrefixer string
|
|
|
|
excluder []string
|
|
|
|
nodesFormatter struct {
|
|
list []nodeFormatter
|
|
}
|
|
nodeFormatter struct {
|
|
path string
|
|
plugin nodePlugin
|
|
}
|
|
|
|
nodePlugin interface {
|
|
AddTo(*Node)
|
|
}
|
|
|
|
arrayFormatter struct{}
|
|
)
|
|
|
|
// WithTypeConverter allows customized js type conversion behavior by passing in the desired JSTypes
|
|
func WithTypeConverter(ts ...JSType) *customTypeConverter {
|
|
return &customTypeConverter{parseTypes: ts}
|
|
}
|
|
|
|
func (tc *customTypeConverter) parseAsString(t JSType) bool {
|
|
if t == String {
|
|
return true
|
|
}
|
|
for i := 0; i < len(tc.parseTypes); i++ {
|
|
if tc.parseTypes[i] == t {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// Adds the type converter to the encoder
|
|
func (tc *customTypeConverter) AddToEncoder(e *Encoder) *Encoder {
|
|
e.tc = tc
|
|
return e
|
|
}
|
|
|
|
func (tc *customTypeConverter) AddToDecoder(d *Decoder) *Decoder {
|
|
return d
|
|
}
|
|
|
|
func (tc *customTypeConverter) Convert(s string) string {
|
|
// remove quotes if they exists
|
|
if strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) {
|
|
s = s[1 : len(s)-1]
|
|
}
|
|
jsType := Str2JSType(s)
|
|
if tc.parseAsString(jsType) {
|
|
// add the quotes removed at the start of this func
|
|
s = `"` + s + `"`
|
|
}
|
|
return s
|
|
}
|
|
|
|
// WithAttrPrefix appends the given prefix to the json output of xml attribute fields to preserve namespaces
|
|
func WithAttrPrefix(prefix string) *attrPrefixer {
|
|
ap := attrPrefixer(prefix)
|
|
return &ap
|
|
}
|
|
|
|
func (a *attrPrefixer) AddToEncoder(e *Encoder) *Encoder {
|
|
e.attributePrefix = string((*a))
|
|
return e
|
|
}
|
|
|
|
func (a *attrPrefixer) AddToDecoder(d *Decoder) *Decoder {
|
|
d.attributePrefix = string((*a))
|
|
return d
|
|
}
|
|
|
|
// WithContentPrefix appends the given prefix to the json output of xml content fields to preserve namespaces
|
|
func WithContentPrefix(prefix string) *contentPrefixer {
|
|
c := contentPrefixer(prefix)
|
|
return &c
|
|
}
|
|
|
|
func (c *contentPrefixer) AddToEncoder(e *Encoder) *Encoder {
|
|
e.contentPrefix = string((*c))
|
|
return e
|
|
}
|
|
|
|
func (c *contentPrefixer) AddToDecoder(d *Decoder) *Decoder {
|
|
d.contentPrefix = string((*c))
|
|
return d
|
|
}
|
|
|
|
// ExcludeAttributes excludes some xml attributes, for example, xmlns:xsi, xsi:noNamespaceSchemaLocation
|
|
func ExcludeAttributes(attrs []string) *excluder {
|
|
ex := excluder(attrs)
|
|
return &ex
|
|
}
|
|
|
|
func (ex *excluder) AddToEncoder(e *Encoder) *Encoder {
|
|
return e
|
|
}
|
|
|
|
func (ex *excluder) AddToDecoder(d *Decoder) *Decoder {
|
|
d.ExcludeAttributes([]string((*ex)))
|
|
return d
|
|
}
|
|
|
|
// WithNodes formats specific nodes
|
|
func WithNodes(n ...nodeFormatter) *nodesFormatter {
|
|
return &nodesFormatter{list: n}
|
|
}
|
|
|
|
func (nf *nodesFormatter) AddToEncoder(e *Encoder) *Encoder {
|
|
return e
|
|
}
|
|
|
|
func (nf *nodesFormatter) AddToDecoder(d *Decoder) *Decoder {
|
|
d.AddFormatters(nf.list)
|
|
return d
|
|
}
|
|
|
|
func NodePlugin(path string, plugin nodePlugin) nodeFormatter {
|
|
return nodeFormatter{path: path, plugin: plugin}
|
|
}
|
|
|
|
func (nf *nodeFormatter) Format(node *Node) {
|
|
child := node.GetChild(nf.path)
|
|
if child != nil {
|
|
nf.plugin.AddTo(child)
|
|
}
|
|
}
|
|
|
|
func ToArray() *arrayFormatter {
|
|
return &arrayFormatter{}
|
|
}
|
|
|
|
func (af *arrayFormatter) AddTo(n *Node) {
|
|
n.ChildrenAlwaysAsArray = true
|
|
}
|