Skip to content

nytlabs/mxj

 
 

Repository files navigation

Marshal/Unmarshal XML to/from JSON and map[string]interface{} values, and extract values from maps by key or key-path, including wildcards.  

**This fork of mxj doesn't prepend attributes with hyphens. **

mxj supplants the legacy x2j and j2x packages. If you want the old syntax, just uncomment the content of x2j.go or j2x.go, which are included as part of this package.

SUMMARY

   type Map map[string]interface{}

   Create a Map value, 'm', from any map[string]interface{} value, 'v':
      m := Map(v)

   Unmarshal / marshal XML as a Map value, 'm':
      m, err := NewMapXml(xmlValue) // unmarshal
      xmlValue, err := m.Xml()      // marshal

   Unmarshal XML from an io.Reader as a Map value, 'm':
      m, err := NewMapReader(xmlReader)         // repeated calls, as with an os.File Reader, will process stream
      m, raw, err := NewMapReaderRaw(xmlReader) // 'raw' points to the raw XML that was decoded

   Marshal Map value, 'm', to an XML Writer (io.Writer):
      err := m.XmlWriter(xmlWriter)         // or: m.XmlIndentWriter(xmlWriter, prefix, indent)
      err, raw := m.XmlWriterRaw(xmlWriter) // 'raw' points to the raw XML that was written on xmlWriter

   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:
      m, err := NewMapStruct(structVal)
      err := m.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 := m.PathsForKey(key)
      path := m.PathForKeyShortest(key)
      values, err := m.ValuesForKey(key, subkeys)
      values, err := m.ValuesForPath(path, subkeys)
      count, err := m.UpdateValuesForPath(newVal, path, subkeys)

   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.)
      newMap := m.NewMap("oldKey_1:newKey_1", "oldKey_2:newKey_2", ..., "oldKey_N:newKey_N")
      newXml := newMap.Xml()   // for example
      newJson := newMap.Json() // ditto

USAGE

The package is fairly well self-documented with examples. (http://godoc.org/github.com/clbanning/mxj)

Also, the subdirectory "examples" contains a wide range of examples, several taken from golang-nuts discussions.

XML PARSING CONVENTIONS

   - Attributes are parsed to map[string]interface{} values by prefixing a hyphen, '-',
     to the attribute label.
   - 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.)

RUNNING "GO TEST"

Because there are no guarantees on the sequence map elements are retrieved, the tests have been 
written for visual verification in most cases.  One advantage is that you can easily use the 
output from running "go test" as examples of calling the various functions and methods.

MOTIVATION

I make extensive use of JSON for messaging and typically unmarshal the messages into
map[string]interface{} variables.  This is easily done using json.Unmarshal from the
standard Go libraries.  Unfortunately, many legacy solutions use structured
XML messages; in those environments the applications would have to be refitted to
interoperate with my components.

The better solution is to just provide an alternative HTTP handler that receives
XML doc messages and parses it into a map[string]interface{} variable and then reuse
all the JSON-based code.  The Go xml.Unmarshal() function does not provide the same
option of unmarshaling XML messages into map[string]interface{} variables. So I wrote
a couple of small functions to fill this gap and released them as the x2j package.

Over the next year and a half additional features were added, and the companion j2x
package was released to address XML encoding of arbitrary JSON and map[string]interface{}
values.  As part of a refactoring of our production system and looking at how we'd been
using the x2j and j2x packages we found that we rarely performed direct XML-to-JSON or
JSON-to_XML conversion and that working with the XML or JSON as map[string]interface{}
values was the primary value.  Thus, everything was refactored into the mxj package.

About

Encode / decode XML as JSON or map[string]interface{}; extract values with dot-notation paths and wildcards. Replaces x2j and j2x packages.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 100.0%