在XCode

时间:2018-04-14 20:05:27

标签: swift xml xcode parsing xml-parsing

我需要解析本地XML文件。我想我拥有显示代码所需的一切,问题是它的实际解析。我有一个先前项目的代码,它解析了一个xml文件的链接,但是这是一个名为" Recipes.xml"

的本地文件

需要转移的是parseFeed()功能,我已经尝试了几种方法将其解析为本地文件,但仍未找到解决方案。

XMLParser类:

struct Recipe {
let title: String
let calories: String
let ingredients: String
}

class FeedParser: NSObject, XMLParserDelegate {
private var rssItems: [Recipe] = []
private var currentElement = ""
private var currentTitle: String = "" {
    didSet {
        currentTitle =
            currentTitle.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
}
private var currentCalories: String = "" {
    didSet {
        currentCalories =
            currentCalories.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
    }
}
private var currentIngredients: String = "" {
    didSet {
        currentIngredients =
            currentIngredients.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)

    }
}

private var parserCompletionHandler: (([Recipe]) -> Void)?

func parseFeed(url: String, completionHandler: (([Recipe]) -> 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 our 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 == "dish" {
        currentTitle = ""
        currentCalories = ""
        currentIngredients = ""
    }
}

func parser(_ parser: XMLParser, foundCharacters string: String) {
    switch currentElement {
    case "title": currentTitle += string
    case "calories": currentCalories += string
    case "ingredients": currentIngredients += string
    default: break
    }
}

func parser(_ parser: XMLParser, didEndElement elementName: String,
            namespaceURI: String?, qualifiedName qName: String?) {
    if elementName == "item" {
        let rssItem = Recipe(title: currentTitle, 
                              calories: currentCalories, ingredients: currentIngredients)
        self.rssItems.append(rssItem)
        print(rssItem)
    }
}

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

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

这是接收并显示xml文件的表视图。这里,fetchData()函数调用parseFeed()函数来返回xml数据。 " Recipes.xml" fetchData()中的字符串将是一个链接。我知道用本地文件名替换它不会起作用,它只是一个占位符。

RecipeTableViewController:

class RecipeTableViewController: UITableViewController, XMLParserDelegate {

@IBOutlet var myTableView: UITableView!

private var recipeItems: [Recipe]?

override func viewDidLoad() {
    super.viewDidLoad()

    myTableView.dataSource = self
    myTableView.delegate = self

    fetchData()

   /* if let path =  Bundle.main.url(forResource: "Recipes", withExtension: "xml") {
        if let parser = XMLParser(contentsOf: path) {
            parser.delegate = self
            parser.parse()
        }
    } */
}

private func fetchData() {
    let feedParser = FeedParser()
    feedParser.parseFeed(url:
    "Recipes.xml") { (recipeItems) in
        self.recipeItems = recipeItems

        OperationQueue.main.addOperation {
            self.tableView.reloadSections(IndexSet(integer: 0), with: .left)
        }
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

// Table View Delegates

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    guard let recipeItems = recipeItems else {
        return 0
    }

    print(recipeItems.count)
    return recipeItems.count
}

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

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

    return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let Storyboard = UIStoryboard(name: "Main", bundle: nil)
    let resultsVC = Storyboard.instantiateViewController(withIdentifier: "ResultsViewController") as! ResultsViewController

    // Information to be passed to ResultsViewController

    resultsVC.getTitle = recipeItems![indexPath.row].title
    resultsVC.getIngredients = recipeItems![indexPath.row].ingredients

    // Push to next view
    self.navigationController?.pushViewController(resultsVC, animated: true)

}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 100
}

}

来自print(recipeItems.count)的结果返回0

0 个答案:

没有答案