在swift中解析XML数据

在swift中解析XML数据,swift,xml,Swift,Xml,这是我的第一个iOS应用程序,我从XML获取数据时有点麻烦。我需要从如下所示的XML文件中获取歌曲名称和艺术家: <?xml version="1.0" encoding="utf-8"?> <Schedule System="Jazler"> <Event status="happening" startTime="19:14:30" eventType="song"> <Announcement Display="Now On Air:"

这是我的第一个iOS应用程序,我从XML获取数据时有点麻烦。我需要从如下所示的XML文件中获取歌曲名称和艺术家:

<?xml version="1.0" encoding="utf-8"?>
<Schedule System="Jazler">
  <Event status="happening" startTime="19:14:30" eventType="song">
    <Announcement Display="Now On Air:"/>
    <Song title="E timpul">
      <Artist name="Revers">
      </Artist>
      <Jazler ID="16490"/>
      <PlayLister ID=""/>
      <Media runTime="03:03"/>
      <Expire Time="19:17:33"/>
    </Song>
  </Event>
</Schedule>

非常感谢您的帮助。

首先将xml转换为NSData,并调用解析器对其进行解析

//converting into NSData
var data: Data? = theXML.data(using: .utf8)

//initiate  NSXMLParser with this data
var parser: XMLParser? = XMLParser(data: data ?? Data())

//setting delegate
parser?.delegate = self

//call the method to parse
var result: Bool? = parser?.parse()

parser?.shouldResolveExternalEntities = true
现在,您需要在类中实现NSXMLParser委托

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
currentElement = elementName
print("CurrentElementl: [\(elementName)]")
}

func parser(_ parser: XMLParser, foundCharacters string: String) {
print("foundCharacters: [\(string)]")
}

您将在xml的键下找到值。

因为您的xml包含元素属性的所有值,所以您不需要实现
foundCharacters
。例如,您的解析器委托可能看起来很简单,如下所示:

var song: String?
var artist: String?

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
    switch elementName {
    case "Song":   song   = attributeDict["title"]
    case "Artist": artist = attributeDict["name"]
    default:       break
    }
}
两项意见:

  • 不过,我倾向于将此解析代码从视图控制器中取出,并将其放入专用对象中,以帮助防止“视图控制器膨胀”

  • 我还将使用
    URLSession
    ,以防对请求的响应有点慢。通常,应该避免使用
    XMLParser(contentsOf:)
    ,因为这是同步执行请求的

    在您的情况下,因为您是从
    localhost
    请求数据,所以这可能不太重要。但是,始终异步执行HTTP请求是明智的

  • 无论如何,这可能会产生如下结果:

    class SongParser: NSObject {
        var song: String?
        var artist: String?
        
        class func requestSong(completionHandler: @escaping (String?, String?, Error?) -> Void) {
            let url = URL(string: "http://localhost/jazler/NowOnAir.xml")!
            let task = URLSession.shared.dataTask(with: url) { data, _, error in
                guard let data = data, error == nil else {
                    DispatchQueue.main.async {
                        completionHandler(nil, nil, error)
                    }
                    return
                }
                
                let delegate = SongParser()
                let parser = XMLParser(data: data)
                parser.delegate = delegate
                DispatchQueue.main.async {
                    completionHandler(delegate.song, delegate.artist, parser.parserError)
                }
            }
            task.resume()
        }
    }
    
    extension SongParser: XMLParserDelegate {
        func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
            switch elementName {
            case "Song":   song   = attributeDict["title"]
            case "Artist": artist = attributeDict["name"]
            default:       break
            }
        }
        
    }
    
    你会这样使用它:

    SongParser.requestSong { song, artist, error in
        guard let song = song, let artist = artist, error == nil else {
            print(error ?? "Unknown error")
            return
        }
        
        print("Song:", song)
        print("Artist:", artist)
    }
    

    非常感谢你。它起作用了!刚刚在第一个函数中添加了这些行,我得到了歌曲和艺术家的名字。如果(elementName==“Song”){Song=attributeDict[“title”]!print(Song)}如果(elementName==“Artist”){Artist=attributeDict[“name”]!print(Artist)}如果你得到了答案,请接受答案,让社区知道你得到了答案Hey@Rob,我如何修改它来解析本地文件,例如从Apple Music导出的library.xml文件?@southernyanke65-重新解析本地文件,只需使用解析文件即可。但以上是一种特殊情况,其中XML的所有信息都包含在XML标记的属性中,这是非常不寻常的。通常情况下,在开始和结束标记对之间需要捕获字符(比如)。@Rob,我们可以在SwiftUI中获取XML数据吗?我需要更改什么?这里没有UI代码,所以它在SwiftUI中与在UIKit中相同。
    SongParser.requestSong { song, artist, error in
        guard let song = song, let artist = artist, error == nil else {
            print(error ?? "Unknown error")
            return
        }
        
        print("Song:", song)
        print("Artist:", artist)
    }