Swift解析XML问题求助:iOS新手获取XML中歌曲名与艺术家信息
Hey there! Congrats on building your first iOS app—that’s such a huge win, nice work! I totally get how overwhelming XML parsing tutorials can feel when you’re just starting out, so let’s break this down step by step with concrete code examples you can adapt to your project.
First, Let’s Cover the Basics: iOS Native XML Parsing
The most common built-in tool for XML parsing on iOS is NSXMLParser, which works on an event-driven system. That means it triggers methods as it reads through your XML file, and you can capture the data you need at specific points (like when it hits a start tag, reads text inside a tag, or reaches an end tag).
Step 1: Create a Song Model
First, let’s make a simple class to store each song’s data—this will keep your code organized:
class Song { var songName: String? var artist: String? init() {} }
Step 2: Set Up the XML Parser with Delegate Methods
Next, you’ll use NSXMLParser and implement its delegate methods to capture the data. I’ll show you how to do this in a view controller (you could also make a dedicated parser class if you want to keep things clean):
class YourViewController: UIViewController, NSXMLParserDelegate { // Store all parsed songs here var songs = [Song]() // Track the song we're currently parsing var currentSong: Song? // Track which XML element we're reading right now var currentElement = "" // Track the text inside the current element var currentText = "" override func viewDidLoad() { super.viewDidLoad() // Start parsing when the view loads startParsingXML() } func startParsingXML() { // Replace "yourXMLFile" with the name of your XML file in the project guard let filePath = Bundle.main.path(forResource: "yourXMLFile", ofType: "xml") else { print("Oops, couldn't find the XML file in your project!") return } let fileURL = URL(fileURLWithPath: filePath) let parser = NSXMLParser(contentsOf: fileURL)! parser.delegate = self // Start the parsing process parser.parse() // Once parsing is done, you can use the songs array! for song in songs { print("Song: \(song.songName ?? "Unknown") | Artist: \(song.artist ?? "Unknown")") } } // Triggered when the parser finds the start of an XML element (e.g., <song>, <songName>) func parser(_ parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { currentElement = elementName currentText = "" // If we hit a <song> tag, create a new Song object to fill with data if elementName == "song" { currentSong = Song() } } // Triggered when the parser reads text inside an element func parser(_ parser: NSXMLParser, foundCharacters string: String) { // Clean up whitespace/newlines and add to our current text currentText += string.trimmingCharacters(in: .whitespacesAndNewlines) } // Triggered when the parser reaches the end of an XML element (e.g., </song>, </songName>) func parser(_ parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { // Map the parsed text to the correct Song property based on the element name switch elementName { case "songName": // Replace with your actual XML tag for song names currentSong?.songName = currentText case "artist": // Replace with your actual XML tag for artists currentSong?.artist = currentText case "song": // When we finish parsing a <song>, add it to our songs array if let completedSong = currentSong { songs.append(completedSong) currentSong = nil } default: break } // Reset for the next element currentElement = "" currentText = "" } // Handle any parsing errors (super helpful for debugging!) func parser(_ parser: NSXMLParser, parseErrorOccurred parseError: Error) { print("Parsing Error: \(parseError.localizedDescription)") } }
Key Notes to Adapt This to Your XML
You’ll need to tweak the element names (like "songName", "artist", "song") to match exactly what’s in your XML file. For example, if your XML looks like this:
<musicLibrary> <track> <title>Bohemian Rhapsody</title> <performer>Queen</performer> </track> <track> <title>Uptown Funk</title> <performer>Mark Ronson ft. Bruno Mars</performer> </track> </musicLibrary>
You’d change:
elementName == "song"→elementName == "track"case "songName"→case "title"case "artist"→case "performer"
Bonus: Easier Parsing with Third-Party Libraries
If you find NSXMLParser too tedious, you can use a library like XMLCoder (which works with Swift’s Codable protocol) to simplify things. Here’s a quick example:
- Add XMLCoder to your project via Swift Package Manager or CocoaPods.
- Update your Song model to conform to
Codable:
class Song: Codable { var title: String? var performer: String? // Use CodingKeys if your XML tags don't match property names exactly enum CodingKeys: String, CodingKey { case title = "title" case performer = "performer" } }
- Parse the XML with a few lines of code:
let data = try Data(contentsOf: fileURL) let decoder = XMLDecoder() // If your XML has a root element like <musicLibrary>, you might need to wrap the songs in a container let musicLibrary = try decoder.decode(MusicLibrary.self, from: data) let songs = musicLibrary.tracks
(You’d need a MusicLibrary class that contains an array of Song objects to match the root XML element.)
If you share a snippet of your actual XML structure or any code you’ve already written, I can help you tailor this even more. You’ve got this—first app hurdles are tough, but you’re making progress!
内容的提问来源于stack exchange,提问作者Amos94

