【问题标题】:How to do XML Parsing in Swift3 iOS?如何在 Swift3 iOS 中进行 XML 解析?
【发布时间】:2019-02-24 09:31:15
【问题描述】:

我正在尝试对以下文件进行 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 用于显示此内容的详细信息。为此,我在下面创建了两个 Modal 类:

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 而不是解析轨道详细信息。如何将流派标题和歌曲详细信息保存在一个自定义数组中?

有人可以建议我吗?谢谢!

【问题讨论】:

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

标签: ios swift xml-parsing nsmutablearray nsxmlparser


【解决方案1】:

您需要重新考虑您的解析策略。

每当新元素开始时,XMLParser 就会触发 didStartElement。所以第一次出现在“流派”元素上。

接下来的两个元素是“track”,因此解析器再次为每个元素触发 didStartElement

您有责任跟踪层次结构,因此您需要将当前元素存储在变量中并处理子元素。

因此,每当您使用didStartElement 检索新元素时,您必须进一步检查它是什么元素以及您期望的子元素。这一切都取决于您的 XML 文档的结构,因此无法提供一站式解决方案。

...
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
    }
}

【讨论】:

  • 感谢您的建议@zisoft,我不知道跟踪层次结构。我无法在此处使用起始元素流派获取曲目详细信息。
  • 而且我的 XML 数据是动态的,一个标题可以有多个轨道。
  • @AnandGautam 我添加了一些伪代码。希望你能明白。
  • 感谢您的回答,但我们何时会以这种方式解析。当我将我的全局自定义数组附加到 didStartElement 中时,对于数组的 0 索引,我只能保存标题,而对于第一个索引,我只能保存曲目详细信息。但我想将这两个数据都保存到数组的 0 索引中。
  • 我没有为标题和曲目详细信息创建单独的单独数组。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-13
相关资源
最近更新 更多