Documentation ¶
Overview ¶
Marshal/Unmarshal XML to/from JSON and map[string]interface{} values, and extract/modify values from maps by key or key-path, including wildcards.
mxj supplants the legacy x2j and j2x packages. The subpackage x2j-wrapper is provided to facilitate migrating from the x2j package. The x2j and j2x subpackages provide similar functionality of the old packages but are not function-name compatible with them.
Note: this library was designed for processing ad hoc anonymous messages. Bulk processing large data sets may be much more efficiently performed using the encoding/xml or encoding/json packages from Go's standard library directly.
Related Packages:
checkxml: github.com/clbanning/checkxml provides functions for validating XML data.
Notes:
2018.04.18: mv.Xml/mv.XmlIndent encodes non-map[string]interface{} map values - map[string]string, map[int]uint, etc. 2018.03.29: mv.Gob/NewMapGob support gob encoding/decoding of Maps. 2018.03.26: Added mxj/x2j-wrapper sub-package for migrating from legacy x2j package. 2017.02.22: LeafNode paths can use ".N" syntax rather than "[N]" for list member indexing. 2017.02.21: github.com/clbanning/checkxml provides functions for validating XML data. 2017.02.10: SetFieldSeparator changes field separator for args in UpdateValuesForPath, ValuesFor... methods. 2017.02.06: Support XMPP stream processing - HandleXMPPStreamTag(). 2016.11.07: Preserve name space prefix syntax in XmlSeq parser - NewMapXmlSeq(), etc. 2016.06.25: Support overriding default XML attribute prefix, "-", in Map keys - SetAttrPrefix(). 2016.05.26: Support customization of xml.Decoder by exposing CustomDecoder variable. 2016.03.19: Escape invalid chars when encoding XML attribute and element values - XMLEscapeChars(). 2016.03.02: By default decoding XML with float64 and bool value casting will not cast "NaN", "Inf", and "-Inf". To cast them to float64, first set flag with CastNanInf(true). 2016.02.22: New mv.Root(), mv.Elements(), mv.Attributes methods let you examine XML document structure. 2016.02.16: Add CoerceKeysToLower() option to handle tags with mixed capitalization. 2016.02.12: Seek for first xml.StartElement token; only return error if io.EOF is reached first (handles BOM). 2015-12-02: NewMapXmlSeq() with mv.XmlSeq() & co. will try to preserve structure of XML doc when re-encoding. 2014-08-02: AnyXml() and AnyXmlIndent() will try to marshal arbitrary values to XML.
SUMMARY
type Map map[string]interface{} Create a Map value, 'm', from any map[string]interface{} value, 'v': mv := Map(v) Unmarshal / marshal XML as a Map value, 'm': mv, err := NewMapXml(xmlValue) // unmarshal xmlValue, err := m.Xml() // marshal Unmarshal XML from an io.Reader as a Map value, 'm': mv, err := NewMapReader(xmlReader) // repeated calls, as with an os.File Reader, will process stream mv, raw, err := NewMapReaderRaw(xmlReader) // 'raw' is the raw XML that was decoded Marshal Map value, 'm', to an XML Writer (io.Writer): err := mv.XmlWriter(xmlWriter) raw, err := mv.XmlWriterRaw(xmlWriter) // 'raw' is the raw XML that was written on xmlWriter Also, for prettified output: xmlValue, err := mv.XmlIndent(prefix, indent, ...) err := mv.XmlIndentWriter(xmlWriter, prefix, indent, ...) raw, err := mv.XmlIndentWriterRaw(xmlWriter, prefix, indent, ...) Bulk process XML with error handling (note: handlers must return a boolean value): err := HandleXmlReader(xmlReader, mapHandler(Map), errHandler(error)) err := HandleXmlReaderRaw(xmlReader, mapHandler(Map, []byte), errHandler(error, []byte)) Converting XML to JSON: see Examples for NewMapXml and HandleXmlReader. There are comparable functions and methods for JSON processing. Arbitrary structure values can be decoded to / encoded from Map values: mv, err := NewMapStruct(structVal) err := mv.Struct(structPointer) To work with XML tag values, JSON or Map key values or structure field values, decode the XML, JSON or structure to a Map value, 'm', or cast a map[string]interface{} value to a Map value, 'm', then: paths := mv.PathsForKey(key) path := mv.PathForKeyShortest(key) values, err := mv.ValuesForKey(key, subkeys) values, err := mv.ValuesForPath(path, subkeys) // 'path' can be dot-notation with wildcards and indexed arrays. count, err := mv.UpdateValuesForPath(newVal, path, subkeys) Get everything at once, irrespective of path depth: leafnodes := mv.LeafNodes() leafvalues := mv.LeafValues() A new Map with whatever keys are desired can be created from the current Map and then encoded in XML or JSON. (Note: keys can use dot-notation. 'oldKey' can also use wildcards and indexed arrays.) newMap, err := mv.NewMap("oldKey_1:newKey_1", "oldKey_2:newKey_2", ..., "oldKey_N:newKey_N") newXml, err := newMap.Xml() // for example newJson, err := newMap.Json() // ditto
XML PARSING CONVENTIONS
Using NewMapXml() - Attributes are parsed to `map[string]interface{}` values by prefixing a hyphen, `-`, to the attribute label. (Unless overridden by `PrependAttrWithHyphen(false)` or `SetAttrPrefix()`.) - If the element is a simple element and has attributes, the element value is given the key `#text` for its `map[string]interface{}` representation. (See the 'atomFeedString.xml' test data, below.) - XML comments, directives, and process instructions are ignored. - If CoerceKeysToLower() has been called, then the resultant keys will be lower case. Using NewMapXmlSeq() - Attributes are parsed to `map["#attr"]map[<attr_label>]map[string]interface{}`values where the `<attr_label>` value has "#text" and "#seq" keys - the "#text" key holds the value for `<attr_label>`. - All elements, except for the root, have a "#seq" key. - Comments, directives, and process instructions are unmarshalled into the Map using the keys "#comment", "#directive", and "#procinst", respectively. (See documentation for more specifics.) - Name space syntax is preserved: - <ns:key>something</ns.key> parses to map["ns:key"]interface{}{"something"} - xmlns:ns="http://myns.com/ns" parses to map["xmlns:ns"]interface{}{"http://myns.com/ns"} Both - By default, "Nan", "Inf", and "-Inf" values are not cast to float64. If you want them to be cast, set a flag to cast them using CastNanInf(true).
XML ENCODING CONVENTIONS
- 'nil' Map values, which may represent 'null' JSON values, are encoded as "<tag/>". NOTE: the operation is not symmetric as "<tag/>" elements are decoded as 'tag:""' Map values, which, then, encode in JSON as '"tag":""' values..
- ALSO: there is no guarantee that the encoded XML doc will be the same as the decoded one. (Go randomizes the walk through map[string]interface{} values.) If you plan to re-encode the Map value to XML and want the same sequencing of elements look at NewMapXmlSeq() and m.XmlSeq() - these try to preserve the element sequencing but with added complexity when working with the Map representation.
Index ¶
- Constants
- Variables
- func AnyXml(v interface{}, tags ...string) ([]byte, error)
- func AnyXmlIndent(v interface{}, prefix, indent string, tags ...string) ([]byte, error)
- func BeautifyXml(b []byte, prefix, indent string) ([]byte, error)
- func CastNanInf(b bool)
- func CoerceKeysToLower(b ...bool)
- func CoerceKeysToSnakeCase(b ...bool)
- func HandleJsonReader(jsonReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error
- func HandleJsonReaderRaw(jsonReader io.Reader, mapHandler func(Map, []byte) bool, ...) error
- func HandleXMPPStreamTag(b ...bool)
- func HandleXmlReader(xmlReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error
- func HandleXmlReaderRaw(xmlReader io.Reader, mapHandler func(Map, []byte) bool, ...) error
- func IncludeTagSeqNum(b bool)
- func LeafUseDotNotation(b ...bool)
- func PrependAttrWithHyphen(v bool)
- func SetArraySize(size int) int
- func SetAttrPrefix(s string)
- func SetFieldSeparator(s ...string)
- func XMLEscapeChars(b bool)
- func XmlDefaultEmptyElemSyntax()
- func XmlGoEmptyElemSyntax()
- type LeafNode
- type Map
- func New() Map
- func NewMapGob(gobj []byte) (Map, error)
- func NewMapJson(jsonVal []byte) (Map, error)
- func NewMapJsonReader(jsonReader io.Reader) (Map, error)
- func NewMapJsonReaderRaw(jsonReader io.Reader) (Map, []byte, error)
- func NewMapStruct(structVal interface{}) (Map, error)
- func NewMapXml(xmlVal []byte, cast ...bool) (Map, error)
- func NewMapXmlReader(xmlReader io.Reader, cast ...bool) (Map, error)
- func NewMapXmlReaderRaw(xmlReader io.Reader, cast ...bool) (Map, []byte, error)
- func NewMapXmlSeq(xmlVal []byte, cast ...bool) (Map, error)
- func NewMapXmlSeqReader(xmlReader io.Reader, cast ...bool) (Map, error)
- func NewMapXmlSeqReaderRaw(xmlReader io.Reader, cast ...bool) (Map, []byte, error)
- func (mv Map) Attributes(path string) ([]string, error)
- func (mv Map) Copy() (Map, error)
- func (mv Map) Elements(path string) ([]string, error)
- func (mv Map) Exists(path string, subkeys ...string) bool
- func (mv Map) Gob() ([]byte, error)
- func (mv Map) Json(safeEncoding ...bool) ([]byte, error)
- func (mv Map) JsonIndent(prefix, indent string, safeEncoding ...bool) ([]byte, error)
- func (mv Map) JsonIndentWriter(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) error
- func (mv Map) JsonIndentWriterRaw(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) ([]byte, error)
- func (mv Map) JsonWriter(jsonWriter io.Writer, safeEncoding ...bool) error
- func (mv Map) JsonWriterRaw(jsonWriter io.Writer, safeEncoding ...bool) ([]byte, error)
- func (mv Map) LeafNodes(no_attr ...bool) []LeafNode
- func (mv Map) LeafPaths(no_attr ...bool) []string
- func (mv Map) LeafValues(no_attr ...bool) []interface{}
- func (mv Map) NewMap(keypairs ...string) (Map, error)
- func (mv Map) Old() map[string]interface{}
- func (mv Map) PathForKeyShortest(key string) string
- func (mv Map) PathsForKey(key string) []string
- func (mv Map) Remove(path string) error
- func (mv Map) RenameKey(path string, newName string) error
- func (mv Map) Root() (string, error)
- func (mv Map) SetValueForPath(value interface{}, path string) error
- func (mv Map) StringIndent(offset ...int) string
- func (mv Map) StringIndentNoTypeInfo(offset ...int) string
- func (mv Map) Struct(structPtr interface{}) error
- func (mv Map) UpdateValuesForPath(newVal interface{}, path string, subkeys ...string) (int, error)
- func (mv Map) ValueForPath(path string) (interface{}, error)
- func (mv Map) ValueForPathString(path string) (string, error)
- func (mv Map) ValueOrEmptyForPathString(path string) string
- func (mv Map) ValuesForKey(key string, subkeys ...string) ([]interface{}, error)
- func (mv Map) ValuesForPath(path string, subkeys ...string) ([]interface{}, error)
- func (mv Map) Xml(rootTag ...string) ([]byte, error)
- func (mv Map) XmlIndent(prefix, indent string, rootTag ...string) ([]byte, error)
- func (mv Map) XmlIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error
- func (mv Map) XmlIndentWriterRaw(xmlWriter io.Writer, prefix, indent string, rootTag ...string) ([]byte, error)
- func (mv Map) XmlSeq(rootTag ...string) ([]byte, error)
- func (mv Map) XmlSeqIndent(prefix, indent string, rootTag ...string) ([]byte, error)
- func (mv Map) XmlSeqIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error
- func (mv Map) XmlSeqIndentWriterRaw(xmlWriter io.Writer, prefix, indent string, rootTag ...string) ([]byte, error)
- func (mv Map) XmlSeqWriter(xmlWriter io.Writer, rootTag ...string) error
- func (mv Map) XmlSeqWriterRaw(xmlWriter io.Writer, rootTag ...string) ([]byte, error)
- func (mv Map) XmlWriter(xmlWriter io.Writer, rootTag ...string) error
- func (mv Map) XmlWriterRaw(xmlWriter io.Writer, rootTag ...string) ([]byte, error)
- type MapRaw
- type Maps
- func (mvs Maps) JsonFile(file string, safeEncoding ...bool) error
- func (mvs Maps) JsonFileIndent(file, prefix, indent string, safeEncoding ...bool) error
- func (mvs Maps) JsonString(safeEncoding ...bool) (string, error)
- func (mvs Maps) JsonStringIndent(prefix, indent string, safeEncoding ...bool) (string, error)
- func (mvs Maps) XmlFile(file string) error
- func (mvs Maps) XmlFileIndent(file, prefix, indent string) error
- func (mvs Maps) XmlString() (string, error)
- func (mvs Maps) XmlStringIndent(prefix, indent string) (string, error)
Examples ¶
Constants ¶
const ( Cast = true // for clarity - e.g., mxj.NewMapXml(doc, mxj.Cast) SafeEncoding = true // ditto - e.g., mv.Json(mxj.SafeEncoding) )
const (
DefaultElementTag = "element"
)
const (
DefaultRootTag = "doc"
)
const (
NoAttributes = true // suppress LeafNode values that are attributes
)
Variables ¶
var CustomDecoder *xml.Decoder
CustomDecoder can be used to specify xml.Decoder attribute values, e.g., Strict:false, to be used. By default CustomDecoder is nil. If CustomeDecoder != nil, then mxj.XmlCharsetReader variable is ignored and must be set as part of the CustomDecoder value, if needed.
Usage: mxj.CustomDecoder = &xml.Decoder{Strict:false}
var JsonUseNumber bool
Decode numericvalues as json.Number type Map values - see encoding/json#Number. NOTE: this is for decoding JSON into a Map with NewMapJson(), NewMapJsonReader(), etc.; it does not affect NewMapXml(), etc. The XML encoders mv.Xml() and mv.XmlIndent() do recognize json.Number types; a JSON object can be decoded to a Map with json.Number value types and the resulting Map can be correctly encoded into a XML object.
var NO_ROOT = NoRoot // maintain backwards compatibility
var NoRoot = errors.New("no root key")
If XmlCharsetReader != nil, it will be used to decode the XML, if required. Note: if CustomDecoder != nil, then XmlCharsetReader is ignored; set the CustomDecoder attribute instead.
import ( charset "code.google.com/p/go-charset/charset" github.com/clbanning/mxj ) ... mxj.XmlCharsetReader = charset.NewReader m, merr := mxj.NewMapXml(xmlValue)
Functions ¶
func AnyXml ¶
Encode arbitrary value as XML.
Note: unmarshaling the resultant XML may not return the original value, since tag labels may have been injected to create the XML representation of the value.
Encode an arbitrary JSON object. package main import ( "encoding/json" "fmt" "gitee.com/johng/gf/third/github.com/clbanning/mxj" ) func main() { jsondata := []byte(`[ { "somekey":"somevalue" }, "string", 3.14159265, true ]`) var i interface{} err := json.Unmarshal(jsondata, &i) if err != nil { // do something } x, err := mxj.AnyXmlIndent(i, "", " ", "mydoc") if err != nil { // do something else } fmt.Println(string(x)) } output: <mydoc> <somekey>somevalue</somekey> <element>string</element> <element>3.14159265</element> <element>true</element> </mydoc>
Alternative values for DefaultRootTag and DefaultElementTag can be set as: AnyXml( v, myRootTag, myElementTag).
func AnyXmlIndent ¶
Encode an arbitrary value as a pretty XML string. Alternative values for DefaultRootTag and DefaultElementTag can be set as: AnyXmlIndent( v, "", " ", myRootTag, myElementTag).
func BeautifyXml ¶
BeautifyXml (re)formats an XML doc similar to Map.XmlIndent().
func CastNanInf ¶
func CastNanInf(b bool)
Cast "Nan", "Inf", "-Inf" XML values to 'float64'. By default, these values will be decoded as 'string'.
func CoerceKeysToLower ¶
func CoerceKeysToLower(b ...bool)
Coerce all tag values to keys in lower case. This is useful if you've got sources with variable tag capitalization, and you want to use m.ValuesForKeys(), etc., with the key or path spec in lower case.
CoerceKeysToLower() will toggle the coercion flag true|false - on|off CoerceKeysToLower(true|false) will set the coercion flag on|off NOTE: only recognized by NewMapXml, NewMapXmlReader, and NewMapXmlReaderRaw functions as well as the associated HandleXmlReader and HandleXmlReaderRaw.
func CoerceKeysToSnakeCase ¶
func CoerceKeysToSnakeCase(b ...bool)
CoerceKeysToSnakeCase changes the default, false, to the specified value, b. Note: the attribute prefix will be a hyphen, '-', or what ever string value has been specified using SetAttrPrefix.
func HandleJsonReader ¶
func HandleJsonReader(jsonReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error
Bulk process JSON using handlers that process a Map value.
'rdr' is an io.Reader for the JSON (stream). 'mapHandler' is the Map processing handler. Return of 'false' stops io.Reader processing. 'errHandler' is the error processor. Return of 'false' stops io.Reader processing and returns the error. Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. This means that you can stop reading the file on error or after processing a particular message. To have reading and handling run concurrently, pass argument to a go routine in handler and return 'true'.
Example ¶
package main import () func main() { /* See: bulk_test.go for working example. Run "go test" in package directory then scroll back to find output. Basic logic for bulk JSON to XML processing is similar to that for bulk XML to JSON processing as outlined in the HandleXmlReader example. The test case is also a good example. */ }
Output:
func HandleJsonReaderRaw ¶
func HandleJsonReaderRaw(jsonReader io.Reader, mapHandler func(Map, []byte) bool, errHandler func(error, []byte) bool) error
Bulk process JSON using handlers that process a Map value and the raw JSON.
'rdr' is an io.Reader for the JSON (stream). 'mapHandler' is the Map and raw JSON - []byte - processor. Return of 'false' stops io.Reader processing. 'errHandler' is the error and raw JSON processor. Return of 'false' stops io.Reader processing and returns the error. Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. This means that you can stop reading the file on error or after processing a particular message. To have reading and handling run concurrently, pass argument(s) to a go routine in handler and return 'true'.
Example ¶
package main import () func main() { /* See: bulkraw_test.go for working example. Run "go test" in package directory then scroll back to find output. Basic logic for bulk JSON to XML processing is similar to that for bulk XML to JSON processing as outlined in the HandleXmlReader example. The test case is also a good example. */ }
Output:
func HandleXMPPStreamTag ¶
func HandleXMPPStreamTag(b ...bool)
HandleXMPPStreamTag causes decoder to parse XMPP <stream:stream> elements. If called with no argument, XMPP stream element handling is toggled on/off. (See xmppStream_test.go for example.)
If called with NewMapXml, NewMapXmlReader, New MapXmlReaderRaw the "stream" element will be returned as: map["stream"]interface{}{map[-<attrs>]interface{}}. If called with NewMapSeq, NewMapSeqReader, NewMapSeqReaderRaw the "stream" element will be returned as: map["stream:stream"]interface{}{map["#attr"]interface{}{map[string]interface{}}} where the "#attr" values have "#text" and "#seq" keys. (See NewMapXmlSeq.)
func HandleXmlReader ¶
func HandleXmlReader(xmlReader io.Reader, mapHandler func(Map) bool, errHandler func(error) bool) error
Bulk process XML using handlers that process a Map value.
'rdr' is an io.Reader for XML (stream) 'mapHandler' is the Map processor. Return of 'false' stops io.Reader processing. 'errHandler' is the error processor. Return of 'false' stops io.Reader processing and returns the error. Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. This means that you can stop reading the file on error or after processing a particular message. To have reading and handling run concurrently, pass argument to a go routine in handler and return 'true'.
Example ¶
package main import () func main() { /* Bulk processing XML to JSON seems to be a common requirement. See: bulk_test.go for working example. Run "go test" in package directory then scroll back to find output. The logic is as follows. // need somewhere to write the JSON. var jsonWriter io.Writer // probably want to log any errors in reading the XML stream var xmlErrLogger io.Writer // func to handle Map value from XML Reader func maphandler(m mxj.Map) bool { // marshal Map as JSON jsonVal, err := m.Json() if err != nil { // log error return false // stops further processing of XML Reader } // write JSON somewhere _, err = jsonWriter.Write(jsonVal) if err != nil { // log error return false // stops further processing of XML Reader } // continue - get next XML from Reader return true } // func to handle error from unmarshaling XML Reader func errhandler(errVal error) bool { // log error somewhere _, err := xmlErrLogger.Write([]byte(errVal.Error())) if err != nil { // log error return false // stops further processing of XML Reader } // continue processing return true } // func that starts bulk processing of the XML ... // set up io.Reader for XML data - perhaps an os.File ... err := mxj.HandleXmlReader(xmlReader, maphandler, errhandler) if err != nil { // handle error } ... */ }
Output:
func HandleXmlReaderRaw ¶
func HandleXmlReaderRaw(xmlReader io.Reader, mapHandler func(Map, []byte) bool, errHandler func(error, []byte) bool) error
Bulk process XML using handlers that process a Map value and the raw XML.
'rdr' is an io.Reader for XML (stream) 'mapHandler' is the Map and raw XML - []byte - processor. Return of 'false' stops io.Reader processing. 'errHandler' is the error and raw XML processor. Return of 'false' stops io.Reader processing and returns the error. Note: mapHandler() and errHandler() calls are blocking, so reading and processing of messages is serialized. This means that you can stop reading the file on error or after processing a particular message. To have reading and handling run concurrently, pass argument(s) to a go routine in handler and return 'true'. See NewMapXmlReaderRaw for comment on performance associated with retrieving raw XML from a Reader.
Example ¶
package main import () func main() { /* See: bulkraw_test.go for working example. Run "go test" in package directory then scroll back to find output. Basic logic for bulk XML to JSON processing is in HandleXmlReader example; the only major difference is in handler function signatures so they are passed the raw XML. (Read documentation on NewXmlReader regarding performance.) */ }
Output:
func IncludeTagSeqNum ¶
func IncludeTagSeqNum(b bool)
IncludeTagSeqNum - include a "_seq":N key:value pair with each inner tag, denoting its position when parsed. This is of limited usefulness, since list values cannot be tagged with "_seq" without changing their depth in the Map. So THIS SHOULD BE USED WITH CAUTION - see the test cases. Here's a sample of what you get.
<Obj c="la" x="dee" h="da"> <IntObj id="3"/> <IntObj1 id="1"/> <IntObj id="2"/> <StrObj>hello</StrObj> </Obj> parses as: { Obj:{ "-c":"la", "-h":"da", "-x":"dee", "intObj":[ { "-id"="3", "_seq":"0" // if mxj.Cast is passed, then: "_seq":0 }, { "-id"="2", "_seq":"2" }], "intObj1":{ "-id":"1", "_seq":"1" }, "StrObj":{ "#text":"hello", // simple element value gets "#text" tag "_seq":"3" } } }
func LeafUseDotNotation ¶
func LeafUseDotNotation(b ...bool)
LeafUseDotNotation sets a flag that list members in LeafNode paths should be identified using ".N" syntax rather than the default "[N]" syntax. Calling LeafUseDotNotation with no arguments toggles the flag on/off; otherwise, the argument sets the flag value 'true'/'false'.
func PrependAttrWithHyphen ¶
func PrependAttrWithHyphen(v bool)
PrependAttrWithHyphen. Prepend attribute tags with a hyphen. Default is 'true'. (Not applicable to NewMapXmlSeq(), mv.XmlSeq(), etc.)
Note: If 'false', unmarshaling and marshaling is not symmetric. Attributes will be marshal'd as <attr_tag>attr</attr_tag> and may be part of a list.
func SetArraySize ¶
Adjust the buffers for expected number of values to return from ValuesForKey() and ValuesForPath(). This can have the effect of significantly reducing memory allocation-copy functions for large data sets. Returns the initial buffer size.
func SetAttrPrefix ¶
func SetAttrPrefix(s string)
SetAttrPrefix changes the default, "-", to the specified value, s. SetAttrPrefix("") is the same as PrependAttrWithHyphen(false). (Not applicable for NewMapXmlSeq(), mv.XmlSeq(), etc.)
func SetFieldSeparator ¶
func SetFieldSeparator(s ...string)
SetFieldSeparator changes the default field separator, ":", for the newVal argument in mv.UpdateValuesForPath and the optional 'subkey' arguments in mv.ValuesForKey and mv.ValuesForPath.
E.g., if the newVal value is "http://blah/blah", setting the field separator to "|" will allow the newVal specification, "<key>|http://blah/blah" to parse properly. If called with no argument or an empty string value, the field separator is set to the default, ":".
func XMLEscapeChars ¶
func XMLEscapeChars(b 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 '&amp;'.
The values are: " " ' ' < < > > & &
func XmlDefaultEmptyElemSyntax ¶
func XmlDefaultEmptyElemSyntax()
XmlDefaultEmptyElemSyntax() - <tag .../> rather than <tag ...></tag>. Return XML encoding for empty elements to the default package setting. Reverses effect of XmlGoEmptyElemSyntax().
func XmlGoEmptyElemSyntax ¶
func XmlGoEmptyElemSyntax()
XmlGoEmptyElemSyntax() - <tag ...></tag> rather than <tag .../>.
Go's encoding/xml package marshals empty XML elements as <tag ...></tag>. By default this package encodes empty elements as <tag .../>. If you're marshaling Map values that include structures (which are passed to xml.Marshal for encoding), this will let you conform to the standard package.
Types ¶
type LeafNode ¶
type LeafNode struct { Path string // a dot-notation representation of the path with array subscripting Value interface{} // the value at the path termination }
LeafNode - a terminal path value in a Map. For XML Map values it represents an attribute or simple element value - of type string unless Map was created using Cast flag. For JSON Map values it represents a string, numeric, boolean, or null value.
type Map ¶
type Map map[string]interface{}
func NewMapGob ¶
NewMapGob returns a Map value for a gob object that has been encoded from a map[string]interface{} (or compatible type) value. It is intended to provide symmetric handling of Maps that have been encoded using mv.Gob.
func NewMapJson ¶
Just a wrapper on json.Unmarshal
Converting JSON to XML is a simple as: ... mapVal, merr := mxj.NewMapJson(jsonVal) if merr != nil { // handle error } xmlVal, xerr := mapVal.Xml() if xerr != nil { // handle error }
NOTE: as a special case, passing a list, e.g., [{"some-null-value":"", "a-non-null-value":"bar"}], will be interpreted as having the root key 'object' prepended - {"object":[ ... ]} - to unmarshal to a Map. See mxj/j2x/j2x_test.go.
func NewMapJsonReader ¶
Retrieve a Map value from an io.Reader.
NOTE: The raw JSON off the reader is buffered to []byte using a ByteReader. If the io.Reader is an os.File, there may be significant performance impact. If the io.Reader is wrapping a []byte value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal a JSON object.
func NewMapJsonReaderRaw ¶
Retrieve a Map value and raw JSON - []byte - from an io.Reader.
NOTE: The raw JSON off the reader is buffered to []byte using a ByteReader. If the io.Reader is an os.File, there may be significant performance impact. If the io.Reader is wrapping a []byte value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal a JSON object and retrieve the raw JSON in a single call.
func NewMapStruct ¶
DEPRECATED - import github.com/fatih/structs and cast result of structs.Map to mxj.Map.
import "gitee.com/johng/gf/third/github.com/fatih/structs" ... sm, err := structs.Map(<some struct>) if err != nil { // handle error } m := mxj.Map(sm)
Alernatively uncomment the old source and import in struct.go.
Example ¶
package main import ( "fmt" "gitee.com/johng/gf/third/github.com/clbanning/mxj" ) func main() { type str struct { IntVal int `structs:"int"` StrVal string `structs:"str"` FloatVal float64 `structs:"float"` BoolVal bool `structs:"bool"` private string } strVal := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"} mapVal, merr := mxj.NewMapStruct(strVal) if merr != nil { // handle error } fmt.Printf("strVal: %#v\n", strVal) fmt.Printf("mapVal: %#v\n", mapVal) // Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name. // NoFail output: // strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} // mapVal: mxj.Map{"float":3.14159, "bool":true, "int":4, "str":"now's the time"} }
Output:
func NewMapXml ¶
NewMapXml - convert a XML doc into a Map (This is analogous to unmarshalling a JSON string to map[string]interface{} using json.Unmarshal().)
If the optional argument 'cast' is 'true', then values will be converted to boolean or float64 if possible. Converting XML to JSON is a simple as: ... mapVal, merr := mxj.NewMapXml(xmlVal) if merr != nil { // handle error } jsonVal, jerr := mapVal.Json() if jerr != nil { // handle error } NOTES: 1. The 'xmlVal' will be parsed looking for an xml.StartElement, so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 2. If CoerceKeysToLower() has been called, then all key values will be lower case. 3. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
func NewMapXmlReader ¶
Get next XML doc from an io.Reader as a Map value. Returns Map value.
NOTES: 1. The 'xmlReader' will be parsed looking for an xml.StartElement, so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 2. If CoerceKeysToLower() has been called, then all key values will be lower case. 3. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
func NewMapXmlReaderRaw ¶
Get next XML doc from an io.Reader as a Map value. Returns Map value and slice with the raw XML.
NOTES: 1. Due to the implementation of xml.Decoder, the raw XML off the reader is buffered to []byte using a ByteReader. If the io.Reader is an os.File, there may be significant performance impact. See the examples - getmetrics1.go through getmetrics4.go - for comparative use cases on a large data set. If the io.Reader is wrapping a []byte value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal a XML doc and retrieve the raw XML in a single call. 2. The 'raw' return value may be larger than the XML text value. 3. The 'xmlReader' will be parsed looking for an xml.StartElement, so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 4. If CoerceKeysToLower() has been called, then all key values will be lower case. 5. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
func NewMapXmlSeq ¶
This is only useful if you want to re-encode the Map as XML using mv.XmlSeq(), etc., to preserve the original structure. The xml.Decoder.RawToken method is used to parse the XML, so there is no checking for appropriate xml.EndElement values; thus, it is assumed that the XML is valid.
NewMapXmlSeq - convert a XML doc into a Map with elements id'd with decoding sequence int - #seq. If the optional argument 'cast' is 'true', then values will be converted to boolean or float64 if possible. NOTE: "#seq" key/value pairs are removed on encoding with mv.XmlSeq() / mv.XmlSeqIndent().
attributes are a map - map["#attr"]map["attr_key"]map[string]interface{}{"#text":<aval>, "#seq":<num>}
all simple elements are decoded as map["#text"]interface{} with a "#seq" k:v pair, as well.
lists always decode as map["list_tag"][]map[string]interface{} where the array elements are maps that include a "#seq" k:v pair based on sequence they are decoded. Thus, XML like: <doc> <ltag>value 1</ltag> <newtag>value 2</newtag> <ltag>value 3</ltag> </doc> is decoded as: doc : ltag :[[]interface{}] [item: 0] #seq :[int] 0 #text :[string] value 1 [item: 1] #seq :[int] 2 #text :[string] value 3 newtag : #seq :[int] 1 #text :[string] value 2 It will encode in proper sequence even though the Map representation merges all "ltag" elements in an array.
comments - "<!--comment-->" - are decoded as map["#comment"]map["#text"]"cmnt_text" with a "#seq" k:v pair.
directives - "<!text>" - are decoded as map["#directive"]map[#text"]"directive_text" with a "#seq" k:v pair.
process instructions - "<?instr?>" - are decoded as map["#procinst"]interface{} where the #procinst value is of map[string]interface{} type with the following keys: #target, #inst, and #seq.
comments, directives, and procinsts that are NOT part of a document with a root key will be returned as map[string]interface{} and the error value 'NoRoot'.
note: "<![CDATA[" syntax is lost in xml.Decode parser - and is not handled here, either. and: "\r\n" is converted to "\n"
NOTES: 1. The 'xmlVal' will be parsed looking for an xml.StartElement, xml.Comment, etc., so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 2. CoerceKeysToLower() is NOT recognized, since the intent here is to eventually call m.XmlSeq() to re-encode the message in its original structure. 3. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
NAME SPACES: 1. Keys in the Map value that are parsed from a <name space prefix>:<local name> tag preserve the "<prefix>:" notation rather than stripping it as with NewMapXml(). 2. Attribute keys for name space prefix declarations preserve "xmlns:<prefix>" notation.
func NewMapXmlSeqReader ¶
This is only useful if you want to re-encode the Map as XML using mv.XmlSeq(), etc., to preserve the original structure.
Get next XML doc from an io.Reader as a Map value. Returns Map value.
NOTES: 1. The 'xmlReader' will be parsed looking for an xml.StartElement, xml.Comment, etc., so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 2. CoerceKeysToLower() is NOT recognized, since the intent here is to eventually call m.XmlSeq() to re-encode the message in its original structure. 3. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
func NewMapXmlSeqReaderRaw ¶
This is only useful if you want to re-encode the Map as XML using mv.XmlSeq(), etc., to preserve the original structure.
Get next XML doc from an io.Reader as a Map value. Returns Map value and slice with the raw XML.
NOTES: 1. Due to the implementation of xml.Decoder, the raw XML off the reader is buffered to []byte using a ByteReader. If the io.Reader is an os.File, there may be significant performance impact. See the examples - getmetrics1.go through getmetrics4.go - for comparative use cases on a large data set. If the io.Reader is wrapping a []byte value in-memory, however, such as http.Request.Body you CAN use it to efficiently unmarshal a XML doc and retrieve the raw XML in a single call. 2. The 'raw' return value may be larger than the XML text value. 3. The 'xmlReader' will be parsed looking for an xml.StartElement, xml.Comment, etc., so BOM and other extraneous xml.CharData will be ignored unless io.EOF is reached first. 4. CoerceKeysToLower() is NOT recognized, since the intent here is to eventually call m.XmlSeq() to re-encode the message in its original structure. 5. If CoerceKeysToSnakeCase() has been called, then all key values will be converted to snake case.
func (Map) Attributes ¶
If the path is an element with attributes, return a list of the attribute keys. (The list is alphabeticly sorted.) NOTE: Map keys that are not prefixed with '-', a hyphen, are not treated as attributes; see m.Elements(path). Also, if the attribute prefix is "" - SetAttrPrefix("") or PrependAttrWithHyphen(false) - then there are no identifiable attributes.
func (Map) Copy ¶
Return a copy of mv as a newly allocated Map. If the Map only contains string, numeric, map[string]interface{}, and []interface{} values, then it can be thought of as a "deep copy." Copying a structure (or structure reference) value is subject to the noted restrictions.
NOTE: If 'mv' includes structure values with, possibly, JSON encoding tags then only public fields of the structure are in the new Map - and with keys that conform to any encoding tag instructions. The structure itself will be represented as a map[string]interface{} value.
Example ¶
package main import ( "fmt" "gitee.com/johng/gf/third/github.com/clbanning/mxj" ) func main() { // Hand-crafted Map values that include structures do NOT Copy() as expected, // since to simulate a deep copy the original Map value is JSON encoded then decoded. type str struct { IntVal int `json:"int"` StrVal string `json:"str"` FloatVal float64 `json:"float"` BoolVal bool `json:"bool"` private string } s := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"} m := make(map[string]interface{}, 0) m["struct"] = interface{}(s) m["struct_ptr"] = interface{}(&s) m["misc"] = interface{}(`Now is the time`) mv := mxj.Map(m) cp, _ := mv.Copy() fmt.Printf("mv:\n%s\n", mv.StringIndent(2)) fmt.Printf("cp:\n%s\n", cp.StringIndent(2)) // NoFail output: // mv: // misc : [string] Now is the time // struct : [mxj_test.str] {IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue} // struct_ptr : [*mxj_test.str] &{IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue} // cp: // misc : [string] Now is the time // struct : // bool : [bool] true // float : [float64] 3.14159 // int : [float64] 4 // str : [string] now's the time // struct_ptr : // bool : [bool] true // float : [float64] 3.14159 // int : [float64] 4 // str : [string] now's the time // }
Output:
func (Map) Elements ¶
If the path is an element with sub-elements, return a list of the sub-element keys. (The list is alphabeticly sorted.) NOTE: Map keys that are prefixed with '-', a hyphen, are considered attributes; see m.Attributes(path).
func (Map) Json ¶
Just a wrapper on json.Marshal. If option safeEncoding is'true' then safe encoding of '<', '>' and '&' is preserved. (see encoding/json#Marshal, encoding/json#Encode)
func (Map) JsonIndent ¶
Just a wrapper on json.MarshalIndent. If option safeEncoding is'true' then safe encoding of '<' , '>' and '&' is preserved. (see encoding/json#Marshal, encoding/json#Encode)
func (Map) JsonIndentWriter ¶
func (mv Map) JsonIndentWriter(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) error
Writes the Map as pretty JSON on the Writer. If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved.
func (Map) JsonIndentWriterRaw ¶
func (mv Map) JsonIndentWriterRaw(jsonWriter io.Writer, prefix, indent string, safeEncoding ...bool) ([]byte, error)
Writes the Map as pretty JSON on the Writer. []byte is the raw JSON that was written. If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved.
func (Map) JsonWriter ¶
Writes the Map as JSON on the Writer. If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved.
func (Map) JsonWriterRaw ¶
Writes the Map as JSON on the Writer. []byte is the raw JSON that was written. If 'safeEncoding' is 'true', then "safe" encoding of '<', '>' and '&' is preserved.
func (Map) LeafNodes ¶
LeafNodes - returns an array of all LeafNode values for the Map. The option no_attr argument suppresses attribute values (keys with prepended hyphen, '-') as well as the "#text" key for the associated simple element value.
PrependAttrWithHypen(false) will result in attributes having .attr-name as terminal node in 'path' while the path for the element value, itself, will be the base path w/o "#text".
LeafUseDotNotation(true) causes list members to be identified using ".N" syntax rather than "[N]" syntax.
func (Map) LeafValues ¶
LeafValues - all terminal values in the Map.
func (Map) NewMap ¶
(Map)NewMap - create a new Map from data in the current Map.
'keypairs' are key mappings "oldKey:newKey" and specify that the current value of 'oldKey' should be the value for 'newKey' in the returned Map. - 'oldKey' supports dot-notation as described for (Map)ValuesForPath() - 'newKey' supports dot-notation but with no wildcards, '*', or indexed arrays - "oldKey" is shorthand for the keypair value "oldKey:oldKey" - "oldKey:" and ":newKey" are invalid keypair values - if 'oldKey' does not exist in the current Map, it is not written to the new Map. "null" is not supported unless it is the current Map. - see newmap_test.go for several syntax examples NOTE: mv.NewMap() == mxj.New().
func (Map) PathForKeyShortest ¶
Extract the shortest path from all possible paths - from PathsForKey() - in Map, 'mv'.. Paths are strings using dot-notation.
func (Map) PathsForKey ¶
Get all paths through Map, 'mv', (in dot-notation) that terminate with the specified key. Results can be used with ValuesForPath.
func (Map) RenameKey ¶
RenameKey renames a key in a Map. It works only for nested maps. It doesn't work for cases when it buried in a list.
func (Map) Root ¶
Return the root element of the Map. If there is not a single key in Map, then an error is returned.
func (Map) SetValueForPath ¶
Sets the value for the path
func (Map) StringIndentNoTypeInfo ¶
Pretty print a Map without the value type information - just key:value entries.
func (Map) Struct ¶
Marshal a map[string]interface{} into a structure referenced by 'structPtr'. Error returned if argument is not a pointer or if json.Unmarshal returns an error.
json.Unmarshal structure encoding rules are followed to encode public structure fields.
Example ¶
package main import ( "fmt" "gitee.com/johng/gf/third/github.com/clbanning/mxj" ) func main() { type str struct { IntVal int `json:"int"` StrVal string `json:"str"` FloatVal float64 `json:"float"` BoolVal bool `json:"bool"` private string } mapVal := mxj.Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true, "private": "Somewhere over the rainbow"} var strVal str mverr := mapVal.Struct(&strVal) if mverr != nil { // handle error } fmt.Printf("mapVal: %#v\n", mapVal) fmt.Printf("strVal: %#v\n", strVal) // Note: example output is conformed to pass "go test". "mxj_test" is example_test.go package name. }
Output: mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true, "private":"Somewhere over the rainbow"} strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""}
func (Map) UpdateValuesForPath ¶
Update value based on path and possible sub-key values. A count of the number of values changed and any error are returned. If the count == 0, then no path (and subkeys) matched.
'newVal' can be a Map or map[string]interface{} value with a single 'key' that is the key to be modified or a string value "key:value[:type]" where type is "bool" or "num" to cast the value. 'path' is dot-notation list of keys to traverse; last key in path can be newVal key NOTE: 'path' spec does not currently support indexed array references. 'subkeys' are "key:value[:type]" entries that must match for path node The subkey can be wildcarded - "key:*" - to require that it's there with some value. If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an exclusion critera - e.g., "!author:William T. Gaddis". NOTES: 1. Simple elements with attributes need a path terminated as ".#text" to modify the actual value. 2. Values in Maps created using NewMapXmlSeq are map[string]interface{} values with a "#text" key. 3. If values in 'newVal' or 'subkeys' args contain ":", use SetFieldSeparator to an unused symbol, perhaps "|".
Example ¶
package main import () func main() { /* var biblioDoc = []byte(` <biblio> <author> <name>William Gaddis</name> <books> <book> <title>The Recognitions</title> <date>1955</date> <review>A novel that changed the face of American literature.</review> </book> <book> <title>JR</title> <date>1975</date> <review>Winner of National Book Award for Fiction.</review> </book> </books> </author> </biblio>`) ... m, merr := mxj.NewMapXml(biblioDoc) if merr != nil { // handle error } // change 'review' for a book count, err := m.UpdateValuesForPath("review:National Book Award winner." "*.*.*.*", "title:JR") if err != nil { // handle error } ... // change 'date' value from string type to float64 type // Note: the following is equivalent to m, merr := NewMapXml(biblioDoc, mxj.Cast). path := m.PathForKeyShortest("date") v, err := m.ValuesForPath(path) if err != nil { // handle error } var total int for _, vv := range v { oldVal := "date:" + vv.(string) newVal := "date:" + vv.(string) + ":num" n, err := m.UpdateValuesForPath(newVal, path, oldVal) if err != nil { // handle error } total += n } ... */ }
Output:
func (Map) ValueForPath ¶
Returns the first found value for the path.
func (Map) ValueForPathString ¶
Returns the first found value for the path as a string.
func (Map) ValueOrEmptyForPathString ¶
Returns the first found value for the path as a string. If the path is not found then it returns an empty string.
func (Map) ValuesForKey ¶
Return all values in Map, 'mv', associated with a 'key'. If len(returned_values) == 0, then no match. On error, the returned array is 'nil'. NOTE: 'key' can be wildcard, "*".
'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list. - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them. - For attributes prefix the label with a hyphen, '-', e.g., "-seq:3". - If the 'key' refers to a list, then "key:value" could select a list member of the list. - The subkey can be wildcarded - "key:*" - to require that it's there with some value. - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an exclusion critera - e.g., "!author:William T. Gaddis". - If val contains ":" symbol, use SetFieldSeparator to a unused symbol, perhaps "|".
func (Map) ValuesForPath ¶
Retrieve all values for a path from the Map. If len(returned_values) == 0, then no match. On error, the returned array is 'nil'.
'path' is a dot-separated path of key values. - If a node in the path is '*', then everything beyond is walked. - 'path' can contain indexed array references, such as, "*.data[1]" and "msgs[2].data[0].field" - even "*[2].*[0].field". 'subkeys' (optional) are "key:val[:type]" strings representing attributes or elements in a list. - By default 'val' is of type string. "key:val:bool" and "key:val:float" to coerce them. - For attributes prefix the label with a hyphen, '-', e.g., "-seq:3". - If the 'path' refers to a list, then "tag:value" would return member of the list. - The subkey can be wildcarded - "key:*" - to require that it's there with some value. - If a subkey is preceeded with the '!' character, the key:value[:type] entry is treated as an exclusion critera - e.g., "!author:William T. Gaddis". - If val contains ":" symbol, use SetFieldSeparator to a unused symbol, perhaps "|".
Example ¶
package main import ( "bytes" "fmt" "gitee.com/johng/gf/third/github.com/clbanning/mxj" "io" ) func main() { // a snippet from examples/gonuts1.go // How to compensate for irregular tag labels in data. // Need to extract from an XML stream the values for "netid" and "idnet". // Solution: use a wildcard path "data.*" to anonymize the "netid" and "idnet" tags. var msg1 = []byte(` <?xml version="1.0" encoding="UTF-8"?> <data> <netid> <disable>no</disable> <text1>default:text</text1> <word1>default:word</word1> </netid> </data> `) var msg2 = []byte(` <?xml version="1.0" encoding="UTF-8"?> <data> <idnet> <disable>yes</disable> <text1>default:text</text1> <word1>default:word</word1> </idnet> </data> `) // let's create a message stream buf := new(bytes.Buffer) // load a couple of messages into it _, _ = buf.Write(msg1) _, _ = buf.Write(msg2) n := 0 for { n++ // Read the stream as Map values - quit on io.EOF. // Get the raw XML as well as the Map value. m, merr := mxj.NewMapXmlReader(buf) if merr != nil && merr != io.EOF { // handle error - for demo we just print it and continue fmt.Printf("msg: %d - merr: %s\n", n, merr.Error()) continue } else if merr == io.EOF { break } // get the values for "netid" or "idnet" key using path == "data.*" values, _ := m.ValuesForPath("data.*") fmt.Println("\nmsg:", n, "> path == data.* - got array of values, len:", len(values)) for i, val := range values { fmt.Println("ValuesForPath result array member -", i, ":", val) fmt.Println(" k:v pairs for array member:", i) for key, val := range val.(map[string]interface{}) { // You'd probably want to process the value, as appropriate. // Here we just print it out. fmt.Println("\t\t", key, ":", val) } } } // NoFail output: // msg: 1 > path == data.* - got array of values, len: 1 // ValuesForPath result array member - 0 : map[disable:no text1:default:text word1:default:word] // k:v pairs for array member: 0 // disable : no // text1 : default:text // word1 : default:word // // msg: 2 > path == data.* - got array of values, len: 1 // ValuesForPath result array member - 0 : map[disable:yes text1:default:text word1:default:word] // k:v pairs for array member: 0 // disable : yes // text1 : default:text // word1 : default:word }
Output:
func (Map) Xml ¶
Encode a Map as XML. The companion of NewMapXml(). The following rules apply.
- The key label "#text" is treated as the value for a simple element with attributes.
- Map keys that begin with a hyphen, '-', are interpreted as attributes. It is an error if the attribute doesn't have a []byte, string, number, or boolean value.
- Map value type encoding: > string, bool, float64, int, int32, int64, float32: per "%v" formating > []bool, []uint8: by casting to string > structures, etc.: handed to xml.Marshal() - if there is an error, the element value is "UNKNOWN"
- Elements with only attribute values or are null are terminated using "/>".
- If len(mv) == 1 and no rootTag is provided, then the map key is used as the root tag, possible. Thus, `{ "key":"value" }` encodes as "<key>value</key>".
- To encode empty elements in a syntax consistent with encoding/xml call UseGoXmlEmptyElementSyntax().
The attributes tag=value pairs are alphabetized by "tag". Also, when encoding map[string]interface{} values - complex elements, etc. - the key:value pairs are alphabetized by key so the resulting tags will appear sorted.
func (Map) XmlIndent ¶
Encode a map[string]interface{} as a pretty XML string. See Xml for encoding rules.
func (Map) XmlIndentWriter ¶
Writes the Map as pretty XML on the Writer. See Xml() for encoding rules.
func (Map) XmlIndentWriterRaw ¶
func (mv Map) XmlIndentWriterRaw(xmlWriter io.Writer, prefix, indent string, rootTag ...string) ([]byte, error)
Writes the Map as pretty XML on the Writer. []byte is the raw XML that was written. See Xml() for encoding rules.
func (Map) XmlSeq ¶
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Encode a Map as XML with elements sorted on #seq. The companion of NewMapXmlSeq(). The following rules apply.
- The key label "#text" is treated as the value for a simple element with attributes.
- The "#seq" key is used to seqence the subelements or attributes but is ignored for writing.
- The "#attr" map key identifies the map of attribute map[string]interface{} values with "#text" key.
- The "#comment" map key identifies a comment in the value "#text" map entry - <!--comment-->.
- The "#directive" map key identifies a directive in the value "#text" map entry - <!directive>.
- The "#procinst" map key identifies a process instruction in the value "#target" and "#inst" map entries - <?target inst?>.
- Value type encoding: > string, bool, float64, int, int32, int64, float32: per "%v" formating > []bool, []uint8: by casting to string > structures, etc.: handed to xml.Marshal() - if there is an error, the element value is "UNKNOWN"
- Elements with only attribute values or are null are terminated using "/>" unless XmlGoEmptyElemSystax() called.
- If len(mv) == 1 and no rootTag is provided, then the map key is used as the root tag, possible. Thus, `{ "key":"value" }` encodes as "<key>value</key>".
func (Map) XmlSeqIndent ¶
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Encode a map[string]interface{} as a pretty XML string. See mv.XmlSeq() for encoding rules.
func (Map) XmlSeqIndentWriter ¶
func (mv Map) XmlSeqIndentWriter(xmlWriter io.Writer, prefix, indent string, rootTag ...string) error
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Writes the Map as pretty XML on the Writer. See Xml() for encoding rules.
func (Map) XmlSeqIndentWriterRaw ¶
func (mv Map) XmlSeqIndentWriterRaw(xmlWriter io.Writer, prefix, indent string, rootTag ...string) ([]byte, error)
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Writes the Map as pretty XML on the Writer. []byte is the raw XML that was written. See XmlSeq() for encoding rules.
func (Map) XmlSeqWriter ¶
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Writes the Map as XML on the Writer. See XmlSeq() for encoding rules.
func (Map) XmlSeqWriterRaw ¶
This should ONLY be used on Map values that were decoded using NewMapXmlSeq() & co.
Writes the Map as XML on the Writer. []byte is the raw XML that was written. See XmlSeq() for encoding rules.
type MapRaw ¶
func NewMapsFromJsonFileRaw ¶
ReadMapsFromJsonFileRaw - creates an array of MapRaw from a file of JSON values.
func NewMapsFromXmlFileRaw ¶
NewMapsFromXmlFileRaw - creates an array of MapRaw from a file of XML values. NOTE: the slice with the raw XML is clean with no extra capacity - unlike NewMapXmlReaderRaw(). It is slow at parsing a file from disk and is intended for relatively small utility files.
type Maps ¶
type Maps []Map
func NewMapsFromJsonFile ¶
NewMapsFromXmlFile - creates an array from a file of JSON values.
func NewMapsFromXmlFile ¶
NewMapsFromXmlFile - creates an array from a file of XML values.
func (Maps) JsonFile ¶
JsonFile - write Maps to named file as JSON Note: the file will be created, if necessary; if it exists it will be truncated. If you need to append to a file, open it and use JsonWriter method.
func (Maps) JsonFileIndent ¶
JsonFileIndent - write Maps to named file as pretty JSON Note: the file will be created, if necessary; if it exists it will be truncated. If you need to append to a file, open it and use JsonIndentWriter method.
func (Maps) JsonString ¶
JsonString - analogous to mv.Json()
func (Maps) JsonStringIndent ¶
JsonStringIndent - analogous to mv.JsonIndent()
func (Maps) XmlFile ¶
XmlFile - write Maps to named file as XML Note: the file will be created, if necessary; if it exists it will be truncated. If you need to append to a file, open it and use XmlWriter method.
func (Maps) XmlFileIndent ¶
XmlFileIndent - write Maps to named file as pretty XML Note: the file will be created,if necessary; if it exists it will be truncated. If you need to append to a file, open it and use XmlIndentWriter method.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
j2x.go - For (mostly) backwards compatibility with legacy j2x package.
|
j2x.go - For (mostly) backwards compatibility with legacy j2x package. |
x2j - For (mostly) backwards compatibility with legacy x2j package.
|
x2j - For (mostly) backwards compatibility with legacy x2j package. |
Unmarshal dynamic / arbitrary XML docs and extract values (using wildcards, if necessary).
|
Unmarshal dynamic / arbitrary XML docs and extract values (using wildcards, if necessary). |