将XML数据解析为字典数组并在TableView中显示

时间:2018-08-24 08:14:12

标签: arrays swift xml parsing tableview

过去两天,我一直在尝试将我的XML解析数据加载到表中。我已经成功解析了数据并将其显示在控制台中。但是,我无法将数据加载到表中。到目前为止,我已经做了两次单独的尝试。

方法1:直接在视图控制器中解析功能-在控制台中成功显示已解析的数据。请注意,我的tableview函数当前未设置为符合此方法。

方法2:创建一个单独的.swift文件(XMLParse.swift)来解析数据,并创建(regionTableViewViewCell.swift)必要的UILabel元素。 -当前在运行应用程序时在控制台中显示nil。

下面是这三个文件中的代码。非常感谢您能帮助我的文件配置为上述两种方法之一。我现在在xCode中工作只有两个星期,所以我确定我的代码很糟糕。如果有人愿意花时间完善我的代码并告诉我正确的编写方式,我将不胜感激。

主要ViewController和方法1:ParseDataViewController.swift

import Foundation
import UIKit
import Firebase

class ParseDataViewController: UIViewController, UITableViewDelegate, 
XMLParserDelegate, UISearchBarDelegate {

@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var searchBar: UISearchBar!
@IBOutlet weak var countyLabel: UILabel!
@IBOutlet weak var zindexLabel: UILabel!
@IBOutlet weak var tableView: UITableView!

private var regionItems: [RegionItem]?

var searchActive : Bool = false
let county = ""
let recordKey = "region"
let dictionaryKeys = Set<String>(["id","name","zindex"])

// 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



override func viewDidLoad() {
    super .viewDidLoad()

    fetchData()
    print([regionItems])

    searchBar.delegate = self
    self.tableView.dataSource = self
    self.tableView.delegate = self


    let urlString =  "https://www.zillow.com/webservice/GetRegionChildren.htm?<MYZILLOWKEY>&state=ca&childtype=county"
    let url = URL(string: urlString)!

    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 ?? "Unknown error")

            // Search 'results' array for specific county and set the index of the currentDictionary - currently set to "Los Angeles" but would like to be able to change it based on the value from the searchbar
            let currentDictionary = self.results.filter { $0["name"] == "Los Angeles" }
            if currentDictionary.isEmpty {
                print("No results found")
                print(self.county)
            } else {
                let currentValue = currentDictionary[0]
                let zIndex = currentValue["zindex"]
                let county = currentValue["name"]
                print("The median price of a home in \(county!) is $\(zIndex!).")
            }
        }
    }
    task.resume()

}

private func fetchData() {
    let dataParser = DataParser()
    dataParser.parseData(url: "https://www.zillow.com/webservice/GetRegionChildren.htm?<MYZILLOWKEY>&state=ca&childtype=county") { (regionItems) in
        self.regionItems = regionItems
        OperationQueue.main.addOperation {
            self.tableView.reloadSections(IndexSet(integer: 0), with: .left)
        }
    }
}

// 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 parserDidStartDocument(_ parser: XMLParser) {
    results = []
}

func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {

    if elementName == recordKey {

        self.currentDictionary = [String : String]()

    } else if dictionaryKeys.contains(elementName) {

        self.currentValue = String()

    }
}

// 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) {

    self.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 == self.recordKey {

        self.results.append(self.currentDictionary)
        self.currentDictionary = nil

    } else if dictionaryKeys.contains(elementName) {

        self.currentDictionary[elementName] = currentValue
        self.currentValue = nil

    }

}

// If there's an error, report it.

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

    self.currentValue = nil
    self.currentDictionary = nil

}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    let county = searchBar.text
    countyLabel.text = searchBar.text
    print("searchText \(county!)")
}

}


// Attempted to configure the below to work with method 2

extension ParseDataViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 150
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard let regionItems = regionItems else {
        return 0
    }
    return regionItems.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! RegionTableViewCell

    if let item = regionItems?[indexPath.item] {
        cell.item = item
    }

    return cell
}
}

方法2:XMLParse.swift和RegionTableViewCell.swift

struct RegionItem {
var id: String
var name: String
var zindex: String
}

class DataParser: NSObject, XMLParserDelegate {

private var regionItem: [RegionItem] = []
private var currentElement = ""
private var currentId: String = "" {
    didSet {
        currentId = currentId.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
}
private var currentName: String = "" {
    didSet {
        currentName = currentName.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
}
}
private var currentZindex: String = ""
{
    didSet {
        currentZindex = currentZindex.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
}
private var parserCompletionHandler: (([RegionItem]) -> Void)?

func parseData(url: String, completionHandler: (([RegionItem]) -> Void)?)
{
    self.parserCompletionHandler = completionHandler

    let request = URLRequest(url: URL(string: url)!)
    let urlSession = URLSession.shared
    let task = urlSession.dataTask(with: request) { (data, response, error) in
        guard let data = data else {
            if let error = error {
                print(error.localizedDescription)
            }
            return
        }

        // Parse XML Data

        let parser = XMLParser(data: data)
        parser.delegate = self
        parser.parse()

    }

    task.resume()
}

// MARK:  - XML Parser Delegate

func parser(_ parser: XMLParser, didStartElement elementName: String, 
namespaceURI: String?, qualifiedName qName: String?, attributes 
attributeDict: [String : String] = [:]) {

    currentElement = elementName
    if currentElement == "region" {
        currentId = ""
        currentName = ""
        currentZindex = ""
    }
}

func parser(_ parser: XMLParser, foundCharacters string: String) {
    switch currentElement {
        case "id": currentId += string
        case "name": currentName += string
        case "zindex": currentZindex += string
        default: break
    }
}

func parser(_ parser: XMLParser, didEndElement elementName: String, 
namespaceURI: String?, qualifiedName qName: String?) {
    if currentElement == "region" {
        let regionItem = RegionItem(id: currentId, name: currentName, 
zindex: currentZindex)
        self.regionItem.append(regionItem)
    }
}

func parserDidEndDocument(_ parser: XMLParser) {
    parserCompletionHandler?(regionItem)
}

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

}

regionTableViewCell.swift

class RegionTableViewCell: UITableViewCell {

@IBOutlet weak var idLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var zindexLabel: UILabel!


var item: RegionItem! {
    didSet {
        idLabel.text = item.id
        nameLabel.text = item.name
        zindexLabel.text = item.zindex
    }
}

}

来自控制台的XML数据:

some([[[“ id”:“ 9”],[“ id”:“ 3101”,“ name”:“洛杉矶”,“ zindex”:“ 485600”],[“ id”:“ 2841 “,” name“:” San Diego“,” zindex“:” 463800“],[” id“:” 1286“,” name“:” Orange“,” zindex“:” 627200“],[” id“ :“ 2832”,“ name”:“河滨”,“ zindex”:“ 298200”],[“ id”:“ 3250”,“ name”:“圣贝纳迪诺”,“ zindex”:“ 257400”],[ “ id”:“ 3136”,“ name”:“ Santa Clara”,“ zindex”:“ 830300”],[“ id”:“ 1510”,“ name”:“ Alameda”,“ zindex”:“ 614500” ],[“ id”:“ 3017”,“ name”:“萨克拉曼多”,“ zindex”:“ 283200”],[“ id”:“ 3159”,“ name”:“ Contra Costa”,“ zindex”: “ 469500”],[“ id”:“ 1018”,“名称”:“ Fresno”,“ zindex”:“ 184900”],[“ id”:“ 204”,“名称”:“ Kern”,“ zindex “:” 166800“],[” id“:” 3227“,” name“:”旧金山“,” zindex“:” 983200“],[” id“:” 2061“,” name“:” Ventura“ ,“ zindex”:“ 499400”],[“ id”:“ 2842”,“名称”:“ San Mateo”,“ zindex”:“ 882700”],[“ id”:“ 3134”,“名称”: “圣华金”,“ zindex”:“ 240500”],[“ id”:“ 3033”,“名称”:“ Stanislaus”,“ zindex”:“ 215200”],[“ id”:“ 1396”,“ name“:” Sonoma“,” zindex“:” 485000“],[” id“:” 1442“,” name“:” Tulare“,” zindex“:” 157900“],[” id“:” 3229“,” name“:” Santa Barbara“,” zindex“:” 526500“],[” id “:” 2444“,” name“:”蒙特雷“,” zindex“:” 420400“],[” id“:” 1395“,” name“:” Solano“,” zindex“:” 314800“],[ “ id”:“ 1325”,“ name”:“ Placer”,“ zindex”:“ 393500”],[“ id”:“ 3261”,“ name”:“ San Luis Obispo”,“ zindex”:“ 487400” “],[” id“:” 3025“,”名称“:” Santa Cruz“,” zindex“:” 627100“],[” id“:” 1196“,”名称“:” Merced“],[” id“:” 625“,” name“:” Marin“,” zindex“:” 897500“],[” id“:” 418“,” name“:” Butte“,” zindex“:” 222500“], [“ id”:“ 340”,“名称”:“ Yolo”,“ zindex”:“ 335800”],[“ id”:“ 2691”,“名称”:“ El Dorado”,“ zindex”:“ 353900” “],[” id“:” 1380“,” name“:” Shasta“,” zindex“:” 206900“],[” id“:” 2354“,” name“:”帝国“,” zindex“: “ 155500”],[“ id”:“ 1156”,“名称”:“ Madera”,“ zindex”:“ 187300”],[“ id”:“ 580”,“ name”:“国王”,“ zindex “:” 155100“],[” id“:” 255“,” name“:”纳帕“,” zindex“:” 490800“],[” id“:” 2351“,” name“:”洪堡“, “ zindex”:“ 245400”],[“ id”:“ 1261”,“ name”:“内华达州”,“ zinde x“:” 372100“],[” id“:” 1415“,” name“:” Sutter“,” zindex“:” 210500“],[” id“:” 2796“,” name“:” Mendocino“ ,“ zindex”:“ 323700”],[“ id”:“ 346”,“ name”:“ Yuba”,“ zindex”:“ 181200”],[“ id”:“ 217”,“ name”:“湖”,“ zindex”:“ 174800”],[“ id”:“ 1426”,“名称”:“ Tehama”,“ zindex”:“ 144300”],[“ id”:“ 3020”,“名称” :“ San Benito”,“ zindex”:“ 410100”],[“ id”:“ 2584”,“ name”:“ Tuolumne”,“ zindex”:“ 205100”],[“ id”:“ 2643”, “名称”:“ Calaveras”,“ zindex”:“ 248300”],[“ id”:“ 2548”,“ name”:“ Siskiyou”,“ zindex”:“ 167600”],[“ id”:“ 829 “,” name“:” Amador“],[” id“:” 1143“,” name“:” Lassen“,” zindex“:” 117300“],[” id“:” 524“,” name“: “” Glenn“],[” id“:” 2678“,”名称“:” Del Norte“],[” id“:” 952“,”名称“:” Colusa“,” zindex“:” 182100“], [“ id”:“ 1329”,“ name”:“ Plumas”],[“ id”:“ 188”,“ name”:“ Inyo”,“ zindex”:“ 285700”],[“ id”:“ 2403“,” name“:” Mariposa“,” zindex“:” 241800“],[” id“:” 253“,” name“:” Mono“],[” id“:” 2056“,” name“ :“ Trinity”],[“ id”:“ 647”,“ name”:“ Modoc”],[“ id”:“ 1391”,“ name”:“ Sierra”,“ zindex”: “ 134800”],[“ id”:“ 828”,“ name”:“ Alpine”]])

0 个答案:

没有答案