Anda di halaman 1dari 10

Parsing XML element attributes with TouchXML

Assuming that you already familiar with parsing XML with a little help from TouchXML we will go straight to the topic: parsing an attribute! Ill just put some sample XML here so it would be easier to understand whats happening in code later.
?

01 02 03 04 05 06 07 08 09 10 11

<pigletlist> <piglet id="1"> <name>Nifnif</name > </piglet> <piglet id="2"> <name>Nufnuf</name > </piglet> <piglet id="3"> <name>Nafnaf</name > </piglet> </pigletlist>

Well, here we have our tree little piglets put in a single XML file and bellow lies the magic code which parses piglet list with their id attributes. If you are too lazy to look trough all the code (I would be), key point is attributeForName method of CXMLElement object used like this: [[node attributeForName:@"id"] stringValue]. 01 02 03 04 05 06 07 08 // we will put parsed data in an a array NSMutableArray *res = [[NSMutableArray alloc] init]; // using local resource file
?

09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

NSString *XMLPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathCom ponent:@"piglets.xml"]; NSData *XMLData = [NSData dataWithContentsOfFile:X MLPath]; CXMLDocument *doc = [[[CXMLDocument alloc] initWithData:XMLData options:0 error:nil] autorelease]; NSArray *nodes = NULL; // searching for piglet nodes nodes = [doc nodesForXPath:@"//piglet " error:nil]; for (CXMLElement *node in nodes) { NSMutableDictionary *item = [[NSMutableDictionary alloc] init]; int counter; for(counter = 0; counter < [node childCount]; counter++) { // common procedure: dictionary with keys/values from XML node [item setObject: [[node childAtIndex:counter] stringValue] forKey: [[node

childAtIndex:counter] name]]; } // and here it is attributeForName! Simple as that. [item setObject:[[node attributeForName:@"id"] stringValue] forKey:@"id"]; // <------ this magical arrow is pointing to the area of interest [res addObject:item]; [item release]; } // and we print our results NSLog(@"%@", res); [res release]; Our results:
?

01 2010-02-05 09:54:01.078 02 demo[1901:207] ( 03 { 04 id = 1; 05 name = Nifnif; 06 }, 07 { 08 id = 2; 09 name = Nufnuf; 10 }, 11 { 12 id = 3; 13 name = Nafnaf; 14 } )

Mysterious "text = \n"

Sorry, that my example caused frustration to everyone, I used cleaner XML than the posted one and let it be a lesson for me that I should post everything as it is. Anyway, cleaning all the white spaces and new lines from XML file is not an option for everyone, so the only solution I can think of would be to check if value for some key is empty.
?

1 2 3 4 5

NSString * value = [[[node childAtIndex:counter] stringValue] stringByTrimmingCharacte rsInSet:[NSCharacterSet whitespaceAndNewlineChar acterSet]]; if ([value length] != 0) { [item setObject:[[node childAtIndex:counter] stringValue] forKey: [[node childAtIndex:counter] localName]]; }

Of course if your XML has "text" key and it can be empty - you should check for that too. /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// ///// /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// ///// <Player PlayerName="Padraig HARRINGTON" CurrentPosition="1" CurrentRank="1"

Country="IRL" NumberOfHolesPlayed="18" ParRelativeScore="+3"> <RoundScore RoundNumber="1" Score="74" /> <RoundScore RoundNumber="2" Score="68" /> <RoundScore RoundNumber="3" Score="72" /> <RoundScore RoundNumber="4" Score="69" /> </Player> <Player PlayerName="Ian POULTER" CurrentPosition="2" CurrentRank="2" Country="ENG" NumberOfHolesPlayed="18" ParRelativeScore="+7"> <RoundScore RoundNumber="1" Score="72" /> <RoundScore RoundNumber="2" Score="71" /> <RoundScore RoundNumber="3" Score="75" /> <RoundScore RoundNumber="4" Score="69" /> </Player> <Player PlayerName="Henrik STENSON" CurrentPosition="3" CurrentRank="T3" Country="SWE" NumberOfHolesPlayed="18" ParRelativeScore="+9"> <RoundScore RoundNumber="1" Score="76" /> <RoundScore RoundNumber="2" Score="72" /> <RoundScore RoundNumber="3" Score="70" /> <RoundScore RoundNumber="4" Score="71" /> </Player> -(void)methodForParsingPlayers{ NSMutableArray *ar=[[NSMutableArray alloc] init]; CXMLDocument *doc=[[[CXMLDocument alloc] initWithData: [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Players" ofType:@"xml"]] options:0 error:nil] autorelease]; NSArray *nodes=nil; nodes=[doc nodesForXPath:@"//Player" error:nil]; NSString *strValue; NSString *strName; for (CXMLElement *node in nodes) {

NSMutableDictionary *object=[[NSMutableDictionary alloc] init]; // process to set attributes of object ---------------------------------------NSMutableDictionary *objectAttributes=[[NSMutableDictionary alloc] init]; NSArray *arAttr=[node attributes]; NSUInteger i, countAttr = [arAttr count]; for (i = 0; i < countAttr; i++) { strValue=[[arAttr objectAtIndex:i] stringValue]; strName=[[arAttr objectAtIndex:i] name]; if(strValue && strName){ [objectAttributes setValue:strValue forKey:strName]; } } [object setValue:objectAttributes forKey:[node name]]; [objectAttributes release]; objectAttributes=nil; // -------------------------------------------------------------------------------// process to read elements of object ---------------------------------------NSUInteger j, countElements = [node childCount]; CXMLNode *element; NSMutableDictionary *elementDictionary=nil; for (j=0; j<countElements; j++) { element=[node childAtIndex:j]; elementDictionary=[[NSMutableDictionary alloc] init]; // process to read element attributes ---------------------------------if([element isMemberOfClass:[CXMLElement class]]){ CXMLElement *element2=(CXMLElement*)element; arAttr=[element2 attributes]; countAttr=[arAttr count]; for (i=0; i<countAttr; i++) { strName=[[arAttr objectAtIndex:i] name];

strValue=[[arAttr objectAtIndex:i] stringValue]; if(strName && strValue){ [elementDictionary setValue:strValue forKey:strName]; } } } // -------------------------------------------------------------------// element value if available strValue=[element stringValue]; if(strValue){ [elementDictionary setValue:strValue forKey:@"value"]; } // --------------------------------------------------------------------// check if object/dictionary exists for this key "name" strName=[element name]; if([object valueForKey:strName]){ if([[object valueForKey:strName] isKindOfClass: [NSMutableDictionary class]]){ NSMutableDictionary *d=[[NSMutableDictionary alloc] initWithDictionary:[object valueForKey:strName]]; NSMutableArray *arOFSameElementName=[[NSMutableArray alloc] initWithObjects:d,elementDictionary,nil]; [object setValue:arOFSameElementName forKey:strName]; [d release]; d=nil; [arOFSameElementName release]; arOFSameElementName=nil; } else { NSMutableArray *arOFSameElementName=[object valueForKey:strName]; [arOFSameElementName addObject:elementDictionary]; }

} else { [object setValue:elementDictionary forKey:strName]; } [elementDictionary release]; elementDictionary=nil; // --------------------------------------------------------------------} [ar addObject:object]; [object release]; object=nil; // -------------------------------------------------------------------------------} NSLog(@"%@",[ar description]); }

2010-08-13 12:45:48.786 TouchTry[2850:207] ( { Player = { Country = IRL; CurrentPosition = 1; CurrentRank = 1; NumberOfHolesPlayed = 18; ParRelativeScore = "+3"; PlayerName = "Padraig HARRINGTON"; }; RoundScore = ( { RoundNumber = 1; Score = 74; }, { RoundNumber = 2; Score = 68; }, { RoundNumber = 3; Score = 72; },

{ RoundNumber = 4; Score = 69; } ); }, { Player = { Country = ENG; CurrentPosition = 2; CurrentRank = 2; NumberOfHolesPlayed = 18; ParRelativeScore = "+7"; PlayerName = "Ian POULTER"; }; RoundScore = ( { RoundNumber = 1; Score = 72; }, { RoundNumber = 2; Score = 71; }, { RoundNumber = 3; Score = 75; }, { RoundNumber = 4; Score = 69; } ); }, { Player = { Country = SWE; CurrentPosition = 3;

CurrentRank = T3; NumberOfHolesPlayed = 18; ParRelativeScore = "+9"; PlayerName = "Henrik STENSON"; }; RoundScore = ( { RoundNumber = Score = 76; }, { RoundNumber = Score = 72; }, { RoundNumber = Score = 70; }, { RoundNumber = Score = 71; } ); } )

1;

2;

3;

4;

Anda mungkin juga menyukai