func parseResponse(m *mxj.Map, response *[]mxj.Map, responsename, idmapname string) error { path := fmt.Sprintf("Envelope.Body.%sResponse.%sReturn.-href", responsename, responsename) mainid, err := m.ValueForPathString(path) if err != nil { return err } value, err := m.ValuesForKey("multiRef", fmt.Sprintf("-id:%s", mainid[1:])) if err != nil { return err } if len(value) == 0 { return errors.New("Main reponse not found") } valuemap := mxj.Map(value[0].(map[string]interface{})) statuscode, err := valuemap.ValueForPathString("statusCode.#text") if err != nil { return err } if statuscode != "SUCCESS" { errcode, _ := valuemap.ValueForPathString("errorCode.#text") return YFErrors[errcode] } if idmapname != "" { ids, err := valuemap.ValuesForPath(idmapname + "." + idmapname) if err != nil { return fmt.Errorf("Could not find %s.%s %v", idmapname, idmapname, err) } for _, id := range ids { idmap := mxj.Map(id.(map[string]interface{})) idvalue, err := idmap.ValueForPathString("-href") if err != nil { return err } multiref, err := m.ValuesForKey("multiRef", "-id:"+idvalue[1:]) if err != nil { return fmt.Errorf("Could not find multiref for id %s, %v", idvalue[1:], err) } if len(multiref) == 0 { return fmt.Errorf("mutilRef element not found for id : %s", idvalue[1:]) } *response = append(*response, mxj.Map(multiref[0].(map[string]interface{}))) } } else { // Add the original back, this is to get responses such as sessionid etc. *response = append(*response, valuemap) } return nil }
func main() { // parse XML into a Map m, merr := mxj.NewMapXml(xmlData) if merr != nil { fmt.Println("merr:", merr.Error()) return } // extract the 'list3-1-1-1' node - there'll be just 1? // NOTE: attribute keys are prepended with '-' lstVal, lerr := m.ValuesForPath("*.*.*.*.*", "-name:list3-1-1-1") if lerr != nil { fmt.Println("ierr:", lerr.Error()) return } // assuming just one value returned - create a new Map mv := mxj.Map(lstVal[0].(map[string]interface{})) // extract the 'int' values by 'name' attribute: "-name" // interate over list of 'name' values of interest var names = []string{"field1", "field2", "field3", "field4", "field5"} for _, n := range names { vals, verr := mv.ValuesForKey("int", "-name:"+n) if verr != nil { fmt.Println("verr:", verr.Error(), len(vals)) return } // values for simple elements have key '#text' // NOTE: there can be only one value for key '#text' fmt.Println(n, ":", vals[0].(map[string]interface{})["#text"]) } }
/* ToMap convert the node value to a mxj map. If fail to convert, an error will be returned. Tags have no sub tag, but have attributes is also a map. Attributes of the tag has key '-attributesName'. Tags' value has key '#test'. Ex: <MessageId MarketplaceID="ATVPDKDDIKX0D" SKU="24478624"> 173964729 </MessageId> After to map, map[string]string{ "-MarketplaceID": "ATVPDKDDIKX0D", "-SKU": "24478624", "#text": "173964729", } */ func (xn *XMLNode) ToMap() (mxj.Map, error) { if xn.ValueType() == reflect.Map { return mxj.Map(xn.Value.(map[string]interface{})), nil } return nil, errors.New("Value is not a map.") }
func ExampleMap_Copy() { // 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:%s\n", mv.StringIndent(2)) fmt.Printf("cp:%s\n", cp.StringIndent(2)) // Output: // mv: // struct :[unknown] mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} // struct_ptr :[unknown] &mxj_test.str{IntVal:4, StrVal:"now's the time", FloatVal:3.14159, BoolVal:true, private:"Skies are blue"} // misc :[string] Now is the time // cp: // misc :[string] Now is the time // struct : // int :[float64] 4.00e+00 // str :[string] now's the time // float :[float64] 3.14e+00 // bool :[bool] true // struct_ptr : // int :[float64] 4.00e+00 // str :[string] now's the time // float :[float64] 3.14e+00 // bool :[bool] true }
// Uncomment the print statements to details of the process here. func copyCmts(m mxj.Map, path string) error { // get the array of Items entries for the 'path' vals, err := m.ValuesForPath(path) if err != nil { return fmt.Errorf("ValuesForPath err: %s", err.Error()) } else if len(vals) == 0 { return fmt.Errorf("no vals for path: %s", path) } // process each Items entry for _, v := range vals { vm, ok := v.(map[string]interface{}) if !ok { return fmt.Errorf("assertion failed") } // get the Comment list c, ok := vm["Comment"] if !ok { // --> no Items.Comment elements continue } // Don't assume that Comment is an array. // There may be just one value, in which case it will decode as map[string]interface{}. switch c.(type) { case map[string]interface{}: c = []interface{}{c} } cmt := c.([]interface{}) // get the Request list r, ok := vm["Request"] if !ok { // --> no Items.Request elements continue } // Don't assume the Request is an array. // There may be just one value, in which case it will decode as map[string]interface{}. switch r.(type) { case map[string]interface{}: r = []interface{}{r} } req := r.([]interface{}) // fmt.Println("Comment:", cmt) // fmt.Println("Request:", req) // Comment elements with #seq==n are followed by Request element with #seq==n+1. // For each Comment.#seq==n extract the CommentText attribute value and use it to // set the ReportingName attribute value in Request.#seq==n+1. for _, v := range cmt { vmap := v.(map[string]interface{}) seq := vmap["#seq"].(int) // type is int // extract CommentText attr from "#attr" acmt, _ := mxj.Map(vmap).ValueForPath("#attr.CommentText.#text") if acmt == "" { fmt.Println("no CommentText value in Comment attributes") } // fmt.Println(seq, acmt) // find the request with the #seq==seq+1 value var r map[string]interface{} for _, vv := range req { rt := vv.(map[string]interface{}) if rt["#seq"].(int) == seq+1 { r = rt break } } if r == nil { // no Request with #seq==seq+1 continue } if err := mxj.Map(r).SetValueForPath(acmt, "#attr.ReportingName.#text"); err != nil { fmt.Println("SetValueForPath err:", err) break } } } return nil }
lua.CheckAny(l, 1) var v interface{} var err error if l.IsTable(1) { if v, err = util.PullTable(l, 1); err != nil { lua.Errorf(l, "%s", err) panic("unreachable") } } else { lua.Errorf(l, "Only tables can be converted to XML") panic("unreachable") } res, err := mxj.Map(v.(map[string]interface{})).Xml() if err != nil { lua.Errorf(l, "%s", err.Error()) panic("unreachable") } util.DeepPush(l, string(res)) return 1 }, }, { "decode", func(l *lua.State) int {
func main() { // fmt.Println(string(data)) rdr := bytes.NewReader(data) // We read processing docs sequentially. // Un-rooted ProcInst or Comments are processed AND just re-encoded. (XmlSeqIndent() knows how, now.) for m, err := mxj.NewMapXmlSeqReader(rdr); m != nil || err != io.EOF; m, err = mxj.NewMapXmlSeqReader(rdr) { if err != nil { if err != mxj.NoRoot { fmt.Println("NewMapXmlSeq err:", err) fmt.Println("m:", m) } else if m != nil { x, _ := m.XmlSeqIndent("", " ") fmt.Println(string(x)) } continue } // fmt.Println(m.StringIndent()) // get the array of TransactionTimer entries for the 'path' vals, err := m.ValuesForPath("WebTest.Items.TransactionTimer") if err != nil { fmt.Printf("ValuesForPath err: %s", err.Error()) continue } else if len(vals) == 0 { fmt.Printf("no vals for WebTest.Items.TransactionTimer") continue } // process each TransactionTimer element ... for _, t := range vals { tmap := t.(map[string]interface{}) // get Name from attrs tname, _ := mxj.Map(tmap).ValueForPathString("#attr.Name.#text") // now process TransactionTimer.Items value ... is a map[string]interface{} value // with Comment and Request keys with array values vm, ok := tmap["Items"].(map[string]interface{}) if !ok { fmt.Println("assertion failed") return } // get the Comment list c, ok := vm["Comment"] if !ok { // --> no Items.Comment elements continue } // Don't assume that Comment is an array. // There may be just one value, in which case it will decode as map[string]interface{}. switch c.(type) { case map[string]interface{}: c = []interface{}{c} } cmt := c.([]interface{}) // get the Request list r, ok := vm["Request"] if !ok { // --> no Items.Request elements continue } // Don't assume the Request is an array. // There may be just one value, in which case it will decode as map[string]interface{}. switch r.(type) { case map[string]interface{}: r = []interface{}{r} } req := r.([]interface{}) // fmt.Println("Comment:", cmt) // fmt.Println("Request:", req) // Comment elements with #seq==n are followed by Request element with #seq==n+1. // For each Comment.#seq==n extract the CommentText attribute value and use it to // set the ReportingName attribute value in Request.#seq==n+1. for _, v := range cmt { vmap := v.(map[string]interface{}) seq := vmap["#seq"].(int) // type is int // extract CommentText attr from array of "#attr" acmt, _ := mxj.Map(vmap).ValueForPathString("#attr.CommentText.#text") if acmt == "" { fmt.Println("no CommentText value in Comment attributes") } // fmt.Println(seq, acmt) // find the request with the #seq==seq+1 value var r map[string]interface{} for _, vv := range req { rt := vv.(map[string]interface{}) if rt["#seq"].(int) == seq+1 { r = rt break } } if r == nil { // no Request with #seq==seq+1 continue } if err := mxj.Map(r).SetValueForPath(tname+", "+acmt, "#attr.ReportingName.#text"); err != nil { fmt.Println("SetValueForPath err:", err) break } } } // re-encode the map with the TransactionTimer.#attr.Name & Items.Comment[#seq==n].#attr.CommentText // values copied to the Items.Request[#seq==n+1].#attr.ReportingName elements. b, err := m.XmlSeqIndent("", " ") if err != nil { fmt.Println("XmlIndent err:", err) return } fmt.Println(string(b)) } }
func main() { fmt.Println(string(data)) m, err := mxj.NewMapXmlSeq(data) if err != nil { fmt.Println("NewMapXml err:", err) return } vals, err := m.ValuesForPath("author.first-name") // full-path option if err != nil { fmt.Println("ValuesForPath err:", err) return } else if len(vals) == 0 { fmt.Println("no first-name vals") return } var fname, date string var index int for _, v := range vals { vm, ok := v.(map[string]interface{}) if !ok { fmt.Println("assertion failed") return } fn, ok := vm["#text"].(string) if !ok { fmt.Println("no #text tag") return } // extract the associated date dt, _ := mxj.Map(vm).ValueForPathString("#attr.effect_range.#text") if dt == "" { fmt.Println("no effect_range attr") return } dts := strings.Split(dt, "-") if len(dts) > 1 && dts[len(dts)-1] == "" { index = len(dts) - 2 } else if len(dts) > 0 { index = len(dts) - 1 } if len(dts) > 0 && dts[index] > date { date = dts[index] fname = fn } } vals, err = m.ValuesForPath("author.last-name.#text") // full-path option if err != nil { fmt.Println("ValuesForPath err:", err) return } else if len(vals) == 0 { fmt.Println("no last-name vals") return } lname := vals[0].(string) if err = m.SetValueForPath(fname+" "+lname, "author.full-name.#text"); err != nil { fmt.Println("SetValueForPath err:", err) return } b, err := m.XmlSeqIndent("", " ") if err != nil { fmt.Println("XmlIndent err:", err) return } fmt.Println(string(b)) }