我正在尝试解析http://apps.wku.edu/iwku/maps/buildings/data/SouthCampus-Buildings.xml
上的XML在Swift Playground中使用以下代码
import UIKit
var str = "Hello, playground"
class Parse: NSObject, NSXMLParserDelegate{
func beginParse(){
let url = NSURL(string: "http://apps.wku.edu/iwku/maps/buildings/data/SouthCampus-Buildings.xml")
var xml = NSXMLParser(contentsOfURL: url)
xml?.delegate = self
xml?.parse()
}
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: NSDictionary!) {
println("Element's name is \(elementName)")
println("Element's attributes are \(attributeDict)")
}
}
var instance = Parse()
instance.beginParse()
不幸的是我在控制台中的输出如下所示:
为什么我的attributeDict似乎是空的,如何访问与这些元素相关的值?
答案 0 :(得分:5)
使用NSXMLParser
解析XML文件并不像您期望的那样容易。您必须实现NSXMLParserDelegate
协议中的多个方法来捕获事件。您已经为didStartElement
执行了此操作,它为(对我而言)提供了预期结果:元素名称及其属性(上面链接的XML文件中没有属性)。
到目前为止,一切正常......
既然您已经抓住了元素的开头,那么您必须注意进一步处理:
协议方法foundCharacters
在元素的开头和结尾之间触发。也许好几次。您必须实现该方法并将找到的字符附加到字符串变量,具体取决于元素的名称。
当didEndElement
被触发时,您的字符串变量将完全填充元素的内容
如果XML文件具有深层次结构,那么事情可能会越来越复杂。
很抱歉这个广泛的答案,但遗憾的是,没有获取该XML文件并使用NSXMLParser
给我一个深度嵌套的字典方法。
答案 1 :(得分:2)
属性是在标记内的属性。例如,如果您的标签看起来像:
<building id="foo">
在这种情况下,id
将位于attributeDict
。
但是,在这种情况下,您的XML看起来像:
<buildings>
<building>
<name>Commonwealth School</name>
<building_code>SC</building_code>
<latitude>36.965075</latitude>
<longitude>-86.467144</longitude>
<image_url>
http://www.wku.edu/marketingandcommunications/images/wkucuptallrb.jpg
</image_url>
<description/>
<handicap_accessible/>
<address/>
<url/>
<aliases>
<alias>South Campus</alias>
<alias>Community College</alias>
</aliases>
<email/>
<phone/>
<organizations/>
</building>
...
因此,考虑<name>Commonwealth School</name>
,这将导致对
didStartElement
,foundCharacters
(可多次调用)和didEndElement
。 答案 2 :(得分:0)
我制作了一个简单的示例应用,它从此Feed中读取XML - jokes-n-fun RSS feed并在表格视图中显示检索到的数据,这里是链接:jokes-n-fun@github,共享源代码可以用作制作类似iOS应用程序的参考。要回答您的问题,您可以参考AtomParser.swift class中编写的代码,复制粘贴在此处:
import UIKit
// MARK: - declaring typealias to store closures with dictionary
typealias StartTagRuleBlock = (NSMutableDictionary, [NSObject : AnyObject]) -> Void
typealias EndTagRuleBlock = (NSMutableDictionary, String) -> Void
// MARK: - Protocol declared
protocol CompletionObserver {
func dataSourcePopulated(dataSourceArray : NSArray) -> ()
}
class AtomParser : NSObject, NSXMLParserDelegate {
// MARK: - Properties
let triggerTag : String
let parseUrl : String
var dataArray : NSMutableArray = NSMutableArray()
var collectedCharacters : NSMutableString?
var recordDict : NSMutableDictionary?
var parser : NSXMLParser?
var startElementRuleMappingDict:[String: StartTagRuleBlock] = [String: StartTagRuleBlock]()
var endElementRuleMappingDict:[String: EndTagRuleBlock] = [String: EndTagRuleBlock]()
var endTagRules : NSDictionary?
var completionObserver : CompletionObserver?
// MARK: - Designated initializer
/**
Designated initializer to initialize AtomParser class.
:param: triggerTag Tag which distinguishes each record.
:param: parseUrl URL supplying xml to be parser.
:returns: Void.
*/
init(triggerTag : String, parseUrl : String) {
self.triggerTag = triggerTag
self.parseUrl = parseUrl
}
// MARK: - Initiate parsing
func startParsing () {
let url = NSURL(string: self.parseUrl)
parser = NSXMLParser(contentsOfURL: url)
parser?.delegate = self
parser?.parse()
}
// MARK: - Parser delegates
func parserDidStartDocument(parser: NSXMLParser!) {
self.dataArray.removeAllObjects()
}
func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) {
if elementName == triggerTag {
recordDict = NSMutableDictionary(capacity: 1)
}
else if recordDict != nil {
if let startTagMappingElement = self.startElementRuleMappingDict[elementName] {
startTagMappingElement(recordDict!,attributeDict)
}
collectedCharacters = NSMutableString(string: "")
}
else {
// no need to handle these tags
}
}
func parser(parser: NSXMLParser!, foundCharacters string: String!) {
collectedCharacters?.appendString(string)
}
func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) {
if let mutableDictionary = recordDict {
if elementName == triggerTag {
dataArray.addObject(recordDict!)
}
else if recordDict != nil {
if let endTagMappingElement = self.endElementRuleMappingDict[elementName] {
endTagMappingElement(recordDict!,"\(String(collectedCharacters!))")
}
}
else {
// no need to handle these tags
}
}
}
func parserDidEndDocument(parser: NSXMLParser) {
let arrayToReturn = NSArray(array: dataArray)
completionObserver?.dataSourcePopulated(arrayToReturn)
}
}