如何在OSX上解析Swift 6.1中的XML字符串?

问题描述:

我是新来的Swift,我试图创建一个OSX终端应用程序来解析一个XML文件。我已经将它读入一个字符串中,但无法弄清楚如何将它解析为一个结构,然后我可以导航并从中提取数据。看起来NSXMLDocument似乎需要一个URL,而NSXMLParser需要一个委托,但我最初的尝试无法让他们工作。如何在OSX上解析Swift 6.1中的XML字符串?

这里是我到目前为止有:

import Foundation 
import Cocoa 

let path = "//Users/<path>/someFile.xml" 

var err: NSError? 
let content = String.stringWithContentsOfFile(path, encoding: NSUTF8StringEncoding, error: &err) 

的XML文件的结构是这样的:

<?xml version="1.0" encoding="UTF-8"?> 
<Data> 
    <Documents> 
    <List> 
     <Document name="name1" type="TYPE1" date="some string"> 
     <Items> 
      <Item name="item1" dataType="DATATYPE1" version="1"> 
      <Item name="item2" dataType="DATATYPE9" version="4"> 
     </Items> 
     </Document> 
     <Document name="name2" type="TYPE4" date="some string"> 
     ... 
    </List> 
    </Documents> 
</Data> 

你的帮助是非常赞赏。

解析XML文档并不是那么简单,不能用代码中的单行代码完成。

要与NSXMLParser解析它,你需要一个实现NSXMLParserDelegate协议的自定义类,像这样:

class myXMLParser: NSObject, NSXMLParserDelegate { 
    ... 

    func parseFile(filename: String) { 
     let url = NSBundle.mainBundle().URLForResource(filename, withExtension: "xml") 

     if let parser = NSXMLParser(contentsOfURL: url) { 
      parser.delegate = self 
      parser.parse() 
     } 
    } 


    func parserDidStartDocument(parser: NSXMLParser!) { 
     ... 
    } 

    func parserDidEndDocument(parser: NSXMLParser!) { 
     ... 
    } 

    func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: [NSObject : AnyObject]!) { 
     ... 
    } 

    func parser(parser: NSXMLParser!, foundCharacters string: String!) { 
     ... 
    } 

    func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!) { 
     ... 
    } 

} 

所以每当你检索新的元素与didStartElement你要检查它是什么元素,什么孩子元素你期望更进一步。这一切都取决于你的XML文档的结构,所以在一个解决方案中你可能不会提供所有的解决方案。

NSXMLDocument使用看起来像:

let fm = NSFileManager.defaultManager() 
var err : NSError? 
let userDirectory = fm.URLForDirectory(.UserDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false, error: &err) 
if err != nil { 
    // ... 
} 

if let path = userDirectory?.URLByAppendingPathComponent("someFile.xml") { 
    NSXMLDocument(contentsOfURL: configURL, options: 0, error: &err) 
    if err != nil { 
    // ... 
    } 

    if let rootNode = config?.rootElement() { 
    // ... 
    } 
}