Thursday, 15 March 2012

ios - XML Parsing error in Swift -



ios - XML Parsing error in Swift -

i'm trying "modernize" 1 of our apps takes xml info noaa. existing app, using "simple xml nsdictionary converter" (http://troybrant.net/blog/2010/09/simple-xml-to-nsdictionary-converter/) works champ. because works , because i'm aiming rebuilt app converted swift much possible, attempted faithful conversion of xml nsdictionary code. unfortunately, i'm getting nsxmlparsererrorlinenumber=1, nsxmlparsererrorcolumn=47, nsxmlparsererrormessage=space required after public identifier.

the url of xml source http://forecast.weather.gov/mapclick.php?fcsttype=digitaldwml&lat=40.501368&lon=-79.865723 i'd love skip xml alternative avoid headaches, noaa's not consistent presents in different info formats (dwml, xml, json).

any ideas i'm messing up?

the code calls object below is:

var task = session.datataskwithrequest(request, completionhandler: {data, response, error -> void in println("task completed") if(error) { // if there error in request, print console self.delegate?.didcompletewitherror(error.localizeddescription) //println(error.localizeddescription) println("oops!") } var err: nserror? if self.responseformat == "json" { // blah blah blah ... code here work fine. snipped brevity } else if self.responseformat == "xml" { // set xml parsing code here var error = nserror() var xmlreader = xmldictionary(error: error) var xmlresult = xmlreader.dictionaryforxmldata(data, error: error) nsdictionary self.delegate?.didcompletewithdictionary(xmlresult) }

the "xml nsdictionary converter:

// // xmldictionary.swift // // import foundation class xmldictionary: nsobject, nsxmlparserdelegate { var dictionarystack = nsmutablearray() var textinprogress = "" allow xmlreadertextnodekey = "text" var errorp = nserror() func dictionaryforxmldata(data: nsdata, error: nserror) -> nsdictionary { var reader = xmldictionary(error: error) homecoming reader.objectwithdata(data, error: error) nsdictionary } func dictionaryforxmlstring(string: string, error: nserror) -> nsdictionary { var info : nsdata = string.datausingencoding(nsutf8stringencoding) homecoming dictionaryforxmldata(data, error: error) } init(error: nserror) { self.errorp = error } func objectwithdata(data:nsdata, error:nserror) -> nsdictionary { // clear out old info dictionarystack.removeallobjects() textinprogress = "" // initialize stack fresh dictionary dictionarystack.addobject(nsmutabledictionary()) // parse xml var parser = nsxmlparser(data: data) parser.delegate = self // more needed var success:bool = parser.parse() if success { println("parse success!") } else { println("parse failure!") } // homecoming stack's root dictionary on success var resultdict : nsdictionary! = dictionarystack[0] nsdictionary nslog(" in parser: %@", resultdict) homecoming resultdict nsdictionary } func parser(parser: nsxmlparser!,didstartelement elementname: string!, namespaceuri: string!, qualifiedname : string!, attributes attributedict: nsdictionary!) { // dictionary current level in stack var elementcount = dictionarystack.count - 1 if elementcount < 0 { elementcount = 0 } nslog("element: %d", elementcount) var parentdict = dictionarystack[elementcount] nsmutabledictionary // create kid dictionary new element , initialize attributes var childdict = nsmutabledictionary() childdict.addentriesfromdictionary(attributedict) // if there's item key, means need create array var existingvalue : anyobject? = parentdict[elementname]! anyobject if allow evalue : nsmutablearray = existingvalue as? nsmutablearray { var array = nsmutablearray() if evalue.iskindofclass(nsmutablearray) { // array exists, utilize array = evalue } else { array.addobject(evalue) // replace kid dictionary array of children dictionaries parentdict.setobject(array, forkey: elementname) } // add together new kid dictionary array array.addobject(childdict) } else { // no existing value, update dictionary parentdict.setobject(childdict, forkey: elementname) } // update stack dictionarystack.addobject(childdict) } func parser(parser: nsxmlparser!, didendelement elementname: string!, namespaceuri: string!, qualifiedname qname: string!) { // update parent dict text info var elementcount = dictionarystack.count - 1 if elementcount < 0 { elementcount = 0 } var dictinprogress = dictionarystack[elementcount] nsmutabledictionary // set text property if countelements(textinprogress) > 0 { // rid of leading + trailing whitespace dictinprogress.setobject(textinprogress, forkey: xmlreadertextnodekey) // reset text textinprogress = "" } // pop current dict dictionarystack.removelastobject() } func parser(parser: nsxmlparser!, foundcharacters string: string!) { // build text value textinprogress += string } func parser(parser: nsxmlparser!, parseerroroccurred parseerror: nserror!) { self.errorp = parseerror nslog("failure error: %@", parseerror) } }

thanks

edit: added other file's code requested.

// // govdatarequest.swift // // // created michael pulsifer (u.s. section of labor) on 6/18/14. // license: public domain // import foundation protocol govdatarequestprotocol { func didcompletewitherror(errormessage: string) func didcompletewithdictionary(results: nsdictionary) } class govdatarequest { var delegate: govdatarequestprotocol? = nil var apikey = "" var apihost = "" var apiurl = "" var responseformat = "json" var timeout = 60.0 init(apikey: string, apihost: string, apiurl:string) { self.apikey = apikey self.apihost = apihost self.apiurl = apiurl } func callapimethod (#method: string, arguments: dictionary<string,string>) { // build base of operations url based on provided info var url = apihost + apiurl + "/" + method // start building query string var querystring = "" // appropriate, add together key switch apihost { case "http://api.dol.gov": querystring = "?key=" + apikey case "http://api.census.gov", "http://pillbox.nlm.nih.gov": querystring = "?key=" + apikey case "http://api.eia.gov", "http://developer.nrel.gov", "http://api.stlouisfed.org", "http://healthfinder.gov": querystring = "?api_key=" + apikey case "http://www.ncdc.noaa.gov": querystring = "?token=" + apikey default: // nil println("doing nil now") } //construct arguments part of query string (argkey, argvalue) in arguments { switch apihost { case "http://api.dol.gov": // dol's v1 api has specific formatting requirements arguments in query string switch argkey { case "top", "skip", "select", "orderby", "filter": querystring += "&$" + argkey + "=" + argvalue case "format", "query", "region", "locality", "skipcount": querystring += "&" + argkey + "=" + argvalue default: println("nothing see here") } case "http://go.usa.gov": // go.usa.gov requires apikey 2nd argument if countelements(querystring) == 0 { querystring += "?" + argkey + "=" + argvalue + "&apikey=" + apikey } else { querystring += "&" + argkey + "=" + argvalue } default: if countelements(querystring) == 0 { querystring += "?" + argkey + "=" + argvalue } else { querystring += "&" + argkey + "=" + argvalue } } } //if there arguments, append them url if countelements(querystring) > 0 { url += querystring } //dot fmcsa requires key placed @ end. if apihost == "https://mobile.fmcsa.dot.gov" { if countelements(querystring) > 0 { url += "&webkey=" + apikey } else { url += "?webkey=" + apikey } } /* assumption: info retrieved in json format. todo: consider situation when xml received. */ // send request api , parse var urltopackage = url.stringbyaddingpercentescapesusingencoding(nsutf8stringencoding) println(urltopackage) var urltosend: nsurl = nsurl(string: urltopackage) var apisessionconfiguration: nsurlsessionconfiguration = nsurlsessionconfiguration.defaultsessionconfiguration() apisessionconfiguration.timeoutintervalforrequest = timeout var session = nsurlsession(configuration:apisessionconfiguration) var request = nsmutableurlrequest(url:urltosend) request.addvalue("application/json",forhttpheaderfield:"accept") var task = session.datataskwithrequest(request, completionhandler: {data, response, error -> void in println("task completed") if(error) { // if there error in request, print console self.delegate?.didcompletewitherror(error.localizeddescription) //println(error.localizeddescription) println("oops!") } var err: nserror? if self.responseformat == "json" { var jsonresult = nsjsonserialization.jsonobjectwithdata(data, options: nsjsonreadingoptions.mutablecontainers, error: &err) nsdictionary if(err?) { // if there error parson json, print console nslog ("error parsing json") } self.delegate?.didcompletewithdictionary(jsonresult) } else if self.responseformat == "xml" { // set xml parsing code here var error = nserror() var xmlreader = xmldictionary(error: error) var xmlresult = xmlreader.dictionaryforxmldata(data, error: error) nsdictionary self.delegate?.didcompletewithdictionary(xmlresult) } }) task.resume() } }

ios xml swift

No comments:

Post a Comment