在Swift中从URL解析XML [英] Parsing XML from URL in Swift

查看:100
本文介绍了在Swift中从URL解析XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是解析的新手,找不到任何过时且未引发更多问题的教程.我正在尝试解析一个简单的xml文件url. xml非常简单:

I am brand new to parsing and cannot find any tutorial that isn't outdated and doesn't raise more questions. I have a simple xml file url I am trying to parse. The xml is very simple:

<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字符串:

And just wanted to save this as an NSDictionary (tags as keys and data as values). So far all I have been able to do successfully is print the xml string in the console with:

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()

我遍历了所有发现的在线教程,这些教程要么过时,要么过于复杂.感谢您的帮助.

I have been through any online tutorials that I've found and are either outdated or much too complicated. Any help is appreciated.

推荐答案

过程很简单:

  1. 创建XMLParser对象,并向其传递数据.
  2. 为该解析器指定delegate.
  3. 启动分析.
  1. Create XMLParser object, passing it the data.
  2. Specify the delegate for that parser.
  3. Initiate the parsing.

因此,在Swift 3/4中,它看起来像:

So, in Swift 3/4, that looks like:

let task = URLSession.shared.dataTask(with: url) { data, response, 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(用于保存结果).

The question is how do you implement the XMLParserDelegate methods. The three critical methods are didStartElement (where you prepare to receive characters), foundCharacters (where you handle the actual values parsed), and didEndElement (where you save you results).

您问过如何解析单个记录(即单个字典),但是我将向您展示一种更通用的模式来解析一系列记录,这在XML中是一种更为普遍的情况.显然,如果您不需要值数组(或仅获取第一个值),则可以看到如何简化此操作.

You asked how to parse a single record (i.e. a single dictionary), but I'll show you a more general pattern for parsing a series of them, which is a far more common situation with XML. You can obviously see how to simplify this if you didn't need an array of values (or just grab the first one).

// 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, namespaceURI: 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再现,请参见此答案的先前版本.

For Swift 2 rendition, see previous revision of this answer.

这篇关于在Swift中从URL解析XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆