i'm working on project have xml responses being converted instance of object. sake of question, root elements mapped "parameter" , child elements mapped "subparameter" class setup this.
class myclass : nsobject { var parameter = parameter() } class parameter: nsobject { var subparameter = string() }
my question this... how set value of myclass.parameter.subparameter using setvalue(value, key)?
thanks in advance assistance.
if classes subclass nsobject
, enjoy key-value coding (kvc) , can object.setvalue(forkey:)
.
if you're dealing xml elements have sub-elements, trick how let parser keep track upon object perform setvalue(forkey:)
. maintain stack of objects:
consider xml:
<people> <person> <name>rob</name> <address> <address1>1 main street</address1> <address2 /> <city>pasadena</city> <state>ca</state> </address> </person> <person> <name>rachel</name> <address> <address1>1 broadway</address1> <address2>apt 1</address2> <city>new york</city> <state>ny</state> </address> </person> </people>
and consider class hierarchy:
class person : nsobject { var name: string? var address: address? } class address: nsobject { var address1: string? var address2: string? var city: string? var state: string? }
so, when enter <person>
, add person
object stack. when exit </person>
, pop person
off stack , update parent object accordingly. likewise, when enter , exist <address>
, </address>
, push , pop address
objects off stack, again updating parent object accordingly. pattern, @ given point in time, last item in stack "current" object, whenever encounter element other person
or address
, update value current object whatever string value received.
so, can parse with:
var results: [person]? private var objectstack = [nsobject]() private var currentstring: string? func parser(parser: nsxmlparser, didstartelement elementname: string, namespaceuri: string?, qualifiedname qname: string?, attributes attributedict: [string : string]) { if elementname == "people" { objectstack = [person]() } else if elementname == "person" { objectstack.append(person()) } else if elementname == "address" { objectstack.append(address()) } else { currentstring = string() } } func parser(parser: nsxmlparser, foundcharacters string: string) { currentstring? += string } func parser(parser: nsxmlparser, didendelement elementname: string, namespaceuri: string?, qualifiedname qname: string?) { if let foundstring = currentstring { objectstack.last?.setvalue(foundstring, forkey: elementname) currentstring = nil } else if let lastobject = objectstack.last lastobject address { objectstack.removelast() if objectstack.isempty { results = lastobject as? [person] } else { objectstack.last?.setvalue(lastobject, forkey: elementname) } } } func parser(parser: nsxmlparser, parseerroroccurred parseerror: nserror) { print(parseerror) }
now rudimentary example. not, example, checking see if current object has property elementname
, above crash if xml included element names didn't correspond object's properties. nor checking type of element property appropriate conversion of string value parsed. of added, wanted keep example concise possible.
but illustrates basic idea: need
- keep track of "stack" of custom objects know object updating in
didendelement
; - have special handling in
didstartelement
know whether want instantiate custom object , push on stack, or whether you're going parse text value update current object; - have special handling in
didendelement
know whether you're updating value of custom object or whether finished custom object, popping off stack , updating value in parent custom object (that @ end of stack).
if stack concept confusing, can accomplish same sort of thing keeping track of sorts of properties depending upon level of xml tree happen at. find stack model compelling.
anyway, once take care of keeping track of in xml tree, can setvalue(forkey:)
update value whether top level element or child element.
Comments
Post a Comment