微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在Swift中从URL解析XML

我是一个全新的解析,无法找到任何没有过时的教程,也没有提出更多的问题.我有一个简单的xml文件url我试图解析. xml非常简单:
<xml>
    <record>
        <EmpName>A Employee</EmpName>
        <EmpPhone>111-222-3333</EmpPhone>
        <EmpEmail>a@employee.com</EmpEmail>
        <EmpAddress>12345 Fake Street</EmpAddress>
        <EmpAddress1>MyTown,Mystate ZIP</EmpAddress1>
    </record>
</xml>

并且只想将其保存为NSDictionary(标记为键和数据作为值).到目前为止,我能够成功完成的是在控制台中打印xml字符串:

let url = NSURL(string: "http://www.urlexample.com/file.xml")

let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data,response,error) in
        println(Nsstring(data: data,encoding: NSUTF8StringEncoding))
}
print(task)
task.resume()

我已经完成了我发现的任何在线教程,这些教程要么过时,要么过于复杂.任何帮助表示赞赏.

过程很简单:

>创建XMLParser对象,并将数据传递给它.
>指定该解析器的委托.
>启动解析.

所以,在Swift 3/4中,它看起来像:

let task = URLSession.shared.dataTask(with: url) { data,error in
    guard let data = data,error == nil else {
        print(error ?? "UnkNown error")
        return
    }

    let parser = XMLParser(data: data)
    parser.delegate = self
    if parser.parse() {
        print(self.results ?? "No results")
    }
}
task.resume()

问题是如何实现XMLParserDelegate方法.三个关键方法是didStartElement(准备接收字符的地方),foundCharacters(处理解析的实际值)和didEndElement(保存结果的地方).

您询问了如何解析单个记录(即单个字典),但我将向您展示解析其中一系列的更一般模式,这是XML的一种常见情况.如果你不需要一个值数组(或者只是抓住第一个值),你显然可以看到如何简化这个.

// a few constants that identify what element names we're looking for inside the XML

// a few constants that identify what element names we're looking for inside the XML

let recordKey = "record"
let dictionaryKeys = Set<String>(["EmpName","EmpPhone","EmpEmail","EmpAddress","EmpAddress1"])

// a few variables to hold the results as we parse the XML

var results: [[String: String]]?         // the whole array of dictionaries
var currentDictionary: [String: String]? // the current dictionary
var currentValue: String?                // the current value for one of the keys in the dictionary

extension ViewController: XMLParserDelegate {

    // initialize results structure

    func parserDidStartDocument(_ parser: XMLParser) {
        results = []
    }

    // start element
    //
    // - If we're starting a "record" create the dictionary that will hold the results
    // - If we're starting one of our dictionary keys,initialize `currentValue` (otherwise leave `nil`)

    func parser(_ parser: XMLParser,didStartElement elementName: String,namespaceURI: String?,qualifiedname qName: String?,attributes attributeDict: [String : String]) {
        if elementName == recordKey {
            currentDictionary = [:]
        } else if dictionaryKeys.contains(elementName) {
            currentValue = ""
        }
    }

    // found characters
    //
    // - If this is an element we care about,append those characters.
    // - If `currentValue` still `nil`,then do nothing.

    func parser(_ parser: XMLParser,foundCharacters string: String) {
        currentValue? += string
    }

    // end element
    //
    // - If we're at the end of the whole dictionary,then save that dictionary in our array
    // - If we're at the end of an element that belongs in the dictionary,then save that value in the dictionary

    func parser(_ parser: XMLParser,didEndElement elementName: String,qualifiedname qName: String?) {
        if elementName == recordKey {
            results!.append(currentDictionary!)
            currentDictionary = nil
        } else if dictionaryKeys.contains(elementName) {
            currentDictionary![elementName] = currentValue
            currentValue = nil
        }
    }

    // Just in case,if there's an error,report it. (We don't want to fly blind here.)

    func parser(_ parser: XMLParser,parseErrorOccurred parseError: Error) {
        print(parseError)

        currentValue = nil
        currentDictionary = nil
        results = nil
    }

}

对于Swift 2的再现,请参阅previous revision of this answer.

原文地址:https://www.jb51.cc/swift/319209.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐