使用 NSXMLParser 在 Swift 中解析 XML

Parsing XML in Swift with NSXMLParser

我要解析以下 XML 结构:

<plist version="1.0">
        <dict>
            <key>
                PALABRA
            </key>
            <array>
                <string>
                    CATEGORY
                </string>
                <string>
                    WORD
                </string>
            </array>
        </dict>
</plist> 

我正在使用 NSXMLParser 以这种方式解析 XML:

var posts = NSMutableArray()
var parser = NSXMLParser()
var elements = NSMutableDictionary()
var element = NSString()
var CATEGORY = NSMutableString()
var WORD = NSMutableString()

func parseXML() {
        posts = []
        parser = NSXMLParser(contentsOfURL:(NSURL(string:"http://www.serverbpw.com/cm/2016-1/hangman.php"))!)!
        parser.delegate = self
        parser.parse()         
}

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

    element = elementName
    if (elementName as NSString).isEqualToString("array") {
        elements = NSMutableDictionary()
        elements = [:]
        categoria = NSMutableString()
        categoria = ""
    }

    if (elementName as NSString).isEqualToString("string") {
        palabra = NSMutableString()
        palabra = ""
    }
}

func parser(parser: NSXMLParser, foundCharacters string: String) {

    if element.isEqualToString("string") {
        categoria.appendString(string)
    }

    if element.isEqualToString("string") {
        palabra.appendString(string)
    }
}

func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    if (elementName as NSString).isEqualToString("array") {
        if !categoria.isEqual(nil) {
            elements.setObject(categoria, forKey: "CATEGORIA")
        }
        if !palabra.isEqual(nil) {
            elements.setObject(palabra, forKey: "PALABRA")
        }            
        posts.addObject(elements)
    }
}

我从服务器获取的CATEGORY值是CATEGORY的内容,也是WORD的内容,而WORD的值只是WORD的内容。 我知道这不是解析 XML 的正确方法。问题是我不知道如何获取 CATEGORY 和 WORD 元素,因为它们具有相同的 ID ("String")。获取此信息的正确方法是什么?

服务器地址为:http://www.serverbpw.com/cm/2016-1/hangman.php

提前致谢!

这是一个 plist,因此您可以只使用 NSDictionary(contentsOfFile:)。

if let dict = NSDictionary(contentsOfFile: filePath) {
  let array = dict["PALABRA"] as? [String]
  let category = array?[0]
  let word = array?[1]
}

如果您没有文件形式的数据,请使用此方法

if let dict = try NSPropertyListSerialization.propertyListWithData(xmlData, options: .Immutable, format: nil) as? NSDictionary {
    //......
}

如果您要自己解析它,诀窍是您有两次出现 <string>,您必须以某种方式区分它们。您可以拥有自己的计数器来跟踪哪个是哪个:

var posts: [[String: String]]!
var element: String!
var categoria: String?
var palabra: String?
var stringValue: String?
var counter: Int!

func parseXML(url: NSURL) {
    posts = [[:]]
    let parser = NSXMLParser(contentsOfURL: url)!
    parser.delegate = self
    parser.parse()
}

func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
    element = elementName
    if elementName == "array" {
        categoria = nil
        palabra = nil
        counter = 0
    }
}

func parser(parser: NSXMLParser, foundCharacters string: String) {
    if element == "string" {
        if stringValue == nil {
            stringValue = string
        } else {
            stringValue! += string
        }
    }
}

func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
    if elementName == "string" {
        stringValue = stringValue?.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
        if counter == 0 {
            categoria = stringValue
        } else if counter == 1 {
            palabra = stringValue
        }
        stringValue = nil
        counter!++
    }

    if elementName == "array" {
        var element = [String: String]()
        if categoria != nil {
            element["CATEGORIA"] = categoria
        }
        if palabra != nil {
            element["PALABRA"] = palabra
        }            
        posts.append(element)
    }
}

但我同意 cezheng 的观点,这似乎是由 NSDictionary plist 实现的,因此,您应该只使用 NSDictionary(contentsOfFile) 或您有什么。如果这真的是您正在构建的 XML,我会建议您使用不同的格式,例如:

<posts>
    <post>
        <category>
            CATEGORY
        </category>
        <word>
            WORD
        </word>
    </post>
</posts> 

那么你就可以更容易地解析它,而不需要 counter.

的愚蠢行为