Parsing multiple and multi-level nested elements with TouchXML - iphone

I have an XML with the following structure and I am trying to create my model object from this. Can someone please help me find a way to get these objects from the XML using TouchXML, NSMutableArray and NSMutableDictionay.
<?xml version="1.0" encoding="utf-8"?>
<response>
<level1_items>
<level1_item>
<item_1>text</item_1>
<item_2>text</item_2>
</level1_item>
<level1_item>
<item_1>some text</item_1>
<item_2>some more text</item_2>
</level1_items>
<items>
<item>
<child_items>
<child_item>
<leaf1>node text</leaf1>
<leaf2>leaf text</leaf2>
<leaf3>some text</leaf3>
</child_item>
<child_item>
<leaf1>text</leaf1>
<leaf2>leaf text</leaf2>
<leaf3>more text</leaf3>
</child_item>
</child_items>
</item>
<item>
<child_items>
<child_item>
<leaf1>node text</leaf1>
<leaf2>leaf text</leaf2>
<leaf3>some text</leaf3>
</child_item>
<child_item>
<leaf1>text</leaf1>
<leaf2>leaf text</leaf2>
<leaf3>more text</leaf3>
</child_item>
</child_items>
</item>
</items>
</response>
I need to parse the <response> and its children.

First off, I have to say that your XML will be difficult to work with because you are trying to use a specific tag for each item in a list. For example:
<level1_items>
<level1_item>
<item_1>text</item_1>
<item_2>text</item_2>
</level1_item>
<level1_item>
<item_1>some text</item_1>
<item_2>some more text</item_2>
</level1_items>
the tags named <item_ 1>, <item_ 2> don't make sense as XML is intended to describe your data, not define it. If you have an entity called an item, you should probably just call it item and make the XML look like this:
<level1_items>
<level1_item>
<item index="1">text</item>
<item index="2">text</item>
</level1_item>
<level1_item>
<item index="1">some text</item>
<item index="2">some more text</item>
</level1_items>
Where each item has an index. For that matter, you could just load the document in your TouchXML CXMLDocument and grab the nodes you need with XPath and assume they're in the correct order ignoring the index= parameter I specified.
The next issue is that converting XML to an NSDictioanry or NSArray of dictionaries is a pretty involved task and what you gain isn't worth the effort. Just load your XML into a CXMLDocument and then start obtaining nodes using XPath. Something like this:
CXMLDocument *doc = [[CXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
// Returns all 'level1_item' nodes in an array
NSArray *nodes = [[doc rootElement] nodesForXPath:#"//response/level1_items/level1_item" error:nil];
for (CXMLNode *itemNode in nodes)
{
for (CXMLNode *childNode in [itemNode children])
{
NSString *nodeName = [childNode name]; // should contain item_1 in first iteration
NSString *nodeValue = [childNode stringValue]; // should contain 'text' in first iteration
// Do something with the node data.
}
}
I suggest trying to use the XML this way and then come back here and ask specific questions if you have problems.

-(NSMutableArray *)parseNodeFromXML:(NSString *)strXML readForNode:(NSString *)strReadValue
{
NSError *theError = NULL;
CXMLDocument *theXMLDocument = [[CXMLDocument alloc] initWithXMLString:strXML options:0 error:&theError] ;
NSMutableArray *arrReturn = [[NSMutableArray alloc] init];
NSArray *nodes = [[theXMLDocument rootElement] nodesForXPath:strReadValue error:nil];
for (CXMLNode *itemNode in nodes)
{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
// PROCESS FOR READ ELEMENT ATTRIBUTES IN CURRENT NODE -------------------------
if([itemNode isMemberOfClass:[CXMLElement class]]){
CXMLElement *elements=(CXMLElement*)itemNode;
NSArray *arAttr=[elements attributes];
for (int i=0; i<[arAttr count]; i++) {
if([[arAttr objectAtIndex:i] name] && [[arAttr objectAtIndex:i] stringValue]){
[dic setValue:[[arAttr objectAtIndex:i] stringValue] forKey:[[arAttr objectAtIndex:i] name]];
}
}
}
// PROCESS FOR READ CHILD NODE IN CURRENT NODE -------------------------
for (CXMLNode *childNode in [itemNode children])
{
// NSLog(#"count -- %d --- %#",[childNode childCount],[childNode children]);
// IF ANY CHILD NODE HAVE MULTIPLE CHILDRENS THEN DO THIS....-
if ([childNode childCount] > 1)
{
NSMutableDictionary *dicChild = [[NSMutableDictionary alloc] init];
for (CXMLNode *ChildItemNode in [childNode children])
{
[dicChild setValue:[ChildItemNode stringValue] forKey:[ChildItemNode name]];
}
[dic setValue:dicChild forKey:[childNode name]];
}else
{
[dic setValue:[childNode stringValue] forKey:[childNode name]];
}
}
[arrReturn addObject:dic];
}
// NSLog(#"%#",arrReturn);
return arrReturn;
}
may this help for multiple get child

Related

unable to parse xml using touchXML, nodesForXPath return nothing

I am trying to parse xml using the touchXML library but not getting the results, the code is as below
NSError *error = nil;
CXMLDocument *xmlParser = [[CXMLDocument alloc] initWithXMLString:dataString options:0 error:&error];
NSArray *resultNodes = NULL;
resultNodes = [xmlParser nodesForXPath:#"//entry" error:&error];
for (CXMLElement *resultElement in resultNodes) {
NSMutableDictionary *blogItem = [[NSMutableDictionary alloc] init];
int counter;
for(counter = 0; counter < [resultElement childCount]; counter++) {
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
}
}
the method nodesForXPath: doesn't returns anything leaving the resultNodes array with 0 objects. I am getting the proper xml in dataString and the CXMLDocument is also getting prepared properly. I tried debugging it but there is nothing I can see accept the 0 objects in resultNodes, NSError also contains nothing (i.e. no error occurs). the xml file I am trying to parse is as below.
<feed xmlns:s="http://syndication.nhschoices.nhs.uk/services" xmlns="http://www.w3.org/2005/Atom">
<title type="text">...</title>
<id>...</id>
<rights type="text">© Crown Copyright 2009</rights>
<updated>2012-04-27T11:33:02+01:00</updated>
<category term="Search"/>
<logo>...</logo>
<author>...</author>
<s:SearchCoords>174900,517900</s:SearchCoords>
<entry>
<id>
http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/32248
</id>
<title type="text">Sayer A</title>
<updated>2012-04-27T10:33:02Z</updated>
<link rel="self" title="Sayer A" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/32248?apikey=YAHUGHET"/>
<link rel="alternate" title="Sayer A" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=15F37AEF-EC5B-4A90-9E72-269ADEB39629"/>
<content type="application/xml">
<s:organisationSummary>
<s:name>Sayer A</s:name>
<s:address>
<s:addressLine>The Richmond Green Medical Cen</s:addressLine>
<s:addressLine>19 The Green</s:addressLine>
<s:addressLine>Richmond</s:addressLine>
<s:addressLine>Surrey</s:addressLine>
<s:postcode>TW91PX</s:postcode>
</s:address>
<s:contact type="General">
<s:telephone>020 83327515</s:telephone>
</s:contact>
<s:geographicCoordinates>
<s:northing>174900</s:northing>
<s:easting>517800</s:easting>
<s:longitude>-0.305512266736965</s:longitude>
<s:latitude>51.4608026642546</s:latitude>
</s:geographicCoordinates>
<s:Distance>0.1</s:Distance>
</s:organisationSummary>
</content>
</entry>
<entry>
<id>
http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33420
</id>
<title type="text">Griffiths W</title>
<updated>2012-04-27T10:33:02Z</updated>
<link rel="self" title="Griffiths W" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33420?apikey=YAHUGHET"/>
<link rel="alternate" title="Griffiths W" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=EEC98A8A-B888-4F44-A0B6-DC6ABCBF19CE"/>
<content type="application/xml">
<s:organisationSummary>
<s:name>Griffiths W</s:name>
<s:address>
<s:addressLine>Paradise Road Surgery</s:addressLine>
<s:addressLine>37 Paradise Road</s:addressLine>
<s:addressLine>Richmond</s:addressLine>
<s:addressLine>Surrey</s:addressLine>
<s:postcode>TW91SA</s:postcode>
</s:address>
<s:contact type="General">
<s:telephone>020 89402423</s:telephone>
</s:contact>
<s:geographicCoordinates>
<s:northing>174800</s:northing>
<s:easting>518100</s:easting>
<s:longitude>-0.301388352909701</s:longitude>
<s:latitude>51.4601120315006</s:latitude>
</s:geographicCoordinates>
<s:Distance>0.223606797749979</s:Distance>
</s:organisationSummary>
</content>
</entry>
<entry>
<id>
http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33035
</id>
<title type="text">Dr Da Costa</title>
<updated>2012-04-27T10:33:02Z</updated>
<link rel="self" title="Dr Da Costa" href="http://v1.syndication.nhschoices.nhs.uk/organisations/gppractices/33035?apikey=YAHUGHET"/>
<link rel="alternate" title="Dr Da Costa" href="http://www.nhs.uk/ServiceDirectories/Pages/GP.aspx?pid=EDCE215D-6412-4AAB-AFC4-9F37888D413C"/>
<content type="application/xml">
<s:organisationSummary>
<s:name>Dr Da Costa</s:name>
<s:address>
<s:addressLine>The Vineyard Surgery</s:addressLine>
<s:addressLine>35 The Vineyard</s:addressLine>
<s:addressLine>Richmond</s:addressLine>
<s:addressLine>Surrey</s:addressLine>
<s:postcode>TW106PP</s:postcode>
</s:address>
<s:contact type="General">
<s:telephone>020 89480404</s:telephone>
</s:contact>
<s:geographicCoordinates>
<s:northing>174600</s:northing>
<s:easting>518100</s:easting>
<s:longitude>-0.301044685875553</s:longitude>
<s:latitude>51.4581333717098</s:latitude>
</s:geographicCoordinates>
<s:Distance>0.360555127546399</s:Distance>
</s:organisationSummary>
</content>
</entry>
I've never worked with touchXML, but it may be that you need to set your namespace, like here: Getting the value of an Element in Cocoa using TouchXML
Just check out this , I was able to parse the similar kind of response :
- (void)viewDidLoad
{
[super viewDidLoad];
self.rqst=[[WebRqst alloc] init];
[self.rqst startLoading:[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"PASS UR URL"]]
vCtr:self];
}
**// a method to grab the attributes.**
- (void)parseAttributesForElement:(CXMLElement*)element andDictionary:(NSMutableDictionary*)dictionary {
NSString *strName,*strValue;
NSArray *arAttributes = [(CXMLElement*)element attributes];
for (int i=0; i<arAttributes.count; i++) {
strName = [[arAttributes objectAtIndex:i] name];
strValue = [[arAttributes objectAtIndex:i] stringValue];
if(strName && strValue && [strName length]>0 && [strValue length]>0) {
[dictionary setValue:strValue forKey:strName];
}
}
}
**// a method to parse the node & store in dictionary**
- (void)parseThisNode:(CXMLNode*)node storeInDictionary:(NSMutableDictionary*)dOfNode {
NSString *strName = [node name];
NSString *strValue = [node stringValue];
if(strName && [strName length]>0 && ![strName isEqualToString:#"text"]) {
NSMutableDictionary *dOfAttributes = [NSMutableDictionary dictionary];
// if node has value
if(strValue && [strValue length]>0) {
[dOfAttributes setValue:strValue forKey:#"value"];
}
// if node has attributes
if([node isKindOfClass:[CXMLElement class]] && [(CXMLElement*)node attributes].count>0) {
[self parseAttributesForElement:(CXMLElement*)node andDictionary:dOfAttributes];
}
// if node has childs
NSArray *arChildern = [node children];
if(arChildern.count>0) {
NSMutableDictionary *dOfTAG=[NSMutableDictionary dictionary];
for (CXMLNode *nodeChildChild in arChildern) {
// recursive call of a function
[self parseThisNode:nodeChildChild storeInDictionary:dOfTAG];
}
if([[dOfTAG allKeys] count]>0) [dOfAttributes setValue:dOfTAG forKey:#"child"];
}
id valueFK = [dOfNode valueForKey:strName];
// verify if same node is repeated, add it to array (e.g. link tag is repeated )
if([valueFK isKindOfClass:[NSMutableArray class]]) {
NSMutableArray *ar=(NSMutableArray*)valueFK;
[ar addObject:dOfAttributes];
[dOfNode setValue:ar forKey:strName];
} else if([valueFK isKindOfClass:[NSMutableDictionary class]]) {
NSMutableArray *ar=[NSMutableArray arrayWithObjects:valueFK,dOfAttributes, nil];
[dOfNode setValue:ar forKey:strName];
} else {
[dOfNode setValue:dOfAttributes forKey:strName];
}
}
}
**// pass the data to this method & it will return a dictionary**
- (NSDictionary *)startParsingUsingData:(NSData *) data {
// create a mutable-empty dictionary wich will hold the data
NSMutableDictionary *dictionaryParsed = [NSMutableDictionary dictionary];
// verify - do we have proper data for parsing or not
if(data && [data length]>0) {
// load a data into XML Document
CXMLDocument *doc = [[CXMLDocument alloc] initWithData:data options:0 error:nil];
// grab all the tags of XML
NSArray *nodes = [doc nodesForXPath:#"*" error:nil];
// start a loop to goThrough each tag of xml
for (CXMLNode *nodeFeed in nodes) {
// verify that you reached to desired tag or not
if([[nodeFeed name] isEqualToString:#"feed"]) {
// just write this code to get data parsed & stored in our dictionary
[self parseThisNode:nodeFeed storeInDictionary:dictionaryParsed];
// grab the childrens of tag ( as per requirement )
dictionaryParsed=[[dictionaryParsed valueForKey:#"feed"] valueForKey:#"child"];
}
}
}
// return the dictionary.
if([[dictionaryParsed allKeys]count]>0) {
return [NSDictionary dictionaryWithDictionary:dictionaryParsed];
} else {
return nil;
}
}
// It's my delegate method where I am getting my NSData
- (void)webRequestReceivedData:(NSData *)data {
if(data && [data length]>0) {
NSLog(#"Details are as follows\n%#",
[self startParsingUsingData:data]); //This is the method required which will parse the data
}
}
Hope, now you will be able to parse the data.

How can I parse this xml using GDataXML parser?

<list>
<OrderData HASH="1408108039"></OrderData>
<OrderData HASH="208524692">
<id>97</id>
<customer>
<CustomerData HASH="2128670187"></CustomerData></customer>
<billingAddress></billingAddress><deliveryAddress></deliveryAddress>
<orderDetail>
<list>
<OrderDetailData HASH="516790072"></OrderDetailData>
<OrderDetailData HASH="11226247"></OrderDetailData>
<OrderDetailData HASH="11226247"></OrderDetailData>
</list>
</orderDetail>
<log/>
</OrderData>
<OrderData HASH="1502226778"></OrderData>
</list>
I cannot find a solution to find the number of OrderDetailData elements? I also read http://iphonebyradix.blogspot.com/2011/03/using-gdata-to-parse-xml-file.html this url.
Thanks in advance.
Edit:
I am explaining my requirement again. In this xml there will be multiple OrderData element. Now I have to count the number of OrderDetailData elemnts from a particular OrderData element. Suppose that, according to my xml, the current parsed xml has one OrderData element, named id and its value is 97. Now, I have to count how many OrderDetailData elements are contained in the OrderData(whichid` is 97).
This is a simple example how to retrieve some data. This example is very simple and not use XPath expression. I suggest you first understand how it works and then use XPath expression. In my opinion it is not useful to use XPath expression if you cannot understand how the parser works.
NSString* path = [[NSBundle mainBundle] pathForResource:#"test2" ofType:#"xml"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfFile:path];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData
options:0 error:&error];
//NSLog(#"%#", doc.rootElement); // print the whole xml
NSArray *orderDataArray = [doc.rootElement elementsForName:#"OrderData"];
for (GDataXMLElement *orderDataElement in orderDataArray) {
if([orderDataElement childCount] > 0)
{
NSString *attributeForOrderDataElement = [(GDataXMLElement *) [orderDataElement attributeForName:#"HASH"] stringValue];
NSLog(#"attributeForOrderDataElement has value %#", attributeForOrderDataElement);
GDataXMLElement* idElement = (GDataXMLElement*)[[orderDataElement elementsForName:#"id"] objectAtIndex:0];
NSLog(#"id has value %#", idElement.stringValue);
GDataXMLElement* orderDetailElement = (GDataXMLElement*)[[orderDataElement elementsForName:#"orderDetail"] objectAtIndex:0];
GDataXMLElement* listElement = (GDataXMLElement*)[[orderDetailElement elementsForName:#"list"] objectAtIndex:0];
NSArray* orderDetailDataArray = [listElement elementsForName:#"OrderDetailData"];
int count = 0;
for (GDataXMLElement *orderDetailDataElement in orderDetailDataArray) {
NSString *attributeForOrderDetailDataElement = [(GDataXMLElement *) [orderDetailDataElement attributeForName:#"HASH"] stringValue];
NSLog(#"attributeForOrderDetailDataElement has value %#", attributeForOrderDetailDataElement);
count++;
}
NSLog(#"%d", count);
}
}
[doc release];
[xmlData release];
This is the output console:
attributeForOrderDataElement has value 208524692 <-- HASH value
id has value 97 <-- id value
attributeForOrderDetailDataElement has value 516790072 <-- HASH value
attributeForOrderDetailDataElement has value 11226247
attributeForOrderDetailDataElement has value 11226247
3 <-- the count
Hope it helps.
Edit
test2.xml contains your file but you could pass it as a string. You can also pass as parameters as string like the following:
NSString* xmlString = #"<list>"
"<OrderData HASH=\"1408108039\"></OrderData>"
"<OrderData HASH=\"208524692\">"
"<id>97</id>"
"<customer>"
"<CustomerData HASH=\"2128670187\"></CustomerData>"
"</customer>"
"<billingAddress></billingAddress>"
"<deliveryAddress></deliveryAddress>"
"<orderDetail>"
"<list>"
"<OrderDetailData HASH=\"516790072\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"</list>"
"</orderDetail>"
"<log/>"
"</OrderData>"
"<OrderData HASH=\"1502226778\"></OrderData>"
"</list>";
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithXMLString:xmlString options:0 error:&error];
I found TouchXML easy in parsing and you can directly access data needed from xml
First of all Download TouchXML and add libxml2.dylib framework to your project.
change buildsetting for "Header Search Path" and add "/usr/include/libxml2"
Import TouchXML.h to your file
//Access document
CXMLDocument *parserDoc = [[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:&err];
//Access root element and access children in heirarchy
CXMLElement *root = [parserDoc rootElement];
NSArray *places = [[[root children] objectAtIndex:0] children];
Else
//Access node by node
NSString *location =[[[[[parserDoc nodesForXPath:#"/xml_api_reply/weather/forecast_information/city" error:nil] objectAtIndex:0] attributeForName:#"data"] stringValue] retain];
If the OrderDetailData is present in 2nd object of array all the time, u can use the below
NSArray* arr = [[XMLelement elementForName:#"list"] elementsForName:#"OrderData"];
NSXMLElement* listElement = [[[arr objectAtIndex:1] elementForName:#"orderDetail"] elementForName:#"list"];
NSArray* orderDetailArray* = [listElement elementsForName:#"OrderDetailData"];
In this u can get the OrderDetailData elements in the array, and u can parse the data in loop. to get HASH value use.
NSString* hash = [[orderDetailArray objectAtIndex:0] stringValueForAttribute:#"HASH"];
This is the below code, i have tried. I got the right output.. check out
NSString* xmlString = #"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<list>"
"<OrderData HASH=\"1408108039\"></OrderData>"
"<OrderData HASH=\"208524692\">"
"<id>97</id>"
"<customer>"
"<CustomerData HASH=\"2128670187\"></CustomerData></customer>"
"<billingAddress></billingAddress><deliveryAddress></deliveryAddress>"
"<orderDetail>"
"<list>"
"<OrderDetailData HASH=\"516790072\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"<OrderDetailData HASH=\"11226247\"></OrderDetailData>"
"</list>"
"</orderDetail>"
"<log/></OrderData>"
"<OrderData HASH=\"1502226778\"></OrderData>"
"</list>";
NSXMLDocument* doc = [[NSXMLDocument alloc] initWithData:[xmlString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
NSXMLElement* rootElement = [doc rootElement];
NSArray* arr = [rootElement elementsForName:#"OrderData"];
NSXMLElement* orderDataElement;
for (int i = 0; i < [arr count]; i++)
{
int Id = 0;
Id = [[arr objectAtIndex:i] integerValueForNode:#"id"];
if (Id != 0)
{
orderDataElement = [arr objectAtIndex:i];
break;
}
}
NSArray* orderDetailArray = [[[orderDataElement elementForName:#"orderDetail"]
elementForName:#"list"]
elementsForName:#"OrderDetailData"];
for (int j = 0; j < [orderDetailArray count]; j++)
{
NSLog(#"%#", [[orderDetailArray objectAtIndex:j] stringValueForAttribute:#"HASH"]);
}

How can i Parse xml data using GDataXML parser in iPhone application development?

-<stat>
<visitor>4</visitor>
<uniqueVisitor>2</uniqueVisitor>
<order>41</order>
<revenue>20658</revenue>
<conversionRate>48</conversionRate>
<newProduct>25</newProduct>
<outOfStockProduct>11</outOfStockProduct>
</stat>
From this xml i want to get the element name "visitor" & "uniqueVisitor" and their corresponding values using GDataXML parser.
Till now i have done these.
xmlFileLocation = [NSURL URLWithString:#"someurl....abc.php"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfURL:xmlFileLocation];
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:&error];
if (nil == xmlDocument) {
NSLog(#"could not load Branch.xml file");
}
else {
NSLog(#"Loading desire xml url for dashboard");
[self GDataXmlParser];
}
Using a tutorial i have done this till now. But now i want all of these element name and their corresponding values
-(void)GDataXmlParser{
NSArray *getData = [[xmlDocument rootElement]elementsForName:#"stat"];
records = [[NSMutableArray alloc]init];
tempArray = [[NSMutableArray alloc]init];
for(GDataXMLElement *e in getData){
// What i have to do here????
}
}
look at the answer
NSLog(#"%#", xmlDocument.rootElement);
records = [[NSMutableArray alloc] init];
NSLog(#"Enering in the xml file");
NSString *Visitor = [[[xmlDocument.rootElement elementsForName:#"visitor"] objectAtIndex:0] stringValue];
NSLog(#"Visitor : %#",Visitor);
NSString *UVisitor = [[[xmlDocument.rootElement elementsForName:#"uniqueVisitor"] objectAtIndex:0] stringValue];
NSLog(#"Unique Visitor : %#",UVisitor);
for more see the link I am not able to parse xml data using GDataXML
Follow this link for tutorial :http://iphonebyradix.blogspot.com/2011/03/using-gdata-to-parse-xml-file.html
-(void) GDataXmlParser
{
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData
options:0
error:nil];
NSArray *temp = [xmlDocument.rootElement elementsForName:#"stat"];
NSMutableArray *records = [[NSMutableArray alloc]init];
for(GDataXMLElement *e in temp)
{
[records addObject:e];
NSString *Visitor = [[[e elementsForName:#"visitor"] objectAtIndex:0] stringValue];
NSLog(#"Visitor : %#",Visitor);
NSString *UVisitor = [[[e elementsForName:#"uniqueVisitor"] objectAtIndex:0] stringValue];
NSLog(#"Unique Visitor : %#",UVisitor);
}
}
Hope it helps you. Happy iCoding.

How can i parse nested xml using GDataXML parser?

How can I get this <firstName> and <lastName>. I have tried a lot but I have messed up.
<list>
<OrderData HASH="1843180441">
<id>26</id><customer>
<CustomerData HASH="882063912">
<id>1</id>
<sex>Male</sex>
<firstName>admin</firstName>
<lastName>admin</lastName>
<companyName>Individual</companyName>
<userName>admin</userName>
<password>21232f297a57a5a743894a0e4a801fc3</password>
<lastLogin>2012-01-26T12:11:38</lastLogin>
<status>A</status>
<created>2011-09-28T07:01:47</created>
<modified>2012-01-26T12:11:38</modified>
<canChangePassword>Y</canChangePassword>
<isDeleted>false</isDeleted>
<abn/>
<abnBranch/>
<storeCredit>50000.0</storeCredit>
<billingAddress>
<list>
<AddressData HASH="768553743">
<id>2</id>
<firstName>admin</firstName>
<lastName>admin</lastName>
<addressLine1>suite: 1307, 9 Yara Street</addressLine1>
<addressLine2>dgdgdf</addressLine2>
<postCode>3000</postCode>
<suburb>dfgdfg</suburb>
<city>sadf</city>
<phone>4456</phone>
<mobile/>
<fax/>
<active>true</active>
<type>C</type>
<email>afzal.bitmascot#gmail.com</email>
<log/>
</AddressData>
</deliveryAddress>
<purchaseDate>2011-10-03T03:23:48</purchaseDate>
</OrderData>
<OrderData HASH="1569451006"></OrderData>
<OrderData HASH="1449383081"></OrderData>
<OrderData HASH="1438157618"></OrderData>
<OrderData HASH="269308788"></OrderData>
</list>
Till now I have done this.
NSLog(#"Enering in the xml file");
NSArray *getNumberOfOrder = [[xmlDocument rootElement] elementsForName:#"OrderData"];
for(GDataXMLElement *e in getNumberOfOrder){
for(int i =0;i<[[e elementsForName:#"customer"]count];i++){
// All orderd customer name
NSString *orderByFirstString = [[[[e elementsForName:#"customer"] objectAtIndex:0] childAtIndex:2] stringValue];
NSString *orderByLastString = [[[[e elementsForName:#"customer"] objectAtIndex:0] childAtIndex:3]stringValue];
orderByString = [NSString stringWithFormat:#"%# %#",orderByFirstString,orderByLastString];
NSLog(#"order By String: %#",orderByString);
}
}
Cordially appreciate for any help or suggestion.
I would try something like this. I would loop through the XML document, and store it in an array.
Notice the NSLog() which will print to the console and will help you see what is going on.
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:nil];
NSArray *temp = [xmlDocument.rootElement elementsForName:#"OrderData"];
for(GDataXMLElement *e in temp) {
[outputArray addObject:e];
NSLog(#"%#", e);
}
Then I would loop through the array, and do something like this when I wanted to retrieve a result such as the customer's first name.
for (int i = 0; i < [outputArray count]; i++) {
NSString *firstName = [[[[[[[[outputArray objectAtIndex:i]elementsForName:#"customer"] objectAtIndex:0] elementsForName:#"CustomerData"] objectAtIndex:0] childAtIndex:2]stringValue];
}

Unable to parser using TouchXML

I am unable to parse response recieve using Touch XML My response from SOAP
<CXMLDocument 0x4b30110 [0x4b34c90]> <?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetImagesResponse xmlns="http://tempuri.org/">
<GetImagesResult>;http://www.google.com;http://www.hotmail.com;http://www.yahoo.com</GetImagesResult>
</GetImagesResponse>
</soap:Body>
</soap:Envelope>
/// Touch XML function
-(void) grabRSSFeed:(NSData *)responseData {
// Initialize the blogEntries MutableArray that we declared in the header
self.rssEntries = [[[NSMutableArray alloc] init] autorelease];
// Create a new rssParser object based on the TouchXML "CXMLDocument" class, this is the
// object that actually grabs and processes the RSS data
CXMLDocument *rssParser = [[CXMLDocument alloc] initWithData:responseData options:0 error:nil];
//CXMLDocument *rssParser = [[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:nil];
NSLog(#"rssParser %#",rssParser);
//NSLog(#"url %#",url);
// Create a new Array object to be used with the looping of the results from the rssParser
NSArray *resultNodes = NULL;
// Set the resultNodes Array to contain an object for every instance of an node in our RSS feed
resultNodes = [rssParser nodesForXPath:#"//GetImagesResult" error:nil];
// Loop through the resultNodes to access each items actual data
for (CXMLElement *resultElement in resultNodes) {
// Create a temporary MutableDictionary to store the items fields in, which will eventually end up in blogEntries
NSMutableDictionary *blogItem = [[[NSMutableDictionary alloc] init] autorelease];
// Create a counter variable as type "int"
int counter;
// Loop through the children of the current node
for(counter = 0; counter < [resultElement childCount]; counter++) {
//[resultElement initWithXMLString:#""];
NSString *strValue = [[resultElement childAtIndex:counter] stringValue];
//strValue = [strValue stringByReplacingOccurrencesOfString:#"\n" withString:#""];
NSString *strName = [[resultElement childAtIndex:counter] name];
if ([resultNodes containsObject:#""] || resultNodes == nil || resultElement == nil || [resultElement isEqual:#""] || [resultElement children] == nil) {
NSLog(#"Null Object");
}
else {
if (strValue && strName) {
// Add each field to the blogItem Dictionary with the node name as key and node value as the value
[blogItem setObject:[[resultElement childAtIndex:counter] stringValue] forKey:[[resultElement childAtIndex:counter] name]];
}
}
}
// Add the blogItem to the global blogEntries Array so that the view can access it.
[self.rssEntries addObject:[blogItem copy]];
NSLog(#"RSS Entries %#",self.rssEntries);
}
[[rssParser retain] release];
}
Being "unable to parse response" is a very vague description of your problem. However, at first glance I noticed that this XPath query...
resultNodes = [rssParser nodesForXPath:#"//GetImagesResult" error:nil];
...is most likely not matching any elements and thus returning an empty array.
Why? Your XML has a namespace. Use nodesForXPath:namespaceMappings:error: method instead of nodesForXPath:error:. The former has an extra parameter that lets you provide a namespace mapping dictionary. Then edit your XPath query accordingly. See the example below:
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"http://tempuri.org/",
#"tempuri",
nil];
// Set the resultNodes Array to contain an object for every instance of an node in our RSS feed
resultNodes = [rssParser nodesForXPath:#"//tempuri:GetImagesResult" namespaceMappings:dict error:nil];
Also, the last statement of the method is nonsense:
[[rssParser retain] release];
To balance the alloc-init, it should be:
[rssParser release];