TERACytE
TERACytE

Reputation: 7863

How to parse an XML string in Swift 6.1 on OSX?

I'm new to Swift and I'm trying to create an OSX terminal app to parse an xml file. I've got it reading the file in to a string, but cannot figure out how parse it in to a structure I can then navigate and pull data from. It appears that NSXMLDocument seems to want a URL and NSXMLParser needs a delegate, but my initial attempts could not get them to work.

Here's what I've got so far:

import Foundation
import Cocoa

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

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

The structure of the xml file is something like this:

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

Your help is much appreciated.

Upvotes: 1

Views: 6349

Answers (2)

rkusa
rkusa

Reputation: 4902

The NSXMLDocument usage would look like:

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() {
    // ...
  }
}

Upvotes: 2

zisoft
zisoft

Reputation: 23078

Parsing an XML document is not that trivial and cannot be done with a one-liner in code.

To parse it with NSXMLParser you need a custom class that implements the NSXMLParserDelegate protocol, like this:

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!) {
        ...
    }

}

So whenever you retrieve a new element with didStartElement you have to check what element it is and what child elements you expect further. This all depends on the structure of your XML document so there is no all in one solution one can give you.

Upvotes: 2

Related Questions