...

Source file src/github.com/clbanning/mxj/v2/example_test.go

Documentation: github.com/clbanning/mxj/v2

     1  // +test OMIT
     2  
     3  // note - "// Output:" is  a key for "go test" to match function ouput with the lines that follow.
     4  //        It is also use by "godoc" to build the Output block of the function / method documentation.
     5  //        To skip processing Example* functions, use: go test -run "Test*"
     6  //	       or make sure example function output matches // Output: documentation EXACTLY.
     7  
     8  package mxj_test
     9  
    10  import (
    11  /*
    12  	"bytes"
    13  	"fmt"
    14  	"github.com/clbanning/mxj"
    15  	"io"
    16  */
    17  )
    18  
    19  func ExampleHandleXmlReader() {
    20  	/*
    21  		Bulk processing XML to JSON seems to be a common requirement.
    22  		See: bulk_test.go for working example.
    23  		     Run "go test" in package directory then scroll back to find output.
    24  
    25  		The logic is as follows.
    26  
    27  			// need somewhere to write the JSON.
    28  			var jsonWriter io.Writer
    29  
    30  			// probably want to log any errors in reading the XML stream
    31  			var xmlErrLogger io.Writer
    32  
    33  			// func to handle Map value from XML Reader
    34  			func maphandler(m mxj.Map) bool {
    35  				// marshal Map as JSON
    36  				jsonVal, err := m.Json()
    37  				if err != nil {
    38  					// log error
    39  					return false // stops further processing of XML Reader
    40  				}
    41  
    42  				// write JSON somewhere
    43  				_, err = jsonWriter.Write(jsonVal)
    44  				if err != nil {
    45  					// log error
    46  					return false // stops further processing of XML Reader
    47  				}
    48  
    49  				// continue - get next XML from Reader
    50  				return true
    51  			}
    52  
    53  			// func to handle error from unmarshaling XML Reader
    54  			func errhandler(errVal error) bool {
    55  				// log error somewhere
    56  				_, err := xmlErrLogger.Write([]byte(errVal.Error()))
    57  				if err != nil {
    58  					// log error
    59  					return false // stops further processing of XML Reader
    60  				}
    61  
    62  				// continue processing
    63  				return true
    64  			}
    65  
    66  			// func that starts bulk processing of the XML
    67  				...
    68  				// set up io.Reader for XML data - perhaps an os.File
    69  				...
    70  				err := mxj.HandleXmlReader(xmlReader, maphandler, errhandler)
    71  				if err != nil {
    72  					// handle error
    73  				}
    74  				...
    75  	*/
    76  }
    77  
    78  func ExampleHandleXmlReaderRaw() {
    79  	/*
    80  		See: bulkraw_test.go for working example.
    81  		Run "go test" in package directory then scroll back to find output.
    82  
    83  		Basic logic for bulk XML to JSON processing is in HandleXmlReader example;
    84  		the only major difference is in handler function signatures so they are passed
    85  		the raw XML.  (Read documentation on NewXmlReader regarding performance.)
    86  	*/
    87  }
    88  
    89  func ExampleHandleJsonReader() {
    90  	/*
    91  		See: bulk_test.go for working example.
    92  		Run "go test" in package directory then scroll back to find output.
    93  
    94  		Basic logic for bulk JSON to XML processing is similar to that for
    95  		bulk XML to JSON processing as outlined in the HandleXmlReader example.
    96  		The test case is also a good example.
    97  	*/
    98  }
    99  
   100  func ExampleHandleJsonReaderRaw() {
   101  	/*
   102  		See: bulkraw_test.go for working example.
   103  		Run "go test" in package directory then scroll back to find output.
   104  
   105  		Basic logic for bulk JSON to XML processing is similar to that for
   106  		bulk XML to JSON processing as outlined in the HandleXmlReader example.
   107  		The test case is also a good example.
   108  	*/
   109  }
   110  
   111  /*
   112  func ExampleNewMapXmlReaderRaw() {
   113  	// in an http.Handler
   114  
   115  	mapVal, raw, err := mxj.NewMapXmlReader(req.Body)
   116  	if err != nil {
   117  		// handle error
   118  	}
   119  	logger.Print(string(*raw))
   120  	// do something with mapVal
   121  
   122  }
   123  */
   124  
   125  /*
   126  func ExampleNewMapStruct() {
   127  	type str struct {
   128  		IntVal   int     `structs:"int"`
   129  		StrVal   string  `structs:"str"`
   130  		FloatVal float64 `structs:"float"`
   131  		BoolVal  bool    `structs:"bool"`
   132  		private  string
   133  	}
   134  	strVal := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"}
   135  
   136  	mapVal, merr := mxj.NewMapStruct(strVal)
   137  	if merr != nil {
   138  		// handle error
   139  	}
   140  
   141  	fmt.Printf("strVal: %#v\n", strVal)
   142  	fmt.Printf("mapVal: %#v\n", mapVal)
   143  	// Note: example output is conformed to pass "go test".  "mxj_test" is example_test.go package name.
   144  
   145  	// NoFail output:
   146  	// strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"}
   147  	// mapVal: mxj.Map{"float":3.14159, "bool":true, "int":4, "str":"now's the time"}
   148  }
   149  */
   150  
   151  func ExampleMap_Struct() {
   152  	/*
   153  	   	type str struct {
   154  	   		IntVal   int     `json:"int"`
   155  	   		StrVal   string  `json:"str"`
   156  	   		FloatVal float64 `json:"float"`
   157  	   		BoolVal  bool    `json:"bool"`
   158  	   		private  string
   159  	   	}
   160  
   161  	   	mapVal := mxj.Map{"int": 4, "str": "now's the time", "float": 3.14159, "bool": true, "private": "Somewhere over the rainbow"}
   162  
   163  	   	var strVal str
   164  	   	mverr := mapVal.Struct(&strVal)
   165  	   	if mverr != nil {
   166  	   		// handle error
   167  	   	}
   168  
   169  	   	fmt.Printf("mapVal: %#v\n", mapVal)
   170  	   	fmt.Printf("strVal: %#v\n", strVal)
   171  
   172  	   // Unordered output for above:
   173  	   // mapVal: mxj.Map{"int":4, "str":"now's the time", "float":3.14159, "bool":true, "private":"Somewhere over the rainbow"}
   174  	   // strVal: mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:""}
   175  	*/
   176  }
   177  
   178  func ExampleMap_ValuesForPath() {
   179  	/*
   180  	   	// a snippet from examples/gonuts1.go
   181  	   	// How to compensate for irregular tag labels in data.
   182  	   	// Need to extract from an XML stream the values for "netid" and "idnet".
   183  	   	// Solution: use a wildcard path "data.*" to anonymize the "netid" and "idnet" tags.
   184  
   185  	   	var msg1 = []byte(`
   186  	   <?xml version="1.0" encoding="UTF-8"?>
   187  	   <data>
   188  	       <netid>
   189  	           <disable>no</disable>
   190  	           <text1>default:text</text1>
   191  	           <word1>default:word</word1>
   192  	       </netid>
   193  	   </data>
   194  	   `)
   195  
   196  	   	var msg2 = []byte(`
   197  	   <?xml version="1.0" encoding="UTF-8"?>
   198  	   <data>
   199  	       <idnet>
   200  	           <disable>yes</disable>
   201  	           <text1>default:text</text1>
   202  	           <word1>default:word</word1>
   203  	       </idnet>
   204  	   </data>
   205  	   `)
   206  
   207  	   	// let's create a message stream
   208  	   	buf := new(bytes.Buffer)
   209  	   	// load a couple of messages into it
   210  	   	_, _ = buf.Write(msg1)
   211  	   	_, _ = buf.Write(msg2)
   212  
   213  	   	n := 0
   214  	   	for {
   215  	   		n++
   216  	   		// Read the stream as Map values - quit on io.EOF.
   217  	   		// Get the raw XML as well as the Map value.
   218  	   		m, merr := mxj.NewMapXmlReader(buf)
   219  	   		if merr != nil && merr != io.EOF {
   220  	   			// handle error - for demo we just print it and continue
   221  	   			fmt.Printf("msg: %d - merr: %s\n", n, merr.Error())
   222  	   			continue
   223  	   		} else if merr == io.EOF {
   224  	   			break
   225  	   		}
   226  
   227  	   		// get the values for "netid" or "idnet" key using path == "data.*"
   228  	   		values, _ := m.ValuesForPath("data.*")
   229  	   		fmt.Println("\nmsg:", n, "> path == data.* - got array of values, len:", len(values))
   230  	   		for i, val := range values {
   231  	   			fmt.Println("ValuesForPath result array member -", i, ":", val)
   232  	   			fmt.Println("              k:v pairs for array member:", i)
   233  	   			for key, val := range val.(map[string]interface{}) {
   234  	   				// You'd probably want to process the value, as appropriate.
   235  	   				// Here we just print it out.
   236  	   				fmt.Println("\t\t", key, ":", val)
   237  	   			}
   238  	   		}
   239  	   	}
   240  	   	// NoFail output:
   241  	   	// msg: 1 > path == data.* - got array of values, len: 1
   242  	   	// ValuesForPath result array member - 0 : map[disable:no text1:default:text word1:default:word]
   243  	   	//               k:v pairs for array member: 0
   244  	   	// 		 disable : no
   245  	   	// 		 text1 : default:text
   246  	   	// 		 word1 : default:word
   247  	   	//
   248  	   	// msg: 2 > path == data.* - got array of values, len: 1
   249  	   	// ValuesForPath result array member - 0 : map[disable:yes text1:default:text word1:default:word]
   250  	   	//               k:v pairs for array member: 0
   251  	   	// 		 disable : yes
   252  	   	// 		 text1 : default:text
   253  	   	// 		 word1 : default:word
   254  	*/
   255  }
   256  
   257  func ExampleMap_UpdateValuesForPath() {
   258  	/*
   259  
   260  	   var biblioDoc = []byte(`
   261  	   <biblio>
   262  	   	<author>
   263  	   		<name>William Gaddis</name>
   264  	   		<books>
   265  	   			<book>
   266  	   				<title>The Recognitions</title>
   267  	   				<date>1955</date>
   268  	   				<review>A novel that changed the face of American literature.</review>
   269  	   			</book>
   270  	   			<book>
   271  	   				<title>JR</title>
   272  	   				<date>1975</date>
   273  	   				<review>Winner of National Book Award for Fiction.</review>
   274  	   			</book>
   275  	   		</books>
   276  	   	</author>
   277  	   </biblio>`)
   278  
   279  	   	...
   280  	   	m, merr := mxj.NewMapXml(biblioDoc)
   281  	   	if merr != nil {
   282  	   		// handle error
   283  	   	}
   284  
   285  	   	// change 'review' for a book
   286  	   	count, err := m.UpdateValuesForPath("review:National Book Award winner." "*.*.*.*", "title:JR")
   287  	   	if err != nil {
   288  	   		// handle error
   289  	   	}
   290  	   	...
   291  
   292  	   	// change 'date' value from string type to float64 type
   293  	   	// Note: the following is equivalent to m, merr := NewMapXml(biblioDoc, mxj.Cast).
   294  	   	path := m.PathForKeyShortest("date")
   295  	   	v, err := m.ValuesForPath(path)
   296  	   	if err != nil {
   297  	   		// handle error
   298  	   	}
   299  	   	var total int
   300  	   	for _, vv := range v {
   301  	   		oldVal := "date:" + vv.(string)
   302  	   		newVal := "date:" + vv.(string) + ":num"
   303  	   		n, err := m.UpdateValuesForPath(newVal, path, oldVal)
   304  	   		if err != nil {
   305  	   			// handle error
   306  	   		}
   307  	   		total += n
   308  	   	}
   309  	   	...
   310  	*/
   311  }
   312  
   313  func ExampleMap_Copy() {
   314  	/*
   315  		// Hand-crafted Map values that include structures do NOT Copy() as expected,
   316  		// since to simulate a deep copy the original Map value is JSON encoded then decoded.
   317  
   318  		type str struct {
   319  			IntVal   int     `json:"int"`
   320  			StrVal   string  `json:"str"`
   321  			FloatVal float64 `json:"float"`
   322  			BoolVal  bool    `json:"bool"`
   323  			private  string
   324  		}
   325  		s := str{IntVal: 4, StrVal: "now's the time", FloatVal: 3.14159, BoolVal: true, private: "Skies are blue"}
   326  		m := make(map[string]interface{}, 0)
   327  		m["struct"] = interface{}(s)
   328  		m["struct_ptr"] = interface{}(&s)
   329  		m["misc"] = interface{}(`Now is the time`)
   330  
   331  		mv := mxj.Map(m)
   332  		cp, _ := mv.Copy()
   333  
   334  		fmt.Printf("mv:\n%s\n", mv.StringIndent(2))
   335  		fmt.Printf("cp:\n%s\n", cp.StringIndent(2))
   336  
   337  		// NoFail output:
   338  		// mv:
   339  		//     misc : [string] Now is the time
   340  		//     struct : [mxj_test.str] {IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue}
   341  		//     struct_ptr : [*mxj_test.str] &{IntVal:4 StrVal:now's the time FloatVal:3.14159 BoolVal:true private:Skies are blue}
   342  		// cp:
   343  		//    misc : [string] Now is the time
   344  		//    struct :
   345  		//      bool : [bool] true
   346  		//      float : [float64] 3.14159
   347  		//      int : [float64] 4
   348  		//      str : [string] now's the time
   349  		//    struct_ptr :
   350  		//      bool : [bool] true
   351  		//      float : [float64] 3.14159
   352  		//      int : [float64] 4
   353  		//      str : [string] now's the time
   354  		//
   355  	*/
   356  }
   357  

View as plain text