views:

1860

answers:

4

How do I use touchXML to parse this XML? I want to store all the attributes as key/value pairs in a dictionary.

<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>

I have no problem is the XML is formatted like so:

<Player>
<Country>UK</Country>
<NumberOfHolesPlayed>12</NumberOfHolesPlayed>
...
...

But I'm not sure what to do when dealing with attributes...

How can you get attributes with touchXML? In particular if a node has a subnode that also has attributes..

As per the first example XML file. In the first XML example I managed to get the Player attributes but not the child nodes 'RoundScore' attributes.

Would love a helping hand..

Thanks,

Dan

A: 

I found out that you have to check the child nodes are CXElements. Sometimes they're CXMLNodes and these don't have attribute properties.

Dan Morgan
So is your question answered? If it is please mark it so.
JoePasq
can you please post an example? I have the same question about parsing XML tag attributes.
sniurkst
A: 

He can you post an example of how you handle childnode attributes, it's quite difficult seems to me. If I do this:

for(counter=0; counter<[resultElement childCount]; counter++){

[bookItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];

}

it will push my childnode values in bookItem Dictonary, but if one of these is having an childnode, it crashes, because then there is no valid stringvalue, you mention to check if it is an element or node? How have you handled this, because I need, to access lots of childnodes and values etc...

Thanks in advance kees

Hey Kees - You need to check if the stringvalue == nil and if it does then don't add it to dictionary.I do this://get all the child elements into an array NSArray *children = resultElement.children;// Go through all the news nodes children for (CXMLElement *childElement in children) { //Only interested in CXMLElement - other stuff is gunk if ([childElement isMemberOfClass: [CXMLElement class]]) {if ([childElement stringValue] != nil) {}
Dan Morgan
+1  A: 

Yep ! solved your problem.

see, following code. Hope you understand. It's working for your requirement. I also have added - NSLog - Result - parsed.

-(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 = 1;
                Score = 76;
            },
                        {
                RoundNumber = 2;
                Score = 72;
            },
                        {
                RoundNumber = 3;
                Score = 70;
            },
                        {
                RoundNumber = 4;
                Score = 71;
            }
        );
    }
)
sugar
A: 

Use TBXML, its much easier and faster on working with XML files. Nice documentation also. Your problem with Attributes is easier solved here. http://www.tbxml.co.uk/TBXML/TBXML_Free.html

ZaldzBugz