1

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.

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.