package main import ( "fmt" "strings" "strconv" "os" "bufio" "github.com/beevik/etree" ) func main() { // media locations to be replaced itunes_media := "file://localhost/Z:/Music/usb/" // original location web_media := "https://dtam.pw/music/tracks/" // final web location // playlist length counter playlist_length := 0 // temporary variables to set up and gather information // next: will toggle so we know on the next loop to save information name_next := false artist_next := false location_next := false id_next := false // temp: temporarily store the song information before we insert it into our array name_temp := "" artist_temp := "" location_temp := "" id_temp := "" // struct containing a single song and it's information type Song_Information struct { name string artist string location string id string } // array of the playlist, but only it's ID. when we initially parse the xml, // it only gives us the playlist in ID form var playlist_tracks []string // array of the songs, but not in the correct order var songlist []Song_Information // array of the songs, in the correct order var playlist []Song_Information // import the playlist doc := etree.NewDocument() if err := doc.ReadFromFile("main.xml"); err != nil { panic(err) } // find the playlist in it's ID form for _, e := range doc.FindElements("./plist/dict/array/dict/array/dict/integer") { // add track to playlist playlist_tracks = append(playlist_tracks, e.Text()) } // get the length of the playlist for _, e := range doc.FindElements("./plist/dict/dict/*") { _ = e playlist_length += 1 } // cycle through the playlist and grab the song information for i := 0; i < playlist_length; i++ { // based on how the xml is formatted from itunes, it has 2 separate elements for each // key, so we need to mark when we find the key we need and say the next item is the item for _, e := range doc.FindElements("./plist/dict/dict/dict[" + strconv.Itoa(i) + "]/*") { // if we find an element with the name "Name", we know the next element is the actual // name, so mark it so that we know next loop to store it if(e.Text() == "Name") { name_next = true continue } if(e.Text() == "Artist") { artist_next = true continue } if(e.Text() == "Location") { location_next = true continue } if(e.Text() == "Track ID") { id_next = true continue } // once we have determined that this should be the information, save it // to a temporary variable if(name_next) { name_temp = e.Text() name_temp = strings.Replace(name_temp, "&", "&", 5) // make the ampersand xml safe name_next = false continue } if(artist_next) { artist_temp = e.Text() artist_temp = strings.Replace(artist_temp, "&", "&", 5) artist_next = false continue } if(location_next) { location_temp = e.Text() // replace the file name link with the web link location_temp = strings.Replace(location_temp, itunes_media, web_media, 1) location_temp = strings.Replace(location_temp, "&", "&", 5) location_next = false continue } if(id_next) { id_temp = e.Text() id_next = false continue } // once we have found all the information we need, put it into a struct and append it // to our unordered array of songs if(name_temp != "" && artist_temp != "" && location_temp != "" && id_temp != "") { songlist = append(songlist, Song_Information{name_temp, artist_temp, location_temp, id_temp}) name_temp = "" // clear our variables again artist_temp = "" location_temp = "" id_temp = "" continue } } } // put our tracks in the appropriate order based on the playlist for _, e := range playlist_tracks { // loop through our unordered array and find the correct song for _, f := range songlist { if(f.id == e) { // add the correct song to the final playlist playlist = append(playlist, Song_Information{f.name, f.artist, f.location, f.id}) break } } } // at this point, our playlist should be sorted // create the xml file file, err := os.OpenFile("main_parsed.xml", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { panic(err) } // write the initial information for the xml w := bufio.NewWriter(file) fmt.Fprintln(w, ``) fmt.Fprintln(w, ``) fmt.Fprintln(w, "") // cycle through our ordered playlist and write it to the file for _, e := range playlist { fmt.Fprintln(w, "") fmt.Fprintln(w, "" + e.artist + "") fmt.Fprintln(w, "" + e.name + "") fmt.Fprintln(w, "" + e.location+ "") fmt.Fprintln(w, "") } // closing information fmt.Fprintln(w, "") fmt.Fprintln(w, "") // write it out w.Flush() }