zxml

package
v0.0.0-alpha.16 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2025 License: Apache-2.0 Imports: 9 Imported by: 1

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	CauseDataType    = "xmlconv: invalid data type."
	CauseJSONStruct  = "xmlconv: invalid json structure."
	CauseJSONKey     = "xmlconv: invalid json key."
	CauseEmptyVal    = "xmlconv: invalid empty value."
	CauseJSONEncoder = "xmlconv: json encoder return with an error."
	CauseJSONDecoder = "xmlconv: json decoder return with an error."
	CauseXMLEncoder  = "xmlconv: xml encoder return with an error."
	CauseXMLDecoder  = "xmlconv: xml decoder return with an error."
)

Functions

This section is empty.

Types

type BadgerFish

type BadgerFish struct {
	// TextKey is the json key name to store text content of elements.
	// Typically "$" is used.
	// TextKey should not be empty.
	TextKey string
	// AttrPrefix is the json key name prefix for XML attributes.
	// Attribute names are stored in json with this prefix.
	// For example, XML attribute foo="bar" is converted into {"@foo": "bar"}.
	// Typically "@" is used.
	// AttrPrefix should not be empty.
	AttrPrefix string
	// NamespaceSep is the name space separator.
	// Namespace separator ":" in XML element names are converted
	// into the specified string.
	// Use ":" if there is no reason to change.
	// NamespaceSep should not be empty.
	NamespaceSep string
	// TrimSpace if true, trims unicode space from xml text.
	// See the [unicode.IsSpace] for space definition.
	// This option is used in XML to JSON conversion.
	TrimSpace bool

	// XMLValue convert JSON value into XML value.
	// Input value is the any type value decoded by [json.Decoder].
	// Returned value is recognized by [xml.Encoder].
	// The given [xml.StartElement] can be modified in the function.
	// This option is used in JSON to XML conversion.
	XMLValue func(any, *xml.StartElement) (xml.Token, error)
	// JSONValue convert XML value into JSON value.
	// Input value is the text part of a XML element.
	// Returned value is recognized by [json.Encoder].
	// This function is used in XML to JSON conversion.
	JSONValue func(string, xml.StartElement) (any, error)
	// contains filtered or unexported fields
}

BadgerFish is the XML JSON converter following BadgerFish encode-decoder. Basic conversion rules are shown in the table below.

References:

Conversion Rules:

┌=====================================┐┌=====================================┐
│              XML Input              ││            JSON Output              |
└=====================================┘└=====================================┘

| A simple element without attributes or children.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>bob</alice>                  ││ {                                   │
│                                     ││   "alice": { "$": "bob" }           │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with attribute. Prefix "@" is added to the name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie="david">bob</alice>  ││ {                                   │
│                                     ││   "alice": {                        │
│                                     ││     "$": "bob",                     │
│                                     ││     "@charlie": "david"             │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have different name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "alice": {                        │
│   <david>edgar</david>              ││     "bob": { "$": "charlie" },      │
│ </alice>                            ││     "david": { "$": "edgar" }       │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have the same name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "alice": {                        │
│   <bob>edgar</bob>                  ││     "bob": [                        │
│ </alice>                            ││       { "$": "charlie" },           │
│                                     ││       { "$": "edgar" }              │
│                                     ││     ]                               │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with mixed content. Text contents are joined.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   bob                               ││   "alice": {                        │
│   <charlie>david</charlie>          ││     "$": "bobedgar",                │
│   edgar                             ││     "charlie": { "$": "david" }     │
│ </alice>                            ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with namespaces.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice xmlns:ns="http://abc.com/">  ││ {                                   │
│   <ns:bob>charlie</ns:bob>          ││   "alice": {                        │
│ </alice>                            ││     "@xmlns": {                     │
│                                     ││       "ns": "http://abc.com/"       │
│                                     ││     },                              │
│                                     ││     "ns:bob": { "$": "charlie" }    │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An empty element with empty attribute.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie=""></alice>          ││ {                                   │
│                                     ││   "alice": {                        │
│                                     ││     "@charlie": ""                  │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| [BadgerFish.WithEmptyValue] replaces the JSON value for empty elements.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- m := map[string]any{} -->      ││ {                                   │
│ <!-- WithEmptyValue(m) -->          ││   "alice": {}                       │
│ <alice></alice>                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue("") -->         ││ {                                   │
│ <alice></alice>                     ││   "alice": ""                       │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue(nil) -->        ││ {                                   │
│ <alice></alice>                     ││   "alice": null                     │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
Example (Jsonxml)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewBadgerFish(),
	}

	b, err := c.JSONtoXML([]byte(`{"alice":{"$":"bob","@charlie":"david"}}`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

<alice charlie="david">bob</alice>
Example (Xmljson)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewBadgerFish(),
	}

	b, err := c.XMLtoJSON([]byte(`<alice charlie="david">bob</alice>`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

{"alice":{"$":"bob","@charlie":"david"}}

func NewBadgerFish

func NewBadgerFish() *BadgerFish

NewBadgerFish returns a new instance of BadgerFish with default configuration.

func (*BadgerFish) Decode

func (b *BadgerFish) Decode(decoder *xml.Decoder) (any, error)

Decode decodes XML document read by the decoder into Go values.

Returned value can be:

  • map[string]any
  • []map[string]any

Decode:

func (*BadgerFish) Encode

func (b *BadgerFish) Encode(encoder *xml.Encoder, obj map[string]any) error

Encode encodes the given obj into XML document. Resulting XML is written into the encoder. See the comment on BadgerFish for conversion rules.

func (*BadgerFish) WithEmptyValue

func (b *BadgerFish) WithEmptyValue(v any)

WithEmptyValue replaces the value corresponding to empty element that do not have any attributes, text content and child elements. The given value is used in XML to JSON conversion. Allowed values are listed below and other will result in panic.

Allowed values are:

  • nil
  • string("")
  • make(map[string]any,0)

type EncodeDecoder

type EncodeDecoder interface {
	// Encode encodes the obj into XML document.
	// Structure of the obj must follow the implementer's instruction.
	Encode(encoder *xml.Encoder, obj map[string]any) error
	// Decode decodes XML document read from the decoder
	// into map[string]any or []map[string]any.
	Decode(decoder *xml.Decoder) (any, error)
}

EncodeDecoder provides interface for encoding and decoding XML document from/to JSON object.

type JSONConverter

type JSONConverter struct {
	EncodeDecoder
	// Header is the XML header line string.
	// If not empty, the value is written into the
	// header part of XML document.
	// Typically [encoding/xml.Header] should be used.
	Header string
	// contains filtered or unexported fields
}

JSONConverter converts XML to JSON document and JSON to XML document.

func (*JSONConverter) JSONtoXML

func (c *JSONConverter) JSONtoXML(b []byte) ([]byte, error)

JSONtoXML converts JSON document into XML document. Given json structure must follow the instruction of the [JSONConverter.EncodeDecoder].

func (*JSONConverter) WithJSONDecoderOpts

func (c *JSONConverter) WithJSONDecoderOpts(opts ...func(*json.Decoder))

WithJSONDecoderOpts registers JSON decoder options. Following example applies decoder to parse numbers as encoding/json.Number.

Example:

func(d *json.Decoder){
	d.UseNumber()
}
Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}
	c.WithJSONDecoderOpts(func(d *json.Decoder) {
		d.UseNumber()
	})

	b, err := c.JSONtoXML([]byte(`{"alice":{"$":1.2345678901234567890}}`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

<alice>1.2345678901234567890</alice>

func (*JSONConverter) WithJSONEncoderOpts

func (c *JSONConverter) WithJSONEncoderOpts(opts ...func(*json.Encoder))

WithJSONEncoderOpts registers JSON encoder options. Following example make the encoder not to apply HTML escape and to use indent.

Example:

func(e *json.Encoder) {
	e.SetEscapeHTML(false)
	e.SetIndent("", "  ")
}
Example
package main

import (
	"encoding/json"
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}
	c.WithJSONEncoderOpts(func(e *json.Encoder) {
		e.SetIndent("", "  ")
	})

	b, err := c.XMLtoJSON([]byte(`<alice>bob</alice>`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

{
  "alice": "bob"
}

func (*JSONConverter) WithXMLDecoderOpts

func (c *JSONConverter) WithXMLDecoderOpts(opts ...func(*xml.Decoder))

WithXMLDecoderOpts registers XML decoder options. Following example adds ability to read non UTF-8 XML document.

Example:

func(d *xml.Decoder) {
	d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
		switch {
		case strings.EqualFold(charset, "Shift_JIS"):
			return transform.NewReader(input, japanese.ShiftJIS.NewDecoder()), nil
		}
		return input, nil
	}
}
Example
package main

import (
	"encoding/xml"
	"fmt"
	"io"
	"strings"

	"github.com/aileron-projects/go/zencoding/zxml"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/transform"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}
	c.WithXMLDecoderOpts(func(d *xml.Decoder) {
		d.CharsetReader = func(charset string, input io.Reader) (io.Reader, error) {
			switch {
			case strings.EqualFold(charset, "Shift_JIS"):
				return transform.NewReader(input, japanese.ShiftJIS.NewDecoder()), nil
			}
			return input, nil
		}
	})

	header := `<?xml version="1.0" encoding="SHIFT_JIS"?>`
	b, err := c.XMLtoJSON([]byte(header + "<alice>\xea\x9f</alice>"))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

{"alice":"堯"}

func (*JSONConverter) WithXMLEncoderOpts

func (c *JSONConverter) WithXMLEncoderOpts(opts ...func(*xml.Encoder))

WithXMLEncoderOpts registers XML encoder options. Following example apply indent to the output.

Example:

func(e *xml.Encoder){
	e.Indent("", "  ")
}
Example
package main

import (
	"encoding/xml"
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}
	c.WithXMLEncoderOpts(func(e *xml.Encoder) {
		e.Indent("", "  ")
	})

	b, err := c.JSONtoXML([]byte(`{"alice":{"bob":{"$":"david"}}}`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

<alice>
  <bob>david</bob>
</alice>

func (*JSONConverter) XMLtoJSON

func (c *JSONConverter) XMLtoJSON(b []byte) ([]byte, error)

XMLtoJSON converts XML document into JSON document.

type RayFish

type RayFish struct {
	// NameKeys is the json key name to store
	// XML element names.
	// Typically "#name" is used.
	// NameKey should not be empty.
	NameKey string
	// TextKey is the json key name to store text content of elements.
	// Typically "#text" is used.
	// TextKey should not be empty.
	TextKey string
	// ChildrenKey is the json key name to store
	// attributes of a element and its child elements.
	// Typically "#children" is used.
	// ChildrenKey should not be empty.
	ChildrenKey string
	// AttrPrefix is the json key name prefix for XML attributes.
	// Attribute names are stored in json with this prefix.
	// For example, XML attribute foo="bar" is converted into {"@foo": "bar"}.
	// Typically "@" is used.
	// AttrPrefix should not be empty.
	AttrPrefix string
	// NamespaceSep is the name space separator.
	// Namespace separator ":" in XML element names are converted
	// into the specified string.
	// Note that general RayFish convention discards namespace information
	// but this encode-decoder keeps them.
	// Use ":" if there is no reason to change.
	// NamespaceSep should not be empty.
	NamespaceSep string
	// TrimSpace if true, trims unicode space from xml text.
	// See the [unicode.IsSpace] for space definition.
	// This option is used in XML to JSON conversion.
	TrimSpace bool

	// XMLValue convert JSON value into XML value.
	// Input value is the any type value decoded by [json.Decoder].
	// Returned value is recognized by [xml.Encoder].
	// The given [xml.StartElement] can be modified in the function.
	// This option is used in JSON to XML conversion.
	XMLValue func(any, *xml.StartElement) (xml.Token, error)
	// JSONValue convert XML value into JSON value.
	// Input value is the text part of a XML element.
	// Returned value is recognized by [json.Encoder].
	// This function is used in XML to JSON conversion.
	JSONValue func(string, xml.StartElement) (any, error)
	// contains filtered or unexported fields
}

RayFish is the XML JSON converter following RayFish encode-decoder. Basic conversion rules are shown in the table below.

References:

Conversion Rules:

┌=====================================┐┌=====================================┐
│              XML Input              ││            JSON Output              |
└=====================================┘└=====================================┘

| A simple element without attributes or children.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>bob</alice>                  ││ {                                   │
│                                     ││   "#name": "alice",                 │
│                                     ││   "#text": "bob",                   │
│                                     ││   "#children": []                   │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with attribute. Prefix "@" is added to the name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie="david">bob</alice>  ││ {                                   │
│                                     ││   "#name": "alice",                 │
│                                     ││   "#text": "bob",                   │
│                                     ││   "#children": [                    │
│                                     ││     {                               │
│                                     ││       "#name": "@charlie",          │
│                                     ││       "#text": "david",             │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have different name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "#name": "alice",                 │
│   <david>edgar</david>              ││   "#text": "",                      │
│ </alice>                            ││   "#children": [                    │
│                                     ││     {                               │
│                                     ││       "#name": "bob",               │
│                                     ││       "#text": "charlie",           │
│                                     ││       "#children": []               │
│                                     ││     },                              │
│                                     ││     {                               │
│                                     ││       "#name": "david",             │
│                                     ││       "#text": "edgar",             │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have the same name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "#name": "alice",                 │
│   <bob>edgar</bob>                  ││   "#text": "",                      │
│ </alice>                            ││   "#children": [                    │
│                                     ││     {                               │
│                                     ││       "#name": "bob",               │
│                                     ││       "#text": "charlie",           │
│                                     ││       "#children": []               │
│                                     ││     },                              │
│                                     ││     {                               │
│                                     ││       "#name": "bob",               │
│                                     ││       "#text": "edgar",             │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with mixed content. Text contents are joined.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   bob                               ││   "#name": "alice",                 │
│   <charlie>david</charlie>          ││   "#text": "bobedgar",              │
│   edgar                             ││   "#children": [                    │
│ </alice>                            ││     {                               │
│                                     ││       "#name": "charlie",           │
│                                     ││       "#text": "david",             │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with namespaces.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice xmlns:ns="http://abc.com/">  ││ {                                   │
│   <ns:bob>charlie</ns:bob>          ││   "#name": "alice",                 │
│ </alice>                            ││   "#text": "",                      │
│                                     ││   "#children": [                    │
│                                     ││     {                               │
│                                     ││       "#name": "@xmlns:ns",         │
│                                     ││       "#text": "http://abc.com/",   │
│                                     ││       "#children": []               │
│                                     ││     },                              │
│                                     ││     {                               │
│                                     ││       "#name": "ns:bob",            │
│                                     ││       "#text": "charlie",           │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An empty element with empty attribute.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie=""></alice>          ││ {                                   │
│                                     ││   "#name": "alice",                 │
│                                     ││   "#text": "",                      │
│                                     ││   "#children": [                    │
│                                     ││     {                               │
│                                     ││       "#name": "@charlie",          │
│                                     ││       "#text": "",                  │
│                                     ││       "#children": []               │
│                                     ││     }                               │
│                                     ││   ]                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| [RayFish.WithEmptyValue] replaces the JSON value for empty elements.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue("") -->         ││ {                                   │
│ <alice></alice>                     ││   "#name": "alice",                 │
│                                     ││   "#text": "",                      │
│                                     ││   "#children": []                   │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue(nil) -->        ││ {                                   │
│ <alice></alice>                     ││   "#name": "alice",                 │
│                                     ││   "#text": null,                    │
│                                     ││   "#children": []                   │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
Example (Jsonxml)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewRayFish(),
	}

	b, err := c.JSONtoXML([]byte(`
{
  "#name": "alice",
  "#text": "bob",
  "#children": [
    {
      "#name": "@charlie",
      "#text": "david",
      "#children": []
    }
  ]
}
	`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

<alice charlie="david">bob</alice>
Example (Xmljson)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewRayFish(),
	}

	b, err := c.XMLtoJSON([]byte(`<alice charlie="david">bob</alice>`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

{"#children":[{"#children":[],"#name":"@charlie","#text":"david"}],"#name":"alice","#text":"bob"}

func NewRayFish

func NewRayFish() *RayFish

NewRayFish returns a new instance of RayFish with default configuration.

func (*RayFish) Decode

func (r *RayFish) Decode(decoder *xml.Decoder) (any, error)

Decode decodes XML document read by the decoder into Go values.

Returned value can be:

  • map[string]any
  • []map[string]any

Decode:

func (*RayFish) Encode

func (r *RayFish) Encode(encoder *xml.Encoder, obj map[string]any) error

Encode encodes the given obj into XML document. Resulting XML is written into the encoder. See the comment on RayFish for conversion rules.

func (*RayFish) WithEmptyValue

func (r *RayFish) WithEmptyValue(v any)

WithEmptyValue replaces the value corresponding to empty element that do not have any attributes, text content and child elements. The given value is used in XML to JSON conversion. Allowed values are listed below and other will result in panic.

Allowed values are:

  • nil
  • string("")

type Simple

type Simple struct {
	// TextKey is the json key name to store text content of elements.
	// Typically "$" is used.
	// TextKey should not be empty.
	TextKey string
	// AttrPrefix is the json key name prefix for XML attributes.
	// Attribute names are stored in json with this prefix.
	// For example, XML attribute foo="bar" is converted into {"@foo": "bar"}.
	// Typically "@" is used.
	// AttrPrefix should not be empty.
	AttrPrefix string
	// NamespaceSep is the name space separator.
	// Namespace separator ":" in XML element names are converted
	// into the specified string.
	// Note that general RayFish convention discards namespace information
	// but this encode-decoder keeps them.
	// Use ":" if there is no reason to change.
	// NamespaceSep should not be empty.
	NamespaceSep string
	// TrimSpace if true, trims unicode space from xml text.
	// See the [unicode.IsSpace] for space definition.
	// This option is used in XML to JSON conversion.
	TrimSpace bool
	// PreferShort if true, use short format.
	// For XML to JSON conversion, if content has no attribute and no child elements,
	// JSON will be {"key": "value"} rather than {"key": {"$": "value"}}.
	// For JSON to XML conversion, JSON can always use {"key": "value"}
	// and {"key": {"$": "value"}} expression without this configuration.
	// This option is used in XML to JSON conversion.
	PreferShort bool

	// XMLValue convert JSON value into XML value.
	// Input value is the any type value decoded by [json.Decoder].
	// Returned value is recognized by [xml.Encoder].
	// The given [xml.StartElement] can be modified in the function.
	// This option is used in JSON to XML conversion.
	XMLValue func(any, *xml.StartElement) (xml.Token, error)
	// JSONValue convert XML value into JSON value.
	// Input value is the text part of a XML element.
	// Returned value is recognized by [json.Encoder].
	// This function is used in XML to JSON conversion.
	JSONValue func(string, xml.StartElement) (any, error)
	// contains filtered or unexported fields
}

Simple is the simple XML JSON encode-decoder. It is not an implementation of convention such as RayFish or BadgerFish. Basic conversion rules are shown in the table below.

References:

Conversion Rules:

┌=====================================┐┌=====================================┐
│              XML Input              ││            JSON Output              |
└=====================================┘└=====================================┘

| A simple element without attributes or children.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>bob</alice>                  ││ {                                   │
│                                     ││   "alice": { "$": "bob" }           │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with attribute. Prefix "@" is added to the name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie="david">bob</alice>  ││ {                                   │
│                                     ││   "alice": {                        │
│                                     ││     "$": "bob",                     │
│                                     ││     "@charlie": "david"             │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have different name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "alice": {                        │
│   <david>edgar</david>              ││     "bob": { "$": "charlie" },      │
│ </alice>                            ││     "david": { "$": "edgar" }       │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with children. Children have the same name.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   <bob>charlie</bob>                ││   "alice": {                        │
│   <bob>edgar</bob>                  ││     "bob": [                        │
│ </alice>                            ││       { "$": "charlie" },           │
│                                     ││       { "$": "edgar" }              │
│                                     ││     ]                               │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with mixed content. Text contents are joined.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>                             ││ {                                   │
│   bob                               ││   "alice": {                        │
│   <charlie>david</charlie>          ││     "$": "bobedgar",                │
│   edgar                             ││     "charlie": { "$": "david" }     │
│ </alice>                            ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An element with namespaces.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice xmlns:ns="http://abc.com/">  ││ {                                   │
│   <ns:bob>charlie</ns:bob>          ││   "alice": {                        │
│ </alice>                            ││     "@xmlns:ns": "http://abc.com/", │
│                                     ││     "ns:bob": { "$": "charlie" }    │
│                                     ││   }                                 │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| An empty element with empty attribute.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice charlie=""></alice>          ││ {                                   │
│                                     ││   "alice": { "@charlie": "" }       │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| Option [Simple.PreferShort] directory associates text value to the key.
| This option works for the element without any child elements and attributes.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <alice>bob</alice>                  ││ {                                   │
│                                     ││   "alice": "bob"                    │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘

| [Simple.WithEmptyValue] replaces the JSON value for empty elements.
| Note that the output will be different when [Simple.PreferShort] is true.
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue("") -->         ││ {                                   │
│ <alice></alice>                     ││   "alice": { "$": "" }              │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- WithEmptyValue(nil) -->        ││ {                                   │
│ <alice></alice>                     ││   "alice": {}                       │
│                                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
┌─────────────────────────────────────┐┌─────────────────────────────────────┐
│ <!-- m := map[string]any{} -->      ││ {                                   │
│ <!-- WithEmptyValue(m) -->          ││   "alice": { "$": {} }              │
│ <alice></alice>                     ││ }                                   │
└─────────────────────────────────────┘└─────────────────────────────────────┘
Example (Jsonxml)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}

	b, err := c.JSONtoXML([]byte(`{"alice":{"$":"bob","@charlie":"david"}}`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

<alice charlie="david">bob</alice>
Example (Xmljson)
package main

import (
	"fmt"

	"github.com/aileron-projects/go/zencoding/zxml"
)

func main() {
	c := zxml.JSONConverter{
		EncodeDecoder: zxml.NewSimple(),
	}

	b, err := c.XMLtoJSON([]byte(`<alice charlie="david">bob</alice>`))
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}
Output:

{"alice":{"$":"bob","@charlie":"david"}}

func NewSimple

func NewSimple() *Simple

NewSimple returns a new instance of Simple encode-decoder with default configuration.

func (*Simple) Decode

func (s *Simple) Decode(decoder *xml.Decoder) (any, error)

Decode decodes XML document read by the decoder into Go values.

Returned value can be:

  • map[string]any
  • []map[string]any

Decode:

func (*Simple) Encode

func (s *Simple) Encode(encoder *xml.Encoder, obj map[string]any) error

Encode encodes the given obj into XML document. Resulting XML is written into the encoder. See the comment on Simple for conversion rules.

func (*Simple) WithEmptyValue

func (s *Simple) WithEmptyValue(v any)

WithEmptyValue replaces the value corresponding to empty element that do not have any attributes, text content and child elements. The given value is used in XML to JSON conversion. Allowed values are listed below and others will result in panic.

Allowed values are:

  • nil
  • string("")
  • make(map[string]any,0)

type XMLError

type XMLError struct {
	Err    error
	Cause  string
	Detail string
}

XMLError reports cause and detail of an error with an inner error if any.

func (*XMLError) Error

func (e *XMLError) Error() string

func (*XMLError) Is

func (e *XMLError) Is(err error) bool

Is returns if this error is identical to the given error. The err is identical to the error when it has the type XMLError and [XMLError.Cause] field is the same.

func (*XMLError) Unwrap

func (e *XMLError) Unwrap() error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL