提问人:Anand Gautam 提问时间:9/20/2018 最后编辑:Anand Gautam 更新时间:11/23/2018 访问量:605
如何在 Swift3 iOS 中进行 XML 解析?
How to do XML Parsing in Swift3 iOS?
问:
我正在尝试对以下文件进行XML解析:
<bgmusic>
<genre title=“Title1”>
<track title=“SubTitle1” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2856_01_ Animation.ogg" />
<track title="SubTitle2” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2860_02_Entanglement.ogg" />
</genre>
<genre title="Title2”>
<track title="SubTitle3” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2856_01_Animate.ogg" />
<track title="SubTitle4” path="https://test/Background_Track%20-%20Ambient%20-%20ANW2860_02_ SubTitle4.ogg" />
</genre>
</bgmusic>
基本上,我已经创建了两个ViewController,一个用于显示流派标题,另一个VC用于显示其详细信息。为此,我创建了以下两个模态类:
class GenreModel {
var title: String = ""
var genreSongsArray = [GenreSong]()
var genreSongs = GenreSong()
}
class GenreSong {
var songTitle: String = ""
var path: String = ""
}
这是我的代码:
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
let genreModel = GenreModel()
if(elementName == "genre"){
if let id = attributeDict["title"] {
genreModel.title = id
}
}
if(elementName == "track")
{
let genreSong = GenreSong()
for string in attributeDict {
let strvalue = string.value as NSString
switch string.key {
case "title":
genreSong.songTitle = strvalue as String
break
case "path":
genreSong.path = strvalue as String
break
default:
break
}
}
genreModel.genreSongsArray.append(genreSong)
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
}
我的问题是,当我给出时,它只是解析而不是解析曲目细节。如何将流派标题和歌曲详细信息保存在一个自定义数组中?"elementName == genre"
genre title
谁能就此向我提出建议?谢谢!
答:
0赞
zisoft
9/20/2018
#1
你需要重新考虑你的解析策略。
每当新元素启动时,都会触发 XMLParser。因此,第一次出现是在“流派”元素上。didStartElement
接下来的两个元素是“track”,因此解析器会再次为每个元素触发。didStartElement
跟踪层次结构是您的责任,因此您需要将当前元素存储在变量中并处理子元素。
因此,每当您检索一个新元素时,您都必须检查它是什么元素以及您期望进一步使用的子元素。这完全取决于您的XML文档的结构,因此没有可以为您提供的多合一解决方案。didStartElement
...
var genre = ""
var tracks = [String]()
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
if(elementName == "genre") {
// new genre
tracks = []
if let id = attributeDict["title"] {
genre = id
}
}
if(elementName == "track") {
// new subElement track, add it to the tracks array here
}
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
if(elementName == "genre") {
// genre complete with all tracks, process it
}
}
评论
0赞
Anand Gautam
9/20/2018
感谢您的建议@zisoft,我没有任何跟踪层次结构的想法。我无法在此处使用开始元素流派获取曲目详细信息。
0赞
Anand Gautam
9/20/2018
而且我的XML数据是动态的,一个标题可以有多个轨道。
0赞
zisoft
9/20/2018
@AnandGautam 我添加了一些伪代码。希望你明白。
0赞
Anand Gautam
9/20/2018
感谢您的回答,但是我们何时以这种方式进行解析。当我在 didStartElement 中附加我的全局自定义数组时,对于数组的 0 索引,我只能保存标题,而对于第一个索引,我只能保存曲目详细信息。但是我想将这两个数据保存到数组的 0 索引中。
0赞
Anand Gautam
9/20/2018
我没有为标题和曲目详细信息创建单独的单独数组。
评论
XMLParserDelegate
let genreModel = GenreModel()