如何在 Swift3 iOS 中进行 XML 解析?

How to do XML Parsing in Swift3 iOS?

提问人:Anand Gautam 提问时间:9/20/2018 最后编辑:Anand Gautam 更新时间:11/23/2018 访问量:605

问:

我正在尝试对以下文件进行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

谁能就此向我提出建议?谢谢!

iOS Swift XML NSMutableArray NSXML解析器

评论

0赞 OOPer 9/20/2018
你在什么班级中实施?您需要将结果保留在类中(请参阅您的,它是一个局部变量,一旦方法完成,就永远无法再次访问)。XMLParserDelegatelet genreModel = GenreModel()
0赞 Anand Gautam 9/20/2018
我在我的第一个 VC 中使用 XMLParserDelegate,在那里我显示了 Genre 标题列表。是的,我明白你在告诉我什么。但是我已经全局创建了我的自定义数组,因此可以使用该数组获取标题和流派歌曲的详细信息。
0赞 Anand Gautam 9/20/2018
问题是解析它并将标题和流派歌曲详细信息保存在我的自定义数组索引中。
0赞 OOPer 9/20/2018
我真的明白我说的话了,你应该展示更多的代码。
0赞 Anand Gautam 9/20/2018
在全球范围内,我已经声明了“var genreDataSource = [GenreModel]()”,并尝试解析这两个数据并附加到其中。

答:

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
我没有为标题和曲目详细信息创建单独的单独数组。