lucas_turci
lucas_turci

Reputation: 322

NSXMLparser parse() not working

I am working on a game, in which there are patterns of obstacles described in a XML file, so I implemented this class in my swift file:

class PatternsParser: NSObject, NSXMLParserDelegate
{
var myParser: NSXMLParser!
var arrayOfPatterns = [Element]()
var currentId = 0

init(url: NSURL)
{
    myParser = NSXMLParser(contentsOfURL: url)
    println(myParser.parserError?)
    super.init()
    myParser.delegate = self
    if myParser.parse()
    {
        println("Was able to parse")
    }
}

func parser(parser: NSXMLParser!, parseErrorOccurred parseError: NSError!) {
    println("error = \(parseError)")
}

On my other swift file I wrote this:

// this is just a function to return the document path I use to create the NSURL
func getXMLPath(pathName path:String) -> String? 
{
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0] as String
    let filePath: String? = documentsDirectory?.stringByAppendingPathComponent(path)
    return filePath
}

    let buffer: NSURL! = NSURL(fileURLWithPath: getXMLPath(pathName:"patterns.xml"))
    var patternParser = PatternsParser(url:buffer)

However, what I get is that myParser.parse() always returns no, and even so the parserError property doesn't tell me anything (is nil). I also tried implementing the methods parseErrorOcurred and validationErrorOcurred, but nothing...

If you want to take a look at the patterns.xml file, here it is:

<?xml version="1.0"?>
<game>  
    <pattern id="0" difficulty="0" width="800">
        <coinArea>
            <rect x="100" y="470,5" width="12" height="5"/>
        </coinArea>
    </pattern>

    <pattern id="1" difficulty="1" width="600">
        <coinArea>
            <rect x="100" edge="up" width="8"/>
        </coinArea>
        <wall orientation="vertical" texture="wallText">
            <rect x="300" edge="down"/>
        </wall>
    </pattern>

    <pattern id="2" difficulty="1" width="750">
        <wall orientation="vertical" texture="wallText">
            <rect edge="down" x="25"/>
        </wall>
        <wall orientation="vertical" texture="wallText">
            <rect edge="up" x="60"/>
        </wall>
        <electricLine orientation="horizontal">
            <rect edge="up" x="0"/>
        </electricLine>
    </pattern>
</game>

Upvotes: 0

Views: 1583

Answers (2)

lucas_turci
lucas_turci

Reputation: 322

My Solution

My problem really was the URL, so instead of using

func getXMLPath(pathName path:String) -> String? 
{
    let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
    let documentsDirectory = paths[0] as String
    let filePath: String? = documentsDirectory?.stringByAppendingPathComponent(path)
    return filePath
}

let buffer: NSURL! = NSURL(fileURLWithPath: getXMLPath(pathName:"patterns.xml"))
var patternParser = PatternsParser(url:buffer)

I replaced it with:

let bundle = NSBundle.mainBundle()
let url: NSURL! = bundle.URLForResource("patterns", withExtension: "xml")
var patternParser = PatternsParser(url: url)

Upvotes: 0

Rob
Rob

Reputation: 437802

  1. The XML in your original question was not valid. You can run the xmllint command from the Mac OS X Terminal and that would point out that (a) you were missing a root element to wrap your individual pattern tags; and (b) your electricLine open tag was mistyped. It should be:

    <?xml version="1.0"?>
    <patterns>
        <pattern id="0" difficulty="0" width="800">
            <coinArea>
                <rect x="100" y="470,5" width="12" height="5"/>
            </coinArea>
        </pattern>
    
        <pattern id="1" difficulty="1" width="600">
            <coinArea>
                <rect x="100" edge="up" width="8"/>
            </coinArea>
            <wall orientation="vertical" texture="wallText">
                <rect x="300" edge="down"/>
            </wall>
        </pattern>
    
        <pattern id="2" difficulty="1" width="750">
            <wall orientation="vertical" texture="wallText">
                <rect edge="down" x="25"/>
            </wall>
            <wall orientation="vertical" texture="wallText">
                <rect edge="up" x="60"/>
            </wall>
            <electricLine orientation="horizontal">
                <rect edge="up" x="0"/>
            </electricLine>
        </pattern>
    </patterns>
    

    You've since fixed this in your revised question. That new XML a looks fine.

  2. If you implemented the parseErrorOccurred method of the NSXMLParserDelegate protocol, it would have pointed out these issues.

    I ran your original, incorrect XML with the following parseErrorOccurred method:

    func parser(parser: NSXMLParser!, parseErrorOccurred parseError: NSError!) {
        println("error = \(parseError)")
    }
    

    And it correctly reported:

    error = Error Domain=NSXMLParserErrorDomain Code=5 "The operation couldn’t be completed. (NSXMLParserErrorDomain error 5.)" UserInfo=0x60000006eb40 {NSXMLParserErrorColumn=1, NSXMLParserErrorLineNumber=9, NSXMLParserErrorMessage=Extra content at the end of the document }

  3. If your delegate methods aren't getting called, make sure the file exists in the Document folder:

    let path = getXMLPath(pathName:"patterns.xml")!
    if !NSFileManager.defaultManager().fileExistsAtPath(path) {
        println("file NOT found at \(path)")
    } else {
        println("file found at \(path)")
    }
    let fileURL: NSURL! = NSURL(fileURLWithPath: path)
    var patternParser = PatternsParser(url: fileURL)
    

Upvotes: 1

Related Questions